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

[feature-wip](multi-catalog) support to switch catalog #10381

Merged
merged 1 commit into from
Jun 24, 2022
Merged
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
15 changes: 13 additions & 2 deletions fe/fe-core/src/main/cup/sql_parser.cup
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,8 @@ terminal String KW_ADD, KW_ADMIN, KW_AFTER, KW_AGGREGATE, KW_ALIAS, KW_ALL, KW_A
KW_WARNINGS, KW_WEEK, KW_WHEN, KW_WHITELIST, KW_WHERE, KW_WITH, KW_WORK, KW_WRITE,
KW_YEAR,
KW_NOT_NULL,
KW_CATALOG, KW_CATALOGS;
KW_CATALOG, KW_CATALOGS,
KW_SWITCH;

terminal COMMA, COLON, DOT, DOTDOTDOT, AT, STAR, LPAREN, RPAREN, SEMICOLON, LBRACKET, RBRACKET, DIVIDE, MOD, ADD, SUBTRACT;
terminal BITAND, BITOR, BITXOR, BITNOT;
Expand All @@ -301,7 +302,7 @@ nonterminal StatementBase stmt, show_stmt, show_param, help_stmt, load_stmt,
show_routine_load_stmt, show_routine_load_task_stmt, show_create_routine_load_stmt,
describe_stmt, alter_stmt,
use_stmt, kill_stmt, drop_stmt, recover_stmt, grant_stmt, revoke_stmt, create_stmt, set_stmt, sync_stmt, cancel_stmt, cancel_param, delete_stmt,
link_stmt, migrate_stmt, enter_stmt, transaction_stmt, unsupported_stmt, export_stmt, admin_stmt, truncate_stmt,
link_stmt, migrate_stmt, switch_stmt, enter_stmt, transaction_stmt, unsupported_stmt, export_stmt, admin_stmt, truncate_stmt,
import_columns_stmt, import_delete_on_stmt, import_sequence_stmt, import_where_stmt, install_plugin_stmt, uninstall_plugin_stmt,
import_preceding_filter_stmt, unlock_tables_stmt, lock_tables_stmt, refresh_stmt;

Expand Down Expand Up @@ -670,6 +671,8 @@ stmt ::=
{: RESULT = query; :}
| migrate_stmt:query
{: RESULT = query; :}
| switch_stmt:stmt
{: RESULT = stmt; :}
| enter_stmt:enter
{: RESULT = enter; :}
| query_stmt:query
Expand Down Expand Up @@ -3422,6 +3425,14 @@ opt_set_qualifier ::=
{: RESULT = Qualifier.ALL; :}
;

// Change catalog
switch_stmt ::=
KW_SWITCH ident:catalog
{:
RESULT = new SwitchStmt(catalog);
:}
;

// Change cluster
enter_stmt ::=
KW_ENTER ident:cluster
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,14 @@

package org.apache.doris.analysis;


import org.apache.doris.analysis.CompoundPredicate.Operator;
import org.apache.doris.catalog.Catalog;
import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.Config;
import org.apache.doris.common.ErrorCode;
import org.apache.doris.common.ErrorReport;
import org.apache.doris.common.FeNameFormat;
import org.apache.doris.common.UserException;
import org.apache.doris.common.util.Util;
import org.apache.doris.datasource.InternalDataSource;
import org.apache.doris.mysql.privilege.PaloPrivilege;
import org.apache.doris.mysql.privilege.PrivBitSet;
import org.apache.doris.mysql.privilege.PrivPredicate;
import org.apache.doris.qe.ConnectContext;

