[feature](multi-catalog)support catalog name when create/drop db (#33116)

Issue Number: #31442
This commit is contained in:
slothever
2024-04-02 22:54:45 +08:00
committed by morningman
parent 01b21da82d
commit 7a05396cd1
10 changed files with 151 additions and 22 deletions

View File

@ -772,6 +772,7 @@ nonterminal ArrayList<Long> opt_tablet_list, tablet_list;
nonterminal TableSample opt_table_sample, table_sample;
nonterminal TableSnapshot opt_table_snapshot, table_snapshot;
nonterminal TableName table_name, opt_table_name;
nonterminal DbName db_name;
nonterminal FunctionName function_name;
nonterminal EncryptKeyName encryptkey_name;
nonterminal Expr pre_filter_clause;
@ -1766,11 +1767,11 @@ opt_intermediate_type ::=
// Create Statement
create_stmt ::=
/* Database */
KW_CREATE KW_DATABASE opt_if_not_exists:ifNotExists ident:db opt_properties:properties
KW_CREATE KW_DATABASE opt_if_not_exists:ifNotExists db_name:db opt_properties:properties
{:
RESULT = new CreateDbStmt(ifNotExists, db, properties);
:}
| KW_CREATE KW_SCHEMA opt_if_not_exists:ifNotExists ident:db
| KW_CREATE KW_SCHEMA opt_if_not_exists:ifNotExists db_name:db
{:
RESULT = new CreateDbStmt(ifNotExists, db, null);
:}
@ -2989,11 +2990,11 @@ revoke_stmt ::=
// Drop statement
drop_stmt ::=
/* Database */
KW_DROP KW_DATABASE opt_if_exists:ifExists ident:db opt_force:force
KW_DROP KW_DATABASE opt_if_exists:ifExists db_name:db opt_force:force
{:
RESULT = new DropDbStmt(ifExists, db, force);
:}
| KW_DROP KW_SCHEMA opt_if_exists:ifExists ident:db opt_force:force
| KW_DROP KW_SCHEMA opt_if_exists:ifExists db_name:db opt_force:force
{:
RESULT = new DropDbStmt(ifExists, db, force);
:}
@ -5793,6 +5794,13 @@ table_name ::=
{: RESULT = new TableName(ctl, db, tbl); :}
;
db_name ::=
ident:db
{: RESULT = new DbName(null, db); :}
| ident:ctl DOT ident:db
{: RESULT = new DbName(ctl, db); :}
;
colocate_group_name ::=
ident:group
{:

View File

@ -27,17 +27,21 @@ import org.apache.doris.common.util.PrintableMap;
import org.apache.doris.mysql.privilege.PrivPredicate;
import org.apache.doris.qe.ConnectContext;
import org.apache.commons.lang3.StringUtils;
import java.util.HashMap;
import java.util.Map;
public class CreateDbStmt extends DdlStmt {
private boolean ifNotExists;
private String ctlName;
private String dbName;
private Map<String, String> properties;
public CreateDbStmt(boolean ifNotExists, String dbName, Map<String, String> properties) {
public CreateDbStmt(boolean ifNotExists, DbName dbName, Map<String, String> properties) {
this.ifNotExists = ifNotExists;
this.dbName = dbName;
this.ctlName = dbName.getCtl();
this.dbName = dbName.getDb();
this.properties = properties == null ? new HashMap<>() : properties;
}
@ -45,6 +49,10 @@ public class CreateDbStmt extends DdlStmt {
return dbName;
}
public String getCtlName() {
return ctlName;
}
public boolean isSetIfNotExists() {
return ifNotExists;
}
@ -56,6 +64,10 @@ public class CreateDbStmt extends DdlStmt {
@Override
public void analyze(Analyzer analyzer) throws UserException {
super.analyze(analyzer);
if (StringUtils.isEmpty(ctlName)) {
ctlName = Env.getCurrentEnv().getCurrentCatalog().getName();
}
FeNameFormat.checkCatalogName(ctlName);
FeNameFormat.checkDbName(dbName);
InternalDatabaseUtil.checkDatabase(dbName, ConnectContext.get());
if (!Env.getCurrentEnv().getAccessManager().checkDbPriv(ConnectContext.get(), dbName, PrivPredicate.CREATE)) {

View File

@ -0,0 +1,86 @@
// 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.analysis;
import org.apache.doris.datasource.InternalCatalog;
import java.util.Objects;
public class DbName {
private String ctl;
private String db;
public DbName(String ctl, String db) {
this.ctl = ctl;
this.db = db;
}
public String getCtl() {
return ctl;
}
public void setCtl(String ctl) {
this.ctl = ctl;
}
public String getDb() {
return db;
}
public void setDb(String db) {
this.db = db;
}
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
if (ctl != null && !ctl.equals(InternalCatalog.INTERNAL_CATALOG_NAME)) {
stringBuilder.append(ctl).append(".");
}
stringBuilder.append(db);
return stringBuilder.toString();
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (other instanceof DbName) {
return toString().equals(other.toString());
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(ctl, db);
}
public String toSql() {
StringBuilder stringBuilder = new StringBuilder();
if (ctl != null && !ctl.equals(InternalCatalog.INTERNAL_CATALOG_NAME)) {
stringBuilder.append("`").append(ctl).append("`.");
}
stringBuilder.append("`").append(db).append("`");
return stringBuilder.toString();
}
}

View File

@ -32,12 +32,14 @@ import com.google.common.base.Strings;
// DROP DB表达式
public class DropDbStmt extends DdlStmt {
private boolean ifExists;
private String ctlName;
private String dbName;
private boolean forceDrop;
public DropDbStmt(boolean ifExists, String dbName, boolean forceDrop) {
public DropDbStmt(boolean ifExists, DbName dbName, boolean forceDrop) {
this.ifExists = ifExists;
this.dbName = dbName;
this.ctlName = dbName.getCtl();
this.dbName = dbName.getDb();
this.forceDrop = forceDrop;
}
@ -45,6 +47,10 @@ public class DropDbStmt extends DdlStmt {
return ifExists;
}
public String getCtlName() {
return ctlName;
}
public String getDbName() {
return this.dbName;
}

View File

@ -2967,7 +2967,13 @@ public class Env {
// The interface which DdlExecutor needs.
public void createDb(CreateDbStmt stmt) throws DdlException {
getCurrentCatalog().createDb(stmt);
CatalogIf<?> catalogIf;
if (StringUtils.isEmpty(stmt.getCtlName())) {
catalogIf = getCurrentCatalog();
} else {
catalogIf = catalogMgr.getCatalog(stmt.getCtlName());
}
catalogIf.createDb(stmt);
}
// For replay edit log, need't lock metadata
@ -2980,7 +2986,13 @@ public class Env {
}
public void dropDb(DropDbStmt stmt) throws DdlException {
getCurrentCatalog().dropDb(stmt);
CatalogIf<?> catalogIf;
if (StringUtils.isEmpty(stmt.getCtlName())) {
catalogIf = getCurrentCatalog();
} else {
catalogIf = catalogMgr.getCatalog(stmt.getCtlName());
}
catalogIf.dropDb(stmt);
}
public void replayDropDb(String dbName, boolean isForceDrop, Long recycleTime) throws DdlException {

View File

@ -21,6 +21,7 @@ import org.apache.doris.analysis.AlterClause;
import org.apache.doris.analysis.AlterTableStmt;
import org.apache.doris.analysis.CreateDbStmt;
import org.apache.doris.analysis.CreateTableStmt;
import org.apache.doris.analysis.DbName;
import org.apache.doris.analysis.DistributionDesc;
import org.apache.doris.analysis.DropTableStmt;
import org.apache.doris.analysis.HashDistributionDesc;
@ -164,8 +165,8 @@ public class InternalSchemaInitializer extends Thread {
@VisibleForTesting
public static void createDb() {
CreateDbStmt createDbStmt = new CreateDbStmt(true, FeConstants.INTERNAL_DB_NAME,
null);
CreateDbStmt createDbStmt = new CreateDbStmt(true,
new DbName("internal", FeConstants.INTERNAL_DB_NAME), null);
try {
Env.getCurrentEnv().createDb(createDbStmt);
} catch (DdlException e) {

View File

@ -48,7 +48,7 @@ public class CreateDbStmtTest {
@Test
public void testAnalyzeNormal() throws UserException {
CreateDbStmt dbStmt = new CreateDbStmt(false, "test", null);
CreateDbStmt dbStmt = new CreateDbStmt(false, new DbName(null, "test"), null);
dbStmt.analyze(analyzer);
Assert.assertEquals("test", dbStmt.getFullDbName());
Assert.assertEquals("CREATE DATABASE `test`", dbStmt.toString());
@ -56,7 +56,7 @@ public class CreateDbStmtTest {
@Test(expected = AnalysisException.class)
public void testAnalyzeWithException() throws UserException {
CreateDbStmt stmt = new CreateDbStmt(false, "", null);
CreateDbStmt stmt = new CreateDbStmt(false, new DbName("", ""), null);
stmt.analyze(analyzer);
Assert.fail("no exception");
}
@ -66,8 +66,9 @@ public class CreateDbStmtTest {
Map<String, String> properties = new HashMap<>();
properties.put("iceberg.database", "doris");
properties.put("iceberg.hive.metastore.uris", "thrift://127.0.0.1:9087");
CreateDbStmt stmt = new CreateDbStmt(false, "test", properties);
CreateDbStmt stmt = new CreateDbStmt(false, new DbName("ctl", "test"), properties);
stmt.analyze(analyzer);
Assert.assertEquals("ctl", stmt.getCtlName());
Assert.assertEquals("test", stmt.getFullDbName());
Assert.assertEquals("CREATE DATABASE `test`\n"
+ "PROPERTIES (\n"
@ -81,7 +82,7 @@ public class CreateDbStmtTest {
Map<String, String> properties = new HashMap<>();
properties.put("iceberg.database", "doris");
properties.put("iceberg.hive.metastore.uris", "thrift://127.0.0.1:9087");
CreateDbStmt stmt = new CreateDbStmt(false, "", properties);
CreateDbStmt stmt = new CreateDbStmt(false, new DbName("", ""), properties);
stmt.analyze(analyzer);
Assert.fail("No exception throws.");
}

View File

@ -45,16 +45,17 @@ public class DropDbStmtTest {
@Test
public void testNormal() throws UserException, AnalysisException {
DropDbStmt stmt = new DropDbStmt(false, "test", true);
DropDbStmt stmt = new DropDbStmt(false, new DbName("test", "test"), true);
stmt.analyze(analyzer);
Assert.assertEquals("test", stmt.getCtlName());
Assert.assertEquals("test", stmt.getDbName());
Assert.assertEquals("DROP DATABASE `test`", stmt.toString());
}
@Test(expected = AnalysisException.class)
public void testFailed() throws UserException, AnalysisException {
DropDbStmt stmt = new DropDbStmt(false, "", true);
DropDbStmt stmt = new DropDbStmt(false, new DbName("", ""), true);
stmt.analyze(analyzer);
Assert.fail("no exception");
@ -62,7 +63,7 @@ public class DropDbStmtTest {
@Test
public void testNoPriv() {
DropDbStmt stmt = new DropDbStmt(false, "", true);
DropDbStmt stmt = new DropDbStmt(false, new DbName("", ""), true);
try {
stmt.analyze(AccessTestUtil.fetchBlockAnalyzer());
} catch (AnalysisException e) {

View File

@ -20,6 +20,7 @@ package org.apache.doris.datasource.hive;
import org.apache.doris.analysis.CreateCatalogStmt;
import org.apache.doris.analysis.CreateDbStmt;
import org.apache.doris.analysis.CreateTableStmt;
import org.apache.doris.analysis.DbName;
import org.apache.doris.analysis.HashDistributionDesc;
import org.apache.doris.analysis.SwitchStmt;
import org.apache.doris.catalog.Column;
@ -140,7 +141,7 @@ public class HiveDDLAndDMLPlanTest extends TestWithFeService {
}
}
};
CreateDbStmt createDbStmt = new CreateDbStmt(true, mockedDbName, dbProps);
CreateDbStmt createDbStmt = new CreateDbStmt(true, new DbName("hive", mockedDbName), dbProps);
Env.getCurrentEnv().createDb(createDbStmt);
useDatabase(mockedDbName);

View File

@ -19,6 +19,7 @@ package org.apache.doris.datasource.hive;
import org.apache.doris.analysis.CreateDbStmt;
import org.apache.doris.analysis.CreateTableStmt;
import org.apache.doris.analysis.DbName;
import org.apache.doris.analysis.DistributionDesc;
import org.apache.doris.analysis.DropDbStmt;
import org.apache.doris.analysis.DropTableStmt;
@ -99,12 +100,12 @@ public class HiveMetadataOpsTest {
}
private void createDb(String dbName, Map<String, String> props) throws DdlException {
CreateDbStmt createDbStmt = new CreateDbStmt(true, dbName, props);
CreateDbStmt createDbStmt = new CreateDbStmt(true, new DbName("hive", dbName), props);
metadataOps.createDb(createDbStmt);
}
private void dropDb(String dbName, boolean forceDrop) throws DdlException {
DropDbStmt dropDbStmt = new DropDbStmt(true, dbName, forceDrop);
DropDbStmt dropDbStmt = new DropDbStmt(true, new DbName("hive", dbName), forceDrop);
metadataOps.dropDb(dropDbStmt);
}