branch-2.1: [enhancement](nereids)remove dependence on old CreateTableStmt for CreateTableLikeCommand #48007 (#48528)

pick from master https://github.com/apache/doris/pull/48007

### What problem does this PR solve?

Issue Number: close #xxx

Related PR: #xxx

Problem Summary:

### Release note

None

### Check List (For Author)

- Test <!-- At least one of them must be included. -->
    - [ ] Regression test
    - [ ] Unit Test
    - [ ] Manual test (add detailed scripts or steps below)
    - [ ] No need to test or manual test. Explain why:
- [ ] This is a refactor/code format and no logic has been changed.
        - [ ] Previous test can cover this change.
        - [ ] No code files have been changed.
        - [ ] Other reason <!-- Add your reason?  -->

- Behavior changed:
    - [ ] No.
    - [ ] Yes. <!-- Explain the behavior change -->

- Does this need documentation?
    - [ ] No.
- [ ] Yes. <!-- Add document PR link here. eg:
https://github.com/apache/doris-website/pull/1214 -->

### Check List (For Reviewer who merge this PR)

- [ ] Confirm the release note
- [ ] Confirm test cases
- [ ] Confirm document
- [ ] Add branch pick label <!-- Add branch pick label that this PR
should merge into -->
This commit is contained in:
starocean999
2025-03-03 14:50:59 +08:00
committed by GitHub
parent 8b563d6ec1
commit 4134db5ee3
4 changed files with 126 additions and 1 deletions

View File

@ -209,6 +209,10 @@ public class CreateTableCommand extends Command implements ForwardWithSync {
return ctasQuery.isPresent();
}
public Optional<LogicalPlan> getCtasQuery() {
return ctasQuery;
}
@Override
public <R, C> R accept(PlanVisitor<R, C> visitor, C context) {
return visitor.visitCreateTableCommand(this, context);

View File

@ -18,13 +18,27 @@
package org.apache.doris.nereids.trees.plans.commands;
import org.apache.doris.analysis.CreateTableLikeStmt;
import org.apache.doris.catalog.DatabaseIf;
import org.apache.doris.catalog.Env;
import org.apache.doris.catalog.OlapTable;
import org.apache.doris.catalog.TableIf;
import org.apache.doris.common.DdlException;
import org.apache.doris.common.ErrorCode;
import org.apache.doris.common.ErrorReport;
import org.apache.doris.common.UserException;
import org.apache.doris.nereids.parser.NereidsParser;
import org.apache.doris.nereids.trees.plans.PlanType;
import org.apache.doris.nereids.trees.plans.commands.info.CreateTableInfo;
import org.apache.doris.nereids.trees.plans.commands.info.CreateTableLikeInfo;
import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
import org.apache.doris.qe.ConnectContext;
import org.apache.doris.qe.StmtExecutor;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import java.util.List;
/** CreateTableLikeCommand */
public class CreateTableLikeCommand extends Command implements ForwardWithSync {
private final CreateTableLikeInfo info;
@ -39,11 +53,67 @@ public class CreateTableLikeCommand extends Command implements ForwardWithSync {
executor.checkBlockRules();
info.validate(ctx);
CreateTableLikeStmt stmt = info.translateToLegacyStmt();
Env.getCurrentEnv().createTableLike(stmt);
doRun(stmt, ctx, executor);
}
@Override
public <R, C> R accept(PlanVisitor<R, C> visitor, C context) {
return visitor.visitCreateTableLikeCommand(this, context);
}
private void doRun(CreateTableLikeStmt stmt, ConnectContext ctx, StmtExecutor executor) throws Exception {
try {
DatabaseIf db = Env.getCurrentInternalCatalog().getDbOrDdlException(stmt.getExistedDbName());
TableIf table = db.getTableOrDdlException(stmt.getExistedTableName());
if (table.getType() == TableIf.TableType.VIEW) {
throw new DdlException("Not support create table from a View");
}
List<String> createTableStmt = Lists.newArrayList();
table.readLock();
try {
if (table.isManagedTable()) {
if (!CollectionUtils.isEmpty(stmt.getRollupNames())) {
OlapTable olapTable = (OlapTable) table;
for (String rollupIndexName : stmt.getRollupNames()) {
if (!olapTable.hasMaterializedIndex(rollupIndexName)) {
throw new DdlException("Rollup index[" + rollupIndexName + "] not exists in Table["
+ olapTable.getName() + "]");
}
}
}
} else if (!CollectionUtils.isEmpty(stmt.getRollupNames()) || stmt.isWithAllRollup()) {
throw new DdlException("Table[" + table.getName() + "] is external, not support rollup copy");
}
Env.getDdlStmt(stmt, stmt.getDbName(), table, createTableStmt, null, null, false, false, true, -1L,
false, false);
if (createTableStmt.isEmpty()) {
ErrorReport.reportDdlException(ErrorCode.ERROR_CREATE_TABLE_LIKE_EMPTY, "CREATE");
}
} finally {
table.readUnlock();
}
try {
// analyze CreateTableStmt will check create_priv of existedTable, create table like only need
// create_priv of newTable, and select_priv of existedTable, and priv check has done in
// CreateTableStmt/CreateTableCommand, so we skip it
ctx.setSkipAuth(true);
NereidsParser nereidsParser = new NereidsParser();
CreateTableCommand createTableCommand = (CreateTableCommand) nereidsParser
.parseSingle(createTableStmt.get(0));
CreateTableInfo createTableInfo = createTableCommand.getCreateTableInfo();
createTableCommand = new CreateTableCommand(createTableCommand.getCtasQuery(),
createTableInfo.withTableNameAndIfNotExists(stmt.getTableName(), stmt.isIfNotExists()));
createTableCommand.run(ctx, executor);
} finally {
ctx.setSkipAuth(false);
}
} catch (UserException e) {
throw new DdlException("Failed to execute CREATE TABLE LIKE " + stmt.getExistedTableName() + ". Reason: "
+ e.getMessage(), e);
}
}
}

View File

@ -166,6 +166,21 @@ public class CreateTableInfo {
this.clusterKeysColumnNames = Utils.copyRequiredList(clusterKeyColumnNames);
}
/**
* withTableNameAndIfNotExists
*/
public CreateTableInfo withTableNameAndIfNotExists(String tableName, boolean ifNotExists) {
if (ctasColumns != null) {
return new CreateTableInfo(ifNotExists, isExternal, ctlName, dbName, tableName, ctasColumns, engineName,
keysType, keys, comment, partitionTableInfo, distribution, rollups, properties, extProperties,
clusterKeysColumnNames);
} else {
return new CreateTableInfo(ifNotExists, isExternal, ctlName, dbName, tableName, columns, indexes,
engineName, keysType, keys, comment, partitionTableInfo, distribution, rollups, properties,
extProperties, clusterKeysColumnNames);
}
}
public List<String> getCtasColumns() {
return ctasColumns;
}

View File

@ -0,0 +1,36 @@
// 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 suite is for creating table with timestamp datatype in defferent
// case. For example: 'year' and 'Year' datatype should also be valid in definition
suite("test_create_table_like") {
multi_sql """
DROP TABLE IF EXISTS test_create_table_like_t1;
CREATE TABLE `test_create_table_like_t1` (
`id` int NULL,
`m_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=OLAP
UNIQUE KEY(`id`)
DISTRIBUTED BY HASH(`id`) BUCKETS AUTO
PROPERTIES (
"replication_allocation" = "tag.location.default: 1"
);
DROP TABLE IF EXISTS test_create_table_like_t2;
CREATE TABLE test_create_table_like_t2 like test_create_table_like_t1;
"""
}