Expand Down Expand Up @@ -57,21 +53,15 @@ public String getNewCatalogName() {
@Override
public void analyze(Analyzer analyzer) throws UserException {
super.analyze(analyzer);
if (!Config.enable_multi_catalog) {
throw new AnalysisException("The multi-catalog feature is still in experiment, and you can enable it "
+ "manually by set fe configuration named `enable_multi_catalog` to be ture.");
}
if (Strings.isNullOrEmpty(catalogName)) {
throw new AnalysisException("Datasource name is not set");
}
Util.checkCatalogAllRules(catalogName);

if (catalogName.equals(InternalDataSource.INTERNAL_DS_NAME)) {
throw new AnalysisException("Internal catalog can't be alter.");
}

if (!Catalog.getCurrentCatalog().getAuth().checkGlobalPriv(ConnectContext.get(),
PrivPredicate.of(PrivBitSet.of(PaloPrivilege.ADMIN_PRIV, PaloPrivilege.ALTER_PRIV), Operator.OR))) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_DBACCESS_DENIED_ERROR,
if (!Catalog.getCurrentCatalog().getAuth().checkCtlPriv(
ConnectContext.get(), catalogName, PrivPredicate.ALTER)) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_CATALOG_ACCESS_DENIED,
analyzer.getQualifiedUser(), catalogName);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,17 @@

package org.apache.doris.analysis;

import org.apache.doris.catalog.Catalog;
import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.Config;
import org.apache.doris.common.ErrorCode;
import org.apache.doris.common.ErrorReport;
import org.apache.doris.common.FeNameFormat;
import org.apache.doris.common.UserException;
import org.apache.doris.common.util.PrintableMap;
import org.apache.doris.common.util.Util;
import org.apache.doris.datasource.InternalDataSource;

import com.google.common.base.Strings;
import org.apache.doris.mysql.privilege.PrivPredicate;
import org.apache.doris.qe.ConnectContext;

import java.util.Map;

Expand All @@ -51,12 +54,11 @@ public Map<String, String> getNewProperties() {
@Override
public void analyze(Analyzer analyzer) throws UserException {
super.analyze(analyzer);
if (!Config.enable_multi_catalog) {
throw new AnalysisException("The multi-catalog feature is still in experiment, and you can enable it "
+ "manually by set fe configuration named `enable_multi_catalog` to be ture.");
}
if (Strings.isNullOrEmpty(catalogName)) {
throw new AnalysisException("Datasource name is not set");
Util.checkCatalogAllRules(catalogName);
if (!Catalog.getCurrentCatalog().getAuth().checkCtlPriv(
ConnectContext.get(), catalogName, PrivPredicate.ALTER)) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_CATALOG_ACCESS_DENIED,
analyzer.getQualifiedUser(), catalogName);
}

if (catalogName.equals(InternalDataSource.INTERNAL_DS_NAME)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@

import org.apache.doris.catalog.Catalog;
import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.Config;
import org.apache.doris.common.ErrorCode;
import org.apache.doris.common.ErrorReport;
import org.apache.doris.common.FeNameFormat;
import org.apache.doris.common.UserException;
import org.apache.doris.common.util.PrintableMap;
import org.apache.doris.common.util.Util;
import org.apache.doris.datasource.InternalDataSource;
import org.apache.doris.mysql.privilege.PrivPredicate;
import org.apache.doris.qe.ConnectContext;
Expand Down Expand Up @@ -64,17 +64,14 @@ public boolean isSetIfNotExists() {
@Override
public void analyze(Analyzer analyzer) throws UserException {
super.analyze(analyzer);
if (!Config.enable_multi_catalog) {
throw new AnalysisException("The multi-catalog feature is still in experiment, and you can enable it "
+ "manually by set fe configuration named `enable_multi_catalog` to be ture.");
}
Util.checkCatalogAllRules(catalogName);
if (catalogName.equals(InternalDataSource.INTERNAL_DS_NAME)) {
throw new AnalysisException("Internal catalog name can't be create.");
}
FeNameFormat.checkCommonName("catalog", catalogName);

if (!Catalog.getCurrentCatalog().getAuth().checkGlobalPriv(ConnectContext.get(), PrivPredicate.CREATE)) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_DBACCESS_DENIED_ERROR,
if (!Catalog.getCurrentCatalog().getAuth().checkCtlPriv(
ConnectContext.get(), catalogName, PrivPredicate.CREATE)) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_CATALOG_ACCESS_DENIED,
analyzer.getQualifiedUser(), catalogName);
}
FeNameFormat.checkCatalogProperties(properties);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,14 @@

import org.apache.doris.catalog.Catalog;
import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.Config;
import org.apache.doris.common.ErrorCode;
import org.apache.doris.common.ErrorReport;
import org.apache.doris.common.UserException;
import org.apache.doris.common.util.Util;
import org.apache.doris.datasource.InternalDataSource;
import org.apache.doris.mysql.privilege.PrivPredicate;
import org.apache.doris.qe.ConnectContext;

import com.google.common.base.Strings;

/**
* Statement for drop a catalog.
*/
Expand All @@ -52,21 +50,16 @@ public String getCatalogName() {
@Override
public void analyze(Analyzer analyzer) throws UserException {
super.analyze(analyzer);
if (!Config.enable_multi_catalog) {
throw new AnalysisException("The multi-catalog feature is still in experiment, and you can enable it "
+ "manually by set fe configuration named `enable_multi_catalog` to be ture.");
}
if (Strings.isNullOrEmpty(catalogName)) {
throw new AnalysisException("Datasource name is not set");
}
Util.checkCatalogAllRules(catalogName);

if (catalogName.equals(InternalDataSource.INTERNAL_DS_NAME)) {
throw new AnalysisException("Internal catalog can't be drop.");
}

if (!Catalog.getCurrentCatalog().getAuth().checkGlobalPriv(ConnectContext.get(), PrivPredicate.DROP)) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_DBACCESS_DENIED_ERROR,
ConnectContext.get().getQualifiedUser(), catalogName);
if (!Catalog.getCurrentCatalog().getAuth().checkCtlPriv(
ConnectContext.get(), catalogName, PrivPredicate.DROP)) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_CATALOG_ACCESS_DENIED,
analyzer.getQualifiedUser(), catalogName);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,15 +168,21 @@ public static void checkPrivileges(Analyzer analyzer, List<PaloPrivilege> privil
if (!Catalog.getCurrentCatalog().getAuth().checkGlobalPriv(ConnectContext.get(), PrivPredicate.GRANT)) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR, "GRANT");
}
} else if (tblPattern.getPrivLevel() == PrivLevel.CATALOG) {
if (!Catalog.getCurrentCatalog().getAuth().checkCtlPriv(ConnectContext.get(),
tblPattern.getQualifiedCtl(), PrivPredicate.GRANT)) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR, "GRANT");
}
} else if (tblPattern.getPrivLevel() == PrivLevel.DATABASE) {
if (!Catalog.getCurrentCatalog().getAuth().checkDbPriv(ConnectContext.get(),
tblPattern.getQualifiedDb(), PrivPredicate.GRANT)) {
tblPattern.getQualifiedCtl(), tblPattern.getQualifiedDb(), PrivPredicate.GRANT)) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR, "GRANT");
}
} else {
// table level
if (!Catalog.getCurrentCatalog().getAuth().checkTblPriv(ConnectContext.get(),
tblPattern.getQualifiedDb(), tblPattern.getTbl(), PrivPredicate.GRANT)) {
tblPattern.getQualifiedCtl(), tblPattern.getQualifiedDb(),
tblPattern.getTbl(), PrivPredicate.GRANT)) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR, "GRANT");
}
}
Expand Down
65 changes: 65 additions & 0 deletions fe/fe-core/src/main/java/org/apache/doris/analysis/SwitchStmt.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// 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.analysis;

