Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Enhancement] (nereids)implement showCreateViewCommand in nereids #43145

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ supportedShowStatement
| SHOW STORAGE? ENGINES #showStorageEngines
| SHOW CREATE CATALOG name=identifier #showCreateCatalog
| SHOW SQL_BLOCK_RULE (FOR ruleName=identifier)? #showSqlBlockRule
| SHOW CREATE VIEW name=multipartIdentifier #showCreateView
| SHOW CREATE MATERIALIZED VIEW mvName=identifier
ON tableName=multipartIdentifier #showCreateMaterializedView
| SHOW BACKENDS #showBackends
Expand Down Expand Up @@ -285,7 +286,6 @@ unsupportedShowStatement
| SHOW FULL? PROCESSLIST #showProcessList
| SHOW (GLOBAL | SESSION | LOCAL)? STATUS wildWhere? #showStatus
| SHOW EVENTS ((FROM | IN) database=multipartIdentifier)? wildWhere? #showEvents
| SHOW CREATE VIEW name=multipartIdentifier #showCreateView
| SHOW CREATE MATERIALIZED VIEW name=multipartIdentifier #showMaterializedView
| SHOW CREATE (DATABASE | SCHEMA) name=multipartIdentifier #showCreateDatabase
| SHOW CREATE (GLOBAL | SESSION | LOCAL)? FUNCTION functionIdentifier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@
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.ShowCreateViewContext;
import org.apache.doris.nereids.DorisParser.ShowDeleteContext;
import org.apache.doris.nereids.DorisParser.ShowDynamicPartitionContext;
import org.apache.doris.nereids.DorisParser.ShowFrontendsContext;
Expand Down Expand Up @@ -487,6 +488,7 @@
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.ShowCreateViewCommand;
import org.apache.doris.nereids.trees.plans.commands.ShowDeleteCommand;
import org.apache.doris.nereids.trees.plans.commands.ShowDynamicPartitionCommand;
import org.apache.doris.nereids.trees.plans.commands.ShowFrontendsCommand;
Expand Down Expand Up @@ -4297,6 +4299,12 @@ public LogicalPlan visitShowCreateTable(ShowCreateTableContext ctx) {
return new ShowCreateTableCommand(new TableNameInfo(nameParts), ctx.BRIEF() != null);
}

@Override
public LogicalPlan visitShowCreateView(ShowCreateViewContext ctx) {
List<String> nameParts = visitMultipartIdentifier(ctx.name);
return new ShowCreateViewCommand(new TableNameInfo(nameParts));
}

