提交 920722fc authored 作者: Owner's avatar Owner

Refined extra error messages

上级 cc1b27b5
...@@ -124,10 +124,10 @@ MERGE INTO TEST KEY(ID) VALUES(2, 'World') ...@@ -124,10 +124,10 @@ MERGE INTO TEST KEY(ID) VALUES(2, 'World')
"Commands (DML)","MERGE USING"," "Commands (DML)","MERGE USING","
MERGE INTO targetTableName [ [AS] targetAlias] MERGE INTO targetTableName [ [AS] targetAlias]
USING { ( select ) | sourceTableName }[ [AS] sourceAlias ] USING { ( select ) | sourceTableName }[ [AS] sourceAlias ]
ON ( expression ) ON ( expression )
[ WHEN MATCHED THEN [ update ] [ delete] ] [ WHEN MATCHED THEN [ update ] [ delete] ]
[ WHEN NOT MATCHED THEN insert ] [ WHEN NOT MATCHED THEN insert ]
"," ","
Updates or deletes existing rows, and insert rows that don't exist. The ON clause Updates or deletes existing rows, and insert rows that don't exist. The ON clause
specifies the matching column expression and must be specified. If more than one row specifies the matching column expression and must be specified. If more than one row
......
...@@ -106,7 +106,7 @@ public class MergeUsing extends Merge { ...@@ -106,7 +106,7 @@ public class MergeUsing extends Merge {
} }
} }
if(sourceKeysRemembered.containsKey(sourceKeyValuesList)){ if(sourceKeysRemembered.containsKey(sourceKeyValuesList)){
throw DbException.get(ErrorCode.DUPLICATE_KEY_1, "Merge using ON column expression, duplicate values found:keys" throw DbException.get(ErrorCode.DUPLICATE_KEY_1, "Merge using ON column expression, duplicate values found:key columns"
+Arrays.asList(sourceKeys).toString()+":values:"+sourceKeyValuesList.toString() +Arrays.asList(sourceKeys).toString()+":values:"+sourceKeyValuesList.toString()
+":from:"+sourceTableFilter.getTable()+":alias:"+sourceTableFilter.getTableAlias()+":current row number:"+countInputRows +":from:"+sourceTableFilter.getTable()+":alias:"+sourceTableFilter.getTableAlias()+":current row number:"+countInputRows
+":conflicting row number:"+sourceKeysRemembered.get(sourceKeyValuesList)); +":conflicting row number:"+sourceKeysRemembered.get(sourceKeyValuesList));
...@@ -174,7 +174,7 @@ public class MergeUsing extends Merge { ...@@ -174,7 +174,7 @@ public class MergeUsing extends Merge {
rowUpdateCount += updateCommand.update(); rowUpdateCount += updateCommand.update();
System.out.println("update.count="+rowUpdateCount); System.out.println("update.count="+rowUpdateCount);
} }
if(deleteCommand!=null && rowUpdateCount==0){ if(deleteCommand!=null){
System.out.println("deleteCommand="+deleteCommand.getPlanSQL()); System.out.println("deleteCommand="+deleteCommand.getPlanSQL());
rowUpdateCount += deleteCommand.update(); rowUpdateCount += deleteCommand.update();
System.out.println("delete.count="+rowUpdateCount); System.out.println("delete.count="+rowUpdateCount);
...@@ -364,11 +364,19 @@ public class MergeUsing extends Merge { ...@@ -364,11 +364,19 @@ public class MergeUsing extends Merge {
if (keys == null) { if (keys == null) {
HashSet<Column> targetColumns = buildColumnListFromOnCondition(targetTableFilter); HashSet<Column> targetColumns = buildColumnListFromOnCondition(targetTableFilter);
keys = targetColumns.toArray(new Column[1]); keys = targetColumns.toArray(new Column[0]);
System.out.println("keys.length="+keys.length);
}
if(keys.length==0){
throw DbException.get(ErrorCode.COLUMN_NOT_FOUND_1,"No references to target columns found in ON clause:"+targetTableFilter.toString());
} }
if (sourceKeys == null) { if (sourceKeys == null) {
HashSet<Column> sourceColumns = buildColumnListFromOnCondition(sourceTableFilter); HashSet<Column> sourceColumns = buildColumnListFromOnCondition(sourceTableFilter);
sourceKeys = sourceColumns.toArray(new Column[1]); sourceKeys = sourceColumns.toArray(new Column[0]);
System.out.println("sourceKeys.length="+sourceKeys.length);
}
if(sourceKeys.length==0){
throw DbException.get(ErrorCode.COLUMN_NOT_FOUND_1,"No references to source columns found in ON clause:"+sourceTableFilter.toString());
} }
// only do the optimise now - before we have already gathered the unoptimized column data // only do the optimise now - before we have already gathered the unoptimized column data
...@@ -434,21 +442,19 @@ public class MergeUsing extends Merge { ...@@ -434,21 +442,19 @@ public class MergeUsing extends Merge {
} }
private HashSet<Column> buildColumnListFromOnCondition(TableFilter targetTableFilter) { private HashSet<Column> buildColumnListFromOnCondition(TableFilter anyTableFilter) {
HashSet<Column> targetColumns = new HashSet<Column>(); HashSet<Column> filteredColumns = new HashSet<Column>();
HashSet<Column> columns = new HashSet<Column>(); HashSet<Column> columns = new HashSet<Column>();
ExpressionVisitor visitor = ExpressionVisitor.getColumnsVisitor(columns); ExpressionVisitor visitor = ExpressionVisitor.getColumnsVisitor(columns);
onCondition.isEverything(visitor); onCondition.isEverything(visitor);
for(Column c: columns){ for(Column c: columns){
if(c.getTable()==targetTableFilter.getTable()){ System.out.println("C="+c);
targetColumns.add(c); if(c!=null && c.getTable()==anyTableFilter.getTable()){
} filteredColumns.add(c);
} }
System.out.println("columnsVisitedForTable"+targetTableFilter.getTable()+"="+targetColumns);
if (targetColumns.isEmpty()) {
throw DbException.get(ErrorCode.CONSTRAINT_NOT_FOUND_1, "ON (condition) target columns missing");
} }
return targetColumns; System.out.println("columnsVisitedForTable"+anyTableFilter.getTable()+"="+filteredColumns);
return filteredColumns;
} }
private Expression appendOnCondition(Update updateCommand) { private Expression appendOnCondition(Update updateCommand) {
......
...@@ -123,7 +123,7 @@ public class TestMergeUsing extends TestBase { ...@@ -123,7 +123,7 @@ public class TestMergeUsing extends TestBase {
GATHER_ORDERED_RESULTS_SQL, GATHER_ORDERED_RESULTS_SQL,
"SELECT 1 AS ID, 'Marcy'||X||X AS NAME FROM SYSTEM_RANGE(1,1)", "SELECT 1 AS ID, 'Marcy'||X||X AS NAME FROM SYSTEM_RANGE(1,1)",
3, 3,
"Unique index or primary key violation: \"Merge using ON column expression, duplicate values found:keys[ID]:values:[1]:from:PUBLIC.SOURCE:alias:SOURCE:current row number:2:conflicting row number:1" "Unique index or primary key violation: \"Merge using ON column expression, duplicate values found:key columns[ID]:values:[1]:from:PUBLIC.SOURCE:alias:SOURCE:current row number:2:conflicting row number:1"
); );
// Duplicate key updated 3 rows at once, only 1 expected // Duplicate key updated 3 rows at once, only 1 expected
...@@ -136,6 +136,26 @@ public class TestMergeUsing extends TestBase { ...@@ -136,6 +136,26 @@ public class TestMergeUsing extends TestBase {
3, 3,
"Duplicate key updated 3 rows at once, only 1 expected" "Duplicate key updated 3 rows at once, only 1 expected"
); );
// Missing target columns in ON expression
testMergeUsingException(
"CREATE TABLE PARENT AS (SELECT 1 AS ID, 'Marcy'||X AS NAME FROM SYSTEM_RANGE(1,3) );"+
"CREATE TABLE SOURCE AS (SELECT X AS ID, 'Marcy'||X AS NAME FROM SYSTEM_RANGE(1,3) );",
"MERGE INTO PARENT USING SOURCE ON (1 = 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 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,
"No references to target columns found in ON clause"
);
// Missing source columns in ON expression
testMergeUsingException(
"CREATE TABLE PARENT AS (SELECT 1 AS ID, 'Marcy'||X AS NAME FROM SYSTEM_RANGE(1,3) );"+
"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 = 1) 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 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,
"No references to source columns found in ON clause"
);
} }
/** /**
...@@ -192,6 +212,7 @@ public class TestMergeUsing extends TestBase { ...@@ -192,6 +212,7 @@ public class TestMergeUsing extends TestBase {
* @param gatherResultsSQL - a select which gathers the results of the merge from the target table * @param gatherResultsSQL - a select which gathers the results of the merge from the target table
* @param expectedResultsSQL - a select which returns the expected results in the target table * @param expectedResultsSQL - a select which returns the expected results in the target table
* @param expectedRowUpdateCount - how many updates should be expected from the merge using * @param expectedRowUpdateCount - how many updates should be expected from the merge using
* @param exceptionMessage - the exception message expected
* @throws Exception * @throws Exception
*/ */
private void testMergeUsingException(String setupSQL, String statementUnderTest, String gatherResultsSQL, private void testMergeUsingException(String setupSQL, String statementUnderTest, String gatherResultsSQL,
...@@ -201,6 +222,9 @@ public class TestMergeUsing extends TestBase { ...@@ -201,6 +222,9 @@ public class TestMergeUsing extends TestBase {
expectedResultsSQL, expectedRowUpdateCount); expectedResultsSQL, expectedRowUpdateCount);
} }
catch(RuntimeException|org.h2.jdbc.JdbcSQLException e){ catch(RuntimeException|org.h2.jdbc.JdbcSQLException e){
if(!e.getMessage().contains(exceptionMessage)){
e.printStackTrace();
}
assertContains(e.getMessage(),exceptionMessage); assertContains(e.getMessage(),exceptionMessage);
return; return;
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论