import org.apache.doris.catalog.Catalog;
import org.apache.doris.common.ErrorCode;
import org.apache.doris.common.ErrorReport;
import org.apache.doris.common.UserException;
import org.apache.doris.common.util.Util;
import org.apache.doris.mysql.privilege.PrivPredicate;
import org.apache.doris.qe.ConnectContext;

public class SwitchStmt extends StatementBase {
private final String catalogName;

public SwitchStmt(String catalogName) {
this.catalogName = catalogName;
}

public String getCatalogName() {
return catalogName;
}

@Override
public String toSql() {
return "SWITCH `" + catalogName + "`";
}

@Override
public String toString() {
return toSql();
}

public void analyze(Analyzer analyzer) throws UserException {
super.analyze(analyzer);

Util.checkCatalogAllRules(catalogName);

if (!Catalog.getCurrentCatalog().getAuth().checkCtlPriv(
ConnectContext.get(), catalogName, PrivPredicate.SHOW)) {
ErrorReport.reportAnalysisException(
ErrorCode.ERR_CATALOG_ACCESS_DENIED, analyzer.getQualifiedUser(), catalogName);
}
}

@Override
public RedirectStatus getRedirectStatus() {
return RedirectStatus.NO_FORWARD;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4218,6 +4218,15 @@ public void cancelAlterCluster(CancelAlterSystemStmt stmt) throws DdlException {
this.alter.getClusterHandler().cancel(stmt);
}

// Switch catalog of this sesseion.
public void changeCatalog(ConnectContext ctx, String catalogName) throws DdlException {
if (dataSourceMgr.getCatalogNullable(catalogName) == null) {
throw new DdlException(ErrorCode.ERR_UNKNOWN_CATALOG.formatErrorMsg(
catalogName), ErrorCode.ERR_UNKNOWN_CATALOG);
}
ctx.changeDefaultCatalog(catalogName);
}

// Change current database of this session.
public void changeDb(ConnectContext ctx, String qualifiedDb) throws DdlException {
if (!auth.checkDbPriv(ctx, qualifiedDb, PrivPredicate.SHOW)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1686,7 +1686,10 @@ public enum ErrorCode {
+ "Use `SHOW PARTITIONS FROM %s` to see the currently partitions of this table. "),
ERROR_SQL_AND_LIMITATIONS_SET_IN_ONE_RULE(5084, new byte[]{'4', '2', '0', '0', '0'},
"sql/sqlHash and partition_num/tablet_num/cardinality cannot be set in one rule."),
ERR_WRONG_CATALOG_NAME(5085, new byte[]{'4', '2', '0', '0', '0'}, "Incorrect catalog name '%s'");
ERR_WRONG_CATALOG_NAME(5085, new byte[]{'4', '2', '0', '0', '0'}, "Incorrect catalog name '%s'"),
ERR_UNKNOWN_CATALOG(5086, new byte[]{'4', '2', '0', '0', '0'}, "Unknown catalog '%s'"),
ERR_CATALOG_ACCESS_DENIED(5087, new byte[]{'4', '2', '0', '0', '0'},
"Access denied for user '%s' to catalog '%s'");

// This is error code
private final int code;
Expand Down
28 changes: 28 additions & 0 deletions fe/fe-core/src/main/java/org/apache/doris/common/util/Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
import org.apache.doris.catalog.Column;
import org.apache.doris.catalog.PrimitiveType;
import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.Config;
import org.apache.doris.common.FeNameFormat;
import org.apache.doris.datasource.InternalDataSource;
import org.apache.doris.qe.ConnectContext;

import com.google.common.base.Preconditions;
Expand Down Expand Up @@ -457,4 +460,29 @@ public static String escapeSingleRegex(String s) {
}
return s;
}

/**
* Multi-catalog feature is in experiment, and should be enabled by user manually.
*/
public static void checkCatalogEnabled() throws AnalysisException {
if (!Config.enable_multi_catalog) {
throw new AnalysisException("The multi-catalog feature is still in experiment, and you can enable it "
+ "manually by set fe configuration named `enable_multi_catalog` to be ture.");
}
}

/**
* Check all rules of catalog.
*/
public static void checkCatalogAllRules(String catalog) throws AnalysisException {
checkCatalogEnabled();

if (Strings.isNullOrEmpty(catalog)) {
throw new AnalysisException("Catalog name is empty.");
}

if (!catalog.equals(InternalDataSource.INTERNAL_DS_NAME)) {
FeNameFormat.checkCommonName("catalog", catalog);
}
}
}
Loading