From 597d3cefeed7253bbb77b5b78b4f4eea866daf98 Mon Sep 17 00:00:00 2001 From: xiedeyantu Date: Fri, 7 Mar 2025 21:56:54 +0800 Subject: [PATCH 1/5] refactor show table command --- .../plans/commands/ShowTableCommand.java | 62 +++------------ .../trees/plans/commands/info/AliasInfo.java | 75 +++++++++++++++++++ .../org/apache/doris/nereids/util/Utils.java | 42 +++++++++++ 3 files changed, 128 insertions(+), 51 deletions(-) create mode 100644 fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/AliasInfo.java diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowTableCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowTableCommand.java index ab9e970c8eddf4..c25ae0288b1966 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowTableCommand.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowTableCommand.java @@ -30,21 +30,20 @@ import org.apache.doris.common.ErrorCode; import org.apache.doris.common.ErrorReport; import org.apache.doris.common.FeConstants; -import org.apache.doris.common.Pair; import org.apache.doris.common.PatternMatcher; import org.apache.doris.common.PatternMatcherWrapper; import org.apache.doris.mysql.privilege.PrivPredicate; -import org.apache.doris.nereids.glue.LogicalPlanAdapter; -import org.apache.doris.nereids.parser.NereidsParser; import org.apache.doris.nereids.trees.plans.PlanType; +import org.apache.doris.nereids.trees.plans.commands.info.AliasInfo; +import org.apache.doris.nereids.trees.plans.commands.info.TableNameInfo; import org.apache.doris.nereids.trees.plans.logical.LogicalPlan; import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor; +import org.apache.doris.nereids.util.Utils; import org.apache.doris.qe.ConnectContext; import org.apache.doris.qe.GlobalVariable; import org.apache.doris.qe.ShowResultSet; import org.apache.doris.qe.ShowResultSetMetaData; import org.apache.doris.qe.StmtExecutor; -import org.apache.doris.statistics.ResultRow; import com.google.common.base.Strings; import com.google.common.collect.Lists; @@ -52,7 +51,6 @@ import java.util.ArrayList; import java.util.Comparator; import java.util.List; -import java.util.stream.Collectors; /** * ShowTableCommand @@ -107,39 +105,8 @@ public void validate(ConnectContext ctx) throws AnalysisException { } /** - * sql to logical plan - * @param sql sql + * isShowTablesCaseSensitive */ - private LogicalPlan toLogicalPlan(String sql) { - return new NereidsParser().parseSingle(sql); - } - - /** - * Construct a basic SQL without query conditions - * @param columns (original name, alias) - * @param tableName ctl.db.tbl - */ - private String toBaseSql(List> columns, String tableName) throws AnalysisException { - if (columns == null || columns.isEmpty()) { - throw new AnalysisException("columns cannot be empty"); - } - if (tableName == null || tableName.isEmpty()) { - throw new AnalysisException("tableName cannot be empty"); - } - - StringBuilder sb = new StringBuilder("SELECT "); - columns.forEach(column -> { - sb.append(column.first); - if (column.second != null && !column.second.isEmpty()) { - sb.append(" AS ").append(column.second); - } - sb.append(", "); - }); - sb.setLength(sb.length() - 2); - sb.append(" FROM ").append(tableName); - return sb.toString(); - } - public boolean isShowTablesCaseSensitive() { if (GlobalVariable.lowerCaseTableNames == 0) { return CaseSensibility.TABLE.getCaseSensibility(); @@ -149,27 +116,20 @@ public boolean isShowTablesCaseSensitive() { private ShowResultSet executeWhere(ConnectContext ctx, StmtExecutor executor) throws AnalysisException { - List> columns = new ArrayList<>(); - columns.add(Pair.of("`TABLE_NAME`", + List selectList = new ArrayList<>(); + selectList.add(AliasInfo.of("TABLE_NAME", NAME_COL_PREFIX + ClusterNamespace.getNameFromFullName(db))); if (isVerbose) { - columns.add(Pair.of("`TABLE_TYPE`", TYPE_COL)); + selectList.add(AliasInfo.of("TABLE_TYPE", TYPE_COL)); } - String fullTblName = String.format("`%s`.`%s`.`%s`", - catalog, - InfoSchemaDb.DATABASE_NAME, - "tables"); + TableNameInfo fullTblName = new TableNameInfo(catalog, InfoSchemaDb.DATABASE_NAME, "tables"); // We need to use TABLE_SCHEMA as a condition to query When querying external catalogs. // This also applies to the internal catalog. - LogicalPlan plan = toLogicalPlan(toBaseSql(columns, fullTblName) + " " + whereClause - + " and `TABLE_SCHEMA` = '" + db + "'"); - LogicalPlanAdapter adapter = new LogicalPlanAdapter(plan, ctx.getStatementContext()); - executor.setParsedStmt(adapter); - List resultRows = executor.executeInternalQuery(); - List> rows = resultRows.stream() - .map(ResultRow::getValues).collect(Collectors.toList()); + LogicalPlan plan = Utils.buildLogicalPlan(selectList, fullTblName, + whereClause + " and `TABLE_SCHEMA` = '" + db + "'"); + List> rows = Utils.executePlan(ctx, executor, plan); return new ShowResultSet(getMetaData(), rows); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/AliasInfo.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/AliasInfo.java new file mode 100644 index 00000000000000..c7cd76d75d86b1 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/AliasInfo.java @@ -0,0 +1,75 @@ +// 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. +// This file is copied from +// https://github.com/apache/impala/blob/branch-2.9.0/fe/src/main/java/org/apache/impala/TableName.java +// and modified by Doris + +package org.apache.doris.nereids.trees.plans.commands.info; + +import org.apache.doris.analysis.TableName; +import org.apache.doris.catalog.Env; +import org.apache.doris.common.io.Text; +import org.apache.doris.common.io.Writable; +import org.apache.doris.datasource.InternalCatalog; +import org.apache.doris.nereids.exceptions.AnalysisException; +import org.apache.doris.persist.gson.GsonUtils; +import org.apache.doris.qe.ConnectContext; + +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; +import com.google.gson.annotations.SerializedName; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; +import java.util.List; +import java.util.Objects; +import java.util.stream.Stream; + +/** + * alias info + */ +public class AliasInfo { + private final String name; + private final String alias; + + public AliasInfo(String name, String alias) { + this.name = Objects.requireNonNull(name); + this.alias = alias; + } + + public static AliasInfo of(String name, String alias) { + return new AliasInfo(name, alias); + } + + public String getName() { + return name; + } + + public String getAlias() { + return alias; + } + + @Override + public String toString() { + return alias == null || alias.isEmpty() + ? String.format("`%s`", name) + : String.format("`%s` AS `%s`", name, alias); + } + + +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/Utils.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/Utils.java index c111839fc5093e..4f304335c2aea3 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/Utils.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/Utils.java @@ -18,12 +18,20 @@ package org.apache.doris.nereids.util; import org.apache.doris.nereids.exceptions.AnalysisException; +import org.apache.doris.nereids.glue.LogicalPlanAdapter; +import org.apache.doris.nereids.parser.NereidsParser; import org.apache.doris.nereids.trees.expressions.Cast; import org.apache.doris.nereids.trees.expressions.Expression; import org.apache.doris.nereids.trees.expressions.Not; import org.apache.doris.nereids.trees.expressions.Slot; import org.apache.doris.nereids.trees.expressions.SlotReference; import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; +import org.apache.doris.nereids.trees.plans.commands.info.AliasInfo; +import org.apache.doris.nereids.trees.plans.commands.info.TableNameInfo; +import org.apache.doris.nereids.trees.plans.logical.LogicalPlan; +import org.apache.doris.qe.ConnectContext; +import org.apache.doris.qe.StmtExecutor; +import org.apache.doris.statistics.ResultRow; import com.google.common.base.CaseFormat; import com.google.common.base.Preconditions; @@ -40,6 +48,7 @@ import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.StringJoiner; import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Predicate; @@ -589,4 +598,37 @@ public static String addLinePrefix(String str, String prefix) { } return newStr.toString(); } + + /** + * Builds a logical plan for a SQL query. + * + * @param selectList the list of columns and their aliases to be selected + * @param tableName the name of the table from which to select + * @param whereClause the where clause to filter the results + * @return the logical plan representing the SQL query + */ + public static LogicalPlan buildLogicalPlan(List selectList, TableNameInfo tableName, + String whereClause) { + StringJoiner columnJoiner = new StringJoiner(", "); + for (AliasInfo aliasInfo : selectList) { + columnJoiner.add(aliasInfo.toString()); + } + String sql = "SELECT " + columnJoiner.toString() + " FROM " + tableName; + return new NereidsParser().parseSingle(sql); + } + + /** + * Execute a logical plan and return the results. + * + * @param ctx the context in which to execute the plan + * @param executor the executor to use to execute the plan + * @param plan the plan to execute + * @return the results of executing the plan + */ + public static List> executePlan(ConnectContext ctx, StmtExecutor executor, LogicalPlan plan) { + LogicalPlanAdapter adapter = new LogicalPlanAdapter(plan, ctx.getStatementContext()); + executor.setParsedStmt(adapter); + List resultRows = executor.executeInternalQuery(); + return resultRows.stream().map(ResultRow::getValues).collect(Collectors.toList()); + } } From adccaa5e7cf55c5785c3d2a555b84ee5e20cfd65 Mon Sep 17 00:00:00 2001 From: xiedeyantu Date: Sat, 8 Mar 2025 08:52:19 +0800 Subject: [PATCH 2/5] fix --- .../trees/plans/commands/info/AliasInfo.java | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/AliasInfo.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/AliasInfo.java index c7cd76d75d86b1..7191ccbc6bc01d 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/AliasInfo.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/AliasInfo.java @@ -20,25 +20,7 @@ package org.apache.doris.nereids.trees.plans.commands.info; -import org.apache.doris.analysis.TableName; -import org.apache.doris.catalog.Env; -import org.apache.doris.common.io.Text; -import org.apache.doris.common.io.Writable; -import org.apache.doris.datasource.InternalCatalog; -import org.apache.doris.nereids.exceptions.AnalysisException; -import org.apache.doris.persist.gson.GsonUtils; -import org.apache.doris.qe.ConnectContext; - -import com.google.common.base.Preconditions; -import com.google.common.base.Strings; -import com.google.gson.annotations.SerializedName; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.util.List; import java.util.Objects; -import java.util.stream.Stream; /** * alias info @@ -70,6 +52,4 @@ public String toString() { ? String.format("`%s`", name) : String.format("`%s` AS `%s`", name, alias); } - - } From 2ca0471d993ca1fb7623602c4bb13f1e35cb3d04 Mon Sep 17 00:00:00 2001 From: xiedeyantu Date: Sun, 9 Mar 2025 15:10:20 +0800 Subject: [PATCH 3/5] fix --- .../src/main/java/org/apache/doris/nereids/util/Utils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/Utils.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/Utils.java index 4f304335c2aea3..1635e78c110c99 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/Utils.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/Utils.java @@ -613,7 +613,7 @@ public static LogicalPlan buildLogicalPlan(List selectList, TableName for (AliasInfo aliasInfo : selectList) { columnJoiner.add(aliasInfo.toString()); } - String sql = "SELECT " + columnJoiner.toString() + " FROM " + tableName; + String sql = "SELECT " + columnJoiner.toString() + " FROM " + tableName.toSql(); return new NereidsParser().parseSingle(sql); } From 21baa18a2b21a13e3fcff9ac4a3f37e9a65a2fd0 Mon Sep 17 00:00:00 2001 From: xiedeyantu Date: Sun, 9 Mar 2025 16:45:35 +0800 Subject: [PATCH 4/5] fix --- .../src/main/java/org/apache/doris/nereids/util/Utils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/Utils.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/Utils.java index 1635e78c110c99..6af849f1191630 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/Utils.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/Utils.java @@ -613,7 +613,7 @@ public static LogicalPlan buildLogicalPlan(List selectList, TableName for (AliasInfo aliasInfo : selectList) { columnJoiner.add(aliasInfo.toString()); } - String sql = "SELECT " + columnJoiner.toString() + " FROM " + tableName.toSql(); + String sql = "SELECT " + columnJoiner.toString() + " FROM " + tableName.toSql() + " " + whereClause; return new NereidsParser().parseSingle(sql); } From 3cc41e0e4964bd10405ec2924b36a2cb7343f4da Mon Sep 17 00:00:00 2001 From: xiedeyantu Date: Sun, 9 Mar 2025 19:49:40 +0800 Subject: [PATCH 5/5] fix --- .../trees/plans/commands/info/TableNameInfo.java | 15 +++++++++++++++ .../java/org/apache/doris/nereids/util/Utils.java | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/TableNameInfo.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/TableNameInfo.java index 8afe1e186a81e5..d184c330116e8a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/TableNameInfo.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/TableNameInfo.java @@ -233,4 +233,19 @@ public String toSql() { stringBuilder.append("`").append(tbl).append("`"); return stringBuilder.toString(); } + + /** + * toFullyQualified + */ + public String toFullyQualified() { + StringBuilder stringBuilder = new StringBuilder(); + if (ctl != null) { + stringBuilder.append("`").append(ctl).append("`."); + } + if (db != null) { + stringBuilder.append("`").append(db).append("`."); + } + stringBuilder.append("`").append(tbl).append("`"); + return stringBuilder.toString(); + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/Utils.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/Utils.java index 6af849f1191630..507eef6d7bdd10 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/Utils.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/Utils.java @@ -613,7 +613,7 @@ public static LogicalPlan buildLogicalPlan(List selectList, TableName for (AliasInfo aliasInfo : selectList) { columnJoiner.add(aliasInfo.toString()); } - String sql = "SELECT " + columnJoiner.toString() + " FROM " + tableName.toSql() + " " + whereClause; + String sql = "SELECT " + columnJoiner.toString() + " FROM " + tableName.toFullyQualified() + " " + whereClause; return new NereidsParser().parseSingle(sql); }