From 86ccbff65419791f5df0618da2f6aa380a2f717e Mon Sep 17 00:00:00 2001 From: feiniaofeiafei <53502832+feiniaofeiafei@users.noreply.github.com> Date: Fri, 9 Aug 2024 10:39:27 +0800 Subject: [PATCH] [Fix](nereids) fix bind expression compare dbname ignore cluster (#39114) This pr is similar with #23008, ignoring cluster_name in binding when compare dbname. e.g. in this sql, the "dbname" should be viewed same db when comparing with "default_cluster:dbname" ```sql select dbname.test_db_name_ignore_cluster.a from `default_cluster:dbname`.test_db_name_ignore_cluster; ``` --- .../rules/analysis/ExpressionAnalyzer.java | 28 ++++++++++--- .../trees/plans/commands/UpdateCommand.java | 3 +- .../bind_dbname_ignore_cluster.out | 4 ++ .../bind_dbname_ignore_cluster.groovy | 41 +++++++++++++++++++ 4 files changed, 70 insertions(+), 6 deletions(-) create mode 100644 regression-test/data/nereids_rules_p0/bindExpression/bind_dbname_ignore_cluster.out create mode 100644 regression-test/suites/nereids_rules_p0/bindExpression/bind_dbname_ignore_cluster.groovy diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ExpressionAnalyzer.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ExpressionAnalyzer.java index 6dd0963b2fa5f2..afec568545bc0f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ExpressionAnalyzer.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ExpressionAnalyzer.java @@ -674,10 +674,10 @@ private BoundStar bindQualifiedStar(List qualifierStar, List bound case 1: // bound slot is `table`.`column` return false; case 2:// bound slot is `db`.`table`.`column` - return compareDbName(qualifierStar.get(0), boundSlotQualifier.get(0)) + return compareDbNameIgnoreClusterName(qualifierStar.get(0), boundSlotQualifier.get(0)) && qualifierStar.get(1).equalsIgnoreCase(boundSlotQualifier.get(1)); case 3:// bound slot is `catalog`.`db`.`table`.`column` - return compareDbName(qualifierStar.get(0), boundSlotQualifier.get(1)) + return compareDbNameIgnoreClusterName(qualifierStar.get(0), boundSlotQualifier.get(1)) && qualifierStar.get(1).equalsIgnoreCase(boundSlotQualifier.get(2)); default: throw new AnalysisException("Not supported qualifier: " @@ -693,7 +693,7 @@ private BoundStar bindQualifiedStar(List qualifierStar, List bound return false; case 3:// bound slot is `catalog`.`db`.`table`.`column` return qualifierStar.get(0).equalsIgnoreCase(boundSlotQualifier.get(0)) - && compareDbName(qualifierStar.get(1), boundSlotQualifier.get(1)) + && compareDbNameIgnoreClusterName(qualifierStar.get(1), boundSlotQualifier.get(1)) && qualifierStar.get(2).equalsIgnoreCase(boundSlotQualifier.get(2)); default: throw new AnalysisException("Not supported qualifier: " @@ -861,7 +861,7 @@ private List bindSingleSlotByDb(String db, String table, String name, Scop List boundSlotQualifier = boundSlot.getQualifier(); String boundSlotDb = boundSlotQualifier.get(boundSlotQualifier.size() - 2); String boundSlotTable = boundSlotQualifier.get(boundSlotQualifier.size() - 1); - if (!compareDbName(boundSlotDb, db) || !sameTableName(boundSlotTable, table)) { + if (!compareDbNameIgnoreClusterName(boundSlotDb, db) || !sameTableName(boundSlotTable, table)) { continue; } // set sql case as alias @@ -882,7 +882,7 @@ private List bindSingleSlotByCatalog(String catalog, String db, String tab String boundSlotDb = boundSlotQualifier.get(boundSlotQualifier.size() - 2); String boundSlotTable = boundSlotQualifier.get(boundSlotQualifier.size() - 1); if (!boundSlotCatalog.equalsIgnoreCase(catalog) - || !compareDbName(boundSlotDb, db) + || !compareDbNameIgnoreClusterName(boundSlotDb, db) || !sameTableName(boundSlotTable, table)) { continue; } @@ -891,4 +891,22 @@ private List bindSingleSlotByCatalog(String catalog, String db, String tab } return usedSlots.build(); } + + /**compareDbNameIgnoreClusterName.*/ + public static boolean compareDbNameIgnoreClusterName(String name1, String name2) { + if (name1.equalsIgnoreCase(name2)) { + return true; + } + String ignoreClusterName1 = name1; + int idx1 = name1.indexOf(":"); + if (idx1 > -1) { + ignoreClusterName1 = name1.substring(idx1 + 1); + } + String ignoreClusterName2 = name2; + int idx2 = name2.indexOf(":"); + if (idx2 > -1) { + ignoreClusterName2 = name2.substring(idx2 + 1); + } + return ignoreClusterName1.equalsIgnoreCase(ignoreClusterName2); + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/UpdateCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/UpdateCommand.java index 444bc8aa309755..19379dc56b85af 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/UpdateCommand.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/UpdateCommand.java @@ -214,7 +214,8 @@ private void checkAssignmentColumn(ConnectContext ctx, List columnNamePa } List tableQualifier = RelationUtil.getQualifierName(ctx, nameParts); if (!ExpressionAnalyzer.sameTableName(tableAlias == null ? tableQualifier.get(2) : tableAlias, tableName) - || (dbName != null && ExpressionAnalyzer.compareDbName(tableQualifier.get(1), dbName))) { + || (dbName != null + && !ExpressionAnalyzer.compareDbNameIgnoreClusterName(tableQualifier.get(1), dbName))) { throw new AnalysisException("column in assignment list is invalid, " + String.join(".", columnNameParts)); } } diff --git a/regression-test/data/nereids_rules_p0/bindExpression/bind_dbname_ignore_cluster.out b/regression-test/data/nereids_rules_p0/bindExpression/bind_dbname_ignore_cluster.out new file mode 100644 index 00000000000000..b07b84f44a3967 --- /dev/null +++ b/regression-test/data/nereids_rules_p0/bindExpression/bind_dbname_ignore_cluster.out @@ -0,0 +1,4 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !test_update -- +2 10 + diff --git a/regression-test/suites/nereids_rules_p0/bindExpression/bind_dbname_ignore_cluster.groovy b/regression-test/suites/nereids_rules_p0/bindExpression/bind_dbname_ignore_cluster.groovy new file mode 100644 index 00000000000000..a17d1742133a08 --- /dev/null +++ b/regression-test/suites/nereids_rules_p0/bindExpression/bind_dbname_ignore_cluster.groovy @@ -0,0 +1,41 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +suite("test_db_name_ignore_cluster") { + String db = context.config.getDbNameByFile(new File(context.file.parent)) + sql 'set enable_nereids_planner=true' + sql 'set enable_nereids_distribute_planner=false' + sql "use ${db}" + sql "drop table if exists ${db}.test_db_name_ignore_cluster" + sql """create table ${db}.test_db_name_ignore_cluster(a int, b int) unique key(a) distributed by hash(a) + properties("replication_num"="1");""" + sql "select ${db}.test_db_name_ignore_cluster.a from `default_cluster:${db}`.test_db_name_ignore_cluster;" + sql "select ${db}.test_db_name_ignore_cluster.* from `default_cluster:${db}`.test_db_name_ignore_cluster;" + + sql "select `default_cluster:${db}`.test_db_name_ignore_cluster.a from `${db}`.test_db_name_ignore_cluster;" + sql "select `default_cluster:${db}`.test_db_name_ignore_cluster.* from `${db}`.test_db_name_ignore_cluster;" + + sql "select `default_cluster:${db}`.test_db_name_ignore_cluster.a from `default_cluster:${db}`.test_db_name_ignore_cluster;" + sql "select `default_cluster:${db}`.test_db_name_ignore_cluster.* from `default_cluster:${db}`.test_db_name_ignore_cluster;" + + sql "select internal.`${db}`.test_db_name_ignore_cluster.a from internal.`default_cluster:${db}`.test_db_name_ignore_cluster;" + sql "select internal.`default_cluster:${db}`.test_db_name_ignore_cluster.* from internal.`${db}`.test_db_name_ignore_cluster;" + + sql "insert into ${db}.test_db_name_ignore_cluster values(2,4)" + sql "update `default_cluster:${db}`.test_db_name_ignore_cluster set `${db}`.test_db_name_ignore_cluster.b=10;" + sql "update `${db}`.test_db_name_ignore_cluster set `${db}`.test_db_name_ignore_cluster.b=10;" + qt_test_update "select * from ${db}.test_db_name_ignore_cluster" +} \ No newline at end of file