This is an automated email from the ASF dual-hosted git repository. ppa pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push: new 6afc371a05 IGNITE-22164 Sql. Fixed conversion from SqlMerge AST to relational expression when columns defined in different order. 6afc371a05 is described below commit 6afc371a05beb8b94ed2171c346142c74e5bcec1 Author: Pavel Pereslegin <xxt...@gmail.com> AuthorDate: Thu May 23 15:27:57 2024 +0300 IGNITE-22164 Sql. Fixed conversion from SqlMerge AST to relational expression when columns defined in different order. --- .../ignite/internal/sql/engine/ItDmlTest.java | 29 ++++++++++++++++++++++ .../engine/prepare/IgniteSqlToRelConvertor.java | 25 ++++++++++++++----- 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItDmlTest.java b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItDmlTest.java index 29d1ed609c..57a7faa4dc 100644 --- a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItDmlTest.java +++ b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItDmlTest.java @@ -251,6 +251,35 @@ public class ItDmlTest extends BaseSqlIntegrationTest { .returns(444, 444, 2, 200, null) .check(); + // ---- all fields covered on NOT MATCHED but columns in different order + clearAndPopulateMergeTable2(); + + sql = "MERGE INTO test2 dst USING test1 src ON dst.a = src.a " + + "WHEN MATCHED THEN UPDATE SET b = src.b, a = src.a " + + "WHEN NOT MATCHED THEN INSERT (k1, k2, c, a, b) VALUES (src.k1, src.k2, src.c, src.a, src.b)"; + + sql(sql); + + assertQuery("SELECT * FROM test2 ORDER BY k1") + .returns(222, 222, 1, 300, "1") + .returns(333, 333, 0, 100, "") + .returns(444, 444, 2, 200, null) + .check(); + + // ---- all fields covered on NOT MATCHED but columns in different order and with filter + clearAndPopulateMergeTable2(); + + sql = "MERGE INTO test2 dst USING (SELECT * FROM test1 WHERE a = 0) src ON dst.a = src.a " + + "WHEN MATCHED THEN UPDATE SET b = src.b, a = src.a " + + "WHEN NOT MATCHED THEN INSERT (k1, k2, c, a, b) VALUES (src.k1, src.k2, src.c, src.a, src.b)"; + + sql(sql); + + assertQuery("SELECT * FROM test2 ORDER BY k1") + .returns(333, 333, 0, 100, "") + .returns(444, 444, 2, 200, null) + .check(); + // --- only WHEN MATCHED section. clearAndPopulateMergeTable2(); diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteSqlToRelConvertor.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteSqlToRelConvertor.java index 74c6f49bc1..2350f6504a 100644 --- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteSqlToRelConvertor.java +++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteSqlToRelConvertor.java @@ -265,14 +265,27 @@ public class IgniteSqlToRelConvertor extends SqlToRelConverter { // provided, in which case, the expression is the default value for // the column; or if the expressions directly map to the source // table - level1InsertExprs = - ((LogicalProject) insertRel.getInput(0)).getProjects(); - if (insertRel.getInput(0).getInput(0) instanceof LogicalProject) { - level2InsertExprs = - ((LogicalProject) insertRel.getInput(0).getInput(0)) - .getProjects(); + RelNode input = insertRel.getInput(0); + + if (input instanceof LogicalProject) { + level1InsertExprs = ((LogicalProject) input).getProjects(); + } else { + // TODO https://issues.apache.org/jira/browse/IGNITE-22293 + // convertInsert() may return LogicalTableModify without projection in the input. + // As a workaround for this case, we additionally build required column expressions. + RelDataType rowType = input.getRowType(); + level1InsertExprs = new ArrayList<>(rowType.getFieldCount()); + int pos = 0; + for (RelDataTypeField type : rowType.getFieldList()) { + level1InsertExprs.add(rexBuilder.makeInputRef(type.getType(), pos++)); + } } + numLevel1Exprs = level1InsertExprs.size(); + + if (!input.getInputs().isEmpty() && input.getInput(0) instanceof LogicalProject) { + level2InsertExprs = ((LogicalProject) input.getInput(0)).getProjects(); + } } LogicalJoin join = (LogicalJoin) mergeSourceRel.getInput(0);