This is an automated email from the ASF dual-hosted git repository. starocean999 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push: new 50a89d5d230 [Enhancement] (nereids)implement showCreateTableCommand in nereids (#43137) 50a89d5d230 is described below commit 50a89d5d2306d0709caefb661e7c3ce501ab6607 Author: Sridhar R Manikarnike <sridhar.n...@gmail.com> AuthorDate: Wed Nov 20 09:50:12 2024 +0530 [Enhancement] (nereids)implement showCreateTableCommand in nereids (#43137) Issue Number: close #42736 implement showCreateTableCommand in nereids --- .../antlr4/org/apache/doris/nereids/DorisParser.g4 | 2 +- .../doris/nereids/parser/LogicalPlanBuilder.java | 8 ++ .../apache/doris/nereids/trees/plans/PlanType.java | 1 + .../plans/commands/ShowCreateTableCommand.java | 152 +++++++++++++++++++++ .../trees/plans/visitor/CommandVisitor.java | 5 + .../show/test_show_create_table_nereids.groovy | 63 +++++++++ 6 files changed, 230 insertions(+), 1 deletion(-) diff --git a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 index 37c9be99177..b18322cc440 100644 --- a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 +++ b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 @@ -207,6 +207,7 @@ supportedShowStatement ((FROM | IN) database=identifier)? #showView | SHOW PLUGINS #showPlugins | SHOW REPOSITORIES #showRepositories + | SHOW BRIEF? CREATE TABLE name=multipartIdentifier #showCreateTable | SHOW ROLES #showRoles | SHOW PARTITION partitionId=INTEGER_VALUE #showPartitionId | SHOW PRIVILEGES #showPrivileges @@ -263,7 +264,6 @@ unsupportedShowStatement | SHOW (GLOBAL | SESSION | LOCAL)? STATUS wildWhere? #showStatus | SHOW FULL? TRIGGERS ((FROM | IN) database=multipartIdentifier)? wildWhere? #showTriggers | SHOW EVENTS ((FROM | IN) database=multipartIdentifier)? wildWhere? #showEvents - | SHOW BRIEF? CREATE TABLE name=multipartIdentifier #showCreateTable | SHOW CREATE VIEW name=multipartIdentifier #showCreateView | SHOW CREATE MATERIALIZED VIEW name=multipartIdentifier #showMaterializedView | SHOW CREATE (DATABASE | SCHEMA) name=multipartIdentifier #showCreateDatabase diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java index 32f85a52a12..491857858b0 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java @@ -202,6 +202,7 @@ import org.apache.doris.nereids.DorisParser.ShowConstraintContext; import org.apache.doris.nereids.DorisParser.ShowCreateMTMVContext; import org.apache.doris.nereids.DorisParser.ShowCreateMaterializedViewContext; import org.apache.doris.nereids.DorisParser.ShowCreateProcedureContext; +import org.apache.doris.nereids.DorisParser.ShowCreateTableContext; import org.apache.doris.nereids.DorisParser.ShowFrontendsContext; import org.apache.doris.nereids.DorisParser.ShowGrantsContext; import org.apache.doris.nereids.DorisParser.ShowGrantsForUserContext; @@ -453,6 +454,7 @@ import org.apache.doris.nereids.trees.plans.commands.ShowConstraintsCommand; import org.apache.doris.nereids.trees.plans.commands.ShowCreateMTMVCommand; import org.apache.doris.nereids.trees.plans.commands.ShowCreateMaterializedViewCommand; import org.apache.doris.nereids.trees.plans.commands.ShowCreateProcedureCommand; +import org.apache.doris.nereids.trees.plans.commands.ShowCreateTableCommand; import org.apache.doris.nereids.trees.plans.commands.ShowFrontendsCommand; import org.apache.doris.nereids.trees.plans.commands.ShowGrantsCommand; import org.apache.doris.nereids.trees.plans.commands.ShowLastInsertCommand; @@ -4176,6 +4178,12 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> { return new ShowStorageEnginesCommand(); } + @Override + public LogicalPlan visitShowCreateTable(ShowCreateTableContext ctx) { + List<String> nameParts = visitMultipartIdentifier(ctx.name); + return new ShowCreateTableCommand(new TableNameInfo(nameParts), ctx.BRIEF() != null); + } + @Override public LogicalPlan visitShowCreateMaterializedView(ShowCreateMaterializedViewContext ctx) { List<String> nameParts = visitMultipartIdentifier(ctx.tableName); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanType.java index 8f68cd7287e..377bd4ce880 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanType.java @@ -181,6 +181,7 @@ public enum PlanType { SHOW_BLOCK_RULE_COMMAND, SHOW_CONFIG_COMMAND, SHOW_CREATE_MATERIALIZED_VIEW_COMMAND, + SHOW_CREATE_TABLE_COMMAND, SHOW_FRONTENDS_COMMAND, SHOW_GRANTS_COMMAND, SHOW_LAST_INSERT_COMMAND, diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowCreateTableCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowCreateTableCommand.java new file mode 100644 index 00000000000..c0aeaad1d5d --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowCreateTableCommand.java @@ -0,0 +1,152 @@ +// 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. + +package org.apache.doris.nereids.trees.plans.commands; + +import org.apache.doris.catalog.Column; +import org.apache.doris.catalog.DatabaseIf; +import org.apache.doris.catalog.Env; +import org.apache.doris.catalog.MTMV; +import org.apache.doris.catalog.ScalarType; +import org.apache.doris.catalog.Table; +import org.apache.doris.catalog.TableIf; +import org.apache.doris.catalog.View; +import org.apache.doris.common.AnalysisException; +import org.apache.doris.common.ErrorCode; +import org.apache.doris.common.ErrorReport; +import org.apache.doris.datasource.hive.HMSExternalTable; +import org.apache.doris.datasource.hive.HiveMetaStoreClientHelper; +import org.apache.doris.mysql.privilege.PrivPredicate; +import org.apache.doris.nereids.trees.plans.PlanType; +import org.apache.doris.nereids.trees.plans.commands.info.TableNameInfo; +import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor; +import org.apache.doris.qe.ConnectContext; +import org.apache.doris.qe.ShowResultSet; +import org.apache.doris.qe.ShowResultSetMetaData; +import org.apache.doris.qe.StmtExecutor; + +import com.google.common.collect.Lists; + +import java.util.Arrays; +import java.util.List; + +/** + * Represents the command for SHOW CREATE TABLE. + */ +public class ShowCreateTableCommand extends ShowCommand { + private static final ShowResultSetMetaData META_DATA = + ShowResultSetMetaData.builder() + .addColumn(new Column("Table", ScalarType.createVarchar(20))) + .addColumn(new Column("Create Table", ScalarType.createVarchar(30))) + .build(); + + private static final ShowResultSetMetaData VIEW_META_DATA = + ShowResultSetMetaData.builder() + .addColumn(new Column("View", ScalarType.createVarchar(20))) + .addColumn(new Column("Create View", ScalarType.createVarchar(30))) + .addColumn(new Column("character_set_client", ScalarType.createVarchar(30))) + .addColumn(new Column("collation_connection", ScalarType.createVarchar(30))) + .build(); + + private static final ShowResultSetMetaData MATERIALIZED_VIEW_META_DATA = + ShowResultSetMetaData.builder() + .addColumn(new Column("Materialized View", ScalarType.createVarchar(20))) + .addColumn(new Column("Create Materialized View", ScalarType.createVarchar(30))) + .build(); + + private final TableNameInfo tblNameInfo; + private final boolean isBrief; + + public ShowCreateTableCommand(TableNameInfo tableNameInfo, boolean isBrief) { + super(PlanType.SHOW_CREATE_TABLE_COMMAND); + this.tblNameInfo = tableNameInfo; + this.isBrief = isBrief; + } + + private void validate(ConnectContext ctx) throws AnalysisException { + tblNameInfo.analyze(ctx); + + TableIf tableIf = Env.getCurrentEnv().getCatalogMgr() + .getCatalogOrAnalysisException(tblNameInfo.getCtl()) + .getDbOrAnalysisException(tblNameInfo.getDb()).getTableOrAnalysisException(tblNameInfo.getTbl()); + + if (tableIf instanceof MTMV) { + ErrorReport.reportAnalysisException("not support async materialized view, " + + "please use `show create materialized view`"); + } + + PrivPredicate wanted; + if (tableIf instanceof View) { + wanted = PrivPredicate.SHOW_VIEW; + } else { + wanted = PrivPredicate.SHOW; + } + + if (!Env.getCurrentEnv().getAccessManager().checkTblPriv(ConnectContext.get(), + tblNameInfo.getCtl(), tblNameInfo.getDb(), tblNameInfo.getTbl(), wanted)) { + ErrorReport.reportAnalysisException(ErrorCode.ERR_TABLEACCESS_DENIED_ERROR, "SHOW CREATE TABLE", + ConnectContext.get().getQualifiedUser(), + ConnectContext.get().getRemoteIP(), + tblNameInfo.getDb() + ": " + tblNameInfo.getTbl()); + } + } + + @Override + public <R, C> R accept(PlanVisitor<R, C> visitor, C context) { + return visitor.visitShowCreateTableCommand(this, context); + } + + @Override + public ShowResultSet doRun(ConnectContext ctx, StmtExecutor executor) throws Exception { + validate(ctx); + + // Fetch the catalog, database, and table metadata + DatabaseIf db = ctx.getEnv().getCatalogMgr().getCatalogOrAnalysisException(tblNameInfo.getCtl()) + .getDbOrMetaException(tblNameInfo.getDb()); + TableIf table = db.getTableOrMetaException(tblNameInfo.getTbl()); + + List<List<String>> rows = Lists.newArrayList(); + + table.readLock(); + try { + if (table.getType() == Table.TableType.HMS_EXTERNAL_TABLE) { + rows.add(Arrays.asList(table.getName(), + HiveMetaStoreClientHelper.showCreateTable(((HMSExternalTable) table).getRemoteTable()))); + return new ShowResultSet(META_DATA, rows); + } + List<String> createTableStmt = Lists.newArrayList(); + Env.getDdlStmt(null, null, table, createTableStmt, null, null, false, + true /* hide password */, false, -1L, isBrief, false); + if (createTableStmt.isEmpty()) { + return new ShowResultSet(META_DATA, rows); + } + + if (table instanceof View) { + rows.add(Lists.newArrayList(table.getName(), createTableStmt.get(0), "utf8mb4", "utf8mb4_0900_bin")); + return new ShowResultSet(VIEW_META_DATA, rows); + } else { + rows.add(Lists.newArrayList(table.getName(), createTableStmt.get(0))); + return (table.getType() != Table.TableType.MATERIALIZED_VIEW + ? new ShowResultSet(META_DATA, rows) + : new ShowResultSet(MATERIALIZED_VIEW_META_DATA, rows)); + } + } finally { + table.readUnlock(); + } + } + +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/CommandVisitor.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/CommandVisitor.java index d80a24cd347..2959f3f8a56 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/CommandVisitor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/CommandVisitor.java @@ -57,6 +57,7 @@ import org.apache.doris.nereids.trees.plans.commands.ShowConstraintsCommand; import org.apache.doris.nereids.trees.plans.commands.ShowCreateMTMVCommand; import org.apache.doris.nereids.trees.plans.commands.ShowCreateMaterializedViewCommand; import org.apache.doris.nereids.trees.plans.commands.ShowCreateProcedureCommand; +import org.apache.doris.nereids.trees.plans.commands.ShowCreateTableCommand; import org.apache.doris.nereids.trees.plans.commands.ShowFrontendsCommand; import org.apache.doris.nereids.trees.plans.commands.ShowGrantsCommand; import org.apache.doris.nereids.trees.plans.commands.ShowLastInsertCommand; @@ -287,6 +288,10 @@ public interface CommandVisitor<R, C> { return visitCommand(showBackendsCommand, context); } + default R visitShowCreateTableCommand(ShowCreateTableCommand showCreateTableCommand, C context) { + return visitCommand(showCreateTableCommand, context); + } + default R visitShowSqlBlockRuleCommand(ShowSqlBlockRuleCommand showblockruleCommand, C context) { return visitCommand(showblockruleCommand, context); } diff --git a/regression-test/suites/nereids_p0/show/test_show_create_table_nereids.groovy b/regression-test/suites/nereids_p0/show/test_show_create_table_nereids.groovy new file mode 100644 index 00000000000..53f2242d1fa --- /dev/null +++ b/regression-test/suites/nereids_p0/show/test_show_create_table_nereids.groovy @@ -0,0 +1,63 @@ +// 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_show_create_table_nereids", "query,arrow_flight_sql") { + String tb_name = "tb_show_create_table"; + try { + sql """drop table if exists ${tb_name} """ + sql """ + CREATE TABLE IF NOT EXISTS ${tb_name}( + datek1 datev2 COMMENT "a", + datetimek1 datetimev2 COMMENT "b", + datetimek2 datetimev2(3) COMMENT "c", + datetimek3 datetimev2(6) COMMENT "d", + datev1 datev2 MAX NOT NULL COMMENT "e", + datetimev1 datetimev2 MAX NOT NULL COMMENT "f", + datetimev2 datetimev2(3) MAX NOT NULL COMMENT "g", + datetimev3 datetimev2(6) MAX NOT NULL COMMENT "h" + ) + AGGREGATE KEY (datek1, datetimek1, datetimek2, datetimek3) + DISTRIBUTED BY HASH(datek1) BUCKETS 5 properties("replication_num" = "1"); + """ + + def res = sql "show create table `${tb_name}`" + assertTrue(res.size() != 0) + + sql """drop table if exists ${tb_name} """ + sql """ + CREATE TABLE IF NOT EXISTS ${tb_name}( + datek1 datev2 COMMENT "a", + datetimek1 datetimev2 COMMENT "b", + datetimek2 datetimev2(3) COMMENT "c", + datetimek3 datetimev2(6) COMMENT "d", + datev1 datev2 NOT NULL COMMENT "e", + datetimev1 datetimev2 NOT NULL COMMENT "f", + datetimev2 datetimev2(3) NOT NULL COMMENT "g", + datetimev3 datetimev2(6) NOT NULL COMMENT "h" + ) + DUPLICATE KEY (datek1, datetimek1, datetimek2, datetimek3) + DISTRIBUTED BY RANDOM BUCKETS 5 properties("replication_num" = "1"); + """ + + checkNereidsExecute("""show create table `${tb_name}`;""") + + } finally { + + try_sql("DROP TABLE IF EXISTS `${tb_name}`") + } + +} --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org