@Override
public LogicalPlan visitShowCreateMaterializedView(ShowCreateMaterializedViewContext ctx) {
List<String> nameParts = visitMultipartIdentifier(ctx.tableName);
Expand Down Expand Up @@ -4369,6 +4377,7 @@ public RecoverPartitionCommand visitRecoverPartition(RecoverPartitionContext ctx
}

@Override

public LogicalPlan visitShowBroker(ShowBrokerContext ctx) {
return new ShowBrokerCommand();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ public enum PlanType {
SHOW_CREATE_CATALOG_COMMAND,
SHOW_CREATE_MATERIALIZED_VIEW_COMMAND,
SHOW_CREATE_TABLE_COMMAND,
SHOW_CREATE_VIEW_COMMAND,
SHOW_DELETE_COMMAND,
SHOW_DYNAMIC_PARTITION_COMMAND,
SHOW_FRONTENDS_COMMAND,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// 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.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.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.List;

/**
* Represents the command for SHOW CREATE VIEW.
*/
public class ShowCreateViewCommand extends ShowCommand {
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 final TableNameInfo tblNameInfo;

public ShowCreateViewCommand(TableNameInfo tableNameInfo) {
super(PlanType.SHOW_CREATE_VIEW_COMMAND);
this.tblNameInfo = tableNameInfo;
}

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.visitShowCreateViewCommand(this, context);
}

@Override
public ShowResultSet doRun(ConnectContext ctx, StmtExecutor executor) throws Exception {
validate(ctx);
// Fetch the catalog, database, and view metadata
DatabaseIf db = ctx.getEnv().getCatalogMgr().getCatalogOrAnalysisException(tblNameInfo.getCtl())
.getDbOrMetaException(tblNameInfo.getDb());
TableIf view = db.getTableOrMetaException(tblNameInfo.getTbl());

if (!(view instanceof View)) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_WRONG_OBJECT, tblNameInfo.getDb(), tblNameInfo.getTbl(),
"VIEW", "Use 'SHOW CREATE TABLE '" + tblNameInfo.getTbl());
}

List<List<String>> rows = Lists.newArrayList();
// Lock the view to ensure consistent metadata access
view.readLock();
try {
List<String> createViewStmt = Lists.newArrayList();
ctx.getEnv().getDdlStmt(null, null, view, createViewStmt, null, null, false, true,
false, -1L, false, false);

if (!createViewStmt.isEmpty()) {
rows.add(Lists.newArrayList(view.getName(), createViewStmt.get(0), "utf8mb4", "utf8mb4_0900_bin"));
}
} finally {
view.readUnlock();
}

// Set the result set and send it using the executor
return new ShowResultSet(VIEW_META_DATA, rows);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
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.ShowCreateViewCommand;
import org.apache.doris.nereids.trees.plans.commands.ShowDeleteCommand;
import org.apache.doris.nereids.trees.plans.commands.ShowDynamicPartitionCommand;
import org.apache.doris.nereids.trees.plans.commands.ShowFrontendsCommand;
Expand Down Expand Up @@ -375,6 +376,10 @@ default R visitShowCreateMaterializedViewCommand(ShowCreateMaterializedViewComma
return visitCommand(showCreateMtlzViewCommand, context);
}

default R visitShowCreateViewCommand(ShowCreateViewCommand showCreateViewCommand, C context) {
return visitCommand(showCreateViewCommand, context);
}

default R visitAlterRoleCommand(AlterRoleCommand alterRoleCommand, C context) {
return visitCommand(alterRoleCommand, context);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
-- This file is automatically generated. You should know what you did if you want to edit this
-- !cmd --
view_show_create_view CREATE VIEW `view_show_create_view` AS SELECT `internal`.`regression_test_nereids_p0_show`.`table_for_view_test`.`id`, `internal`.`regression_test_nereids_p0_show`.`table_for_view_test`.`name` FROM `internal`.`regression_test_nereids_p0_show`.`table_for_view_test`; utf8mb4 utf8mb4_0900_bin

-- !cmd --
view_show_create_view_2 CREATE VIEW `view_show_create_view_2` AS SELECT `internal`.`regression_test_nereids_p0_show`.`table_for_view_test_2`.`key_field`, `internal`.`regression_test_nereids_p0_show`.`table_for_view_test_2`.`value` FROM `internal`.`regression_test_nereids_p0_show`.`table_for_view_test_2`; utf8mb4 utf8mb4_0900_bin

Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// 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_view", "query,arrow_flight_sql") {
String view_name = "view_show_create_view";
String table_name = "table_for_view_test";
try {
// Create a table for testing
sql """
CREATE TABLE IF NOT EXISTS ${table_name} (
id INT COMMENT "Primary key",
name STRING COMMENT "Name field"
)
DISTRIBUTED BY HASH(id) BUCKETS 5
PROPERTIES ("replication_num" = "1");
"""

// Create a view based on the created table
sql """
CREATE VIEW IF NOT EXISTS ${view_name} AS
SELECT id, name FROM ${table_name}
"""

// Execute the SHOW CREATE VIEW command
checkNereidsExecute("""show create view `${view_name}`;""")
qt_cmd("""show create view `${view_name}`;""")
} finally {
// Drop the view and table after testing
try_sql("DROP VIEW IF EXISTS `${view_name}`")
try_sql("DROP TABLE IF EXISTS `${table_name}`")
}

// Additional case: Create another view based on a different table
String view_name_2 = "view_show_create_view_2";
String table_name_2 = "table_for_view_test_2";
try {
// Create another table for testing
sql """
CREATE TABLE IF NOT EXISTS ${table_name_2} (
`key_field` INT COMMENT "Key field",
`value` STRING COMMENT "Value field"
)
DISTRIBUTED BY HASH(key_field) BUCKETS 3
PROPERTIES ("replication_num" = "1");
"""

// Create a view based on the new table
sql """
CREATE VIEW IF NOT EXISTS ${view_name_2} AS
SELECT key_field, value FROM ${table_name_2}
"""

// Execute the SHOW CREATE VIEW command for the new view
checkNereidsExecute("""show create view `${view_name_2}`;""")
qt_cmd("""show create view `${view_name_2}`;""")

} finally {
// Drop the view and table after testing
try_sql("DROP VIEW IF EXISTS `${view_name_2}`")
try_sql("DROP TABLE IF EXISTS `${table_name_2}`")
}
}