This is an automated email from the ASF dual-hosted git repository. morningman 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 516f5b1789 [feature-wip](multi-catalog) support to switch catalog (#10381) 516f5b1789 is described below commit 516f5b17894233771e86e17e6a950296b1ac596e Author: Ashin Gau <ashin...@users.noreply.github.com> AuthorDate: Fri Jun 24 10:42:13 2022 +0800 [feature-wip](multi-catalog) support to switch catalog (#10381) Add `switch catalog` stmt with privilege check --- fe/fe-core/src/main/cup/sql_parser.cup | 15 +- .../doris/analysis/AlterCatalogNameStmt.java | 20 +-- .../doris/analysis/AlterCatalogPropertyStmt.java | 20 +-- .../apache/doris/analysis/CreateCatalogStmt.java | 13 +- .../org/apache/doris/analysis/DropCatalogStmt.java | 19 +-- .../java/org/apache/doris/analysis/GrantStmt.java | 10 +- .../{DropCatalogStmt.java => SwitchStmt.java} | 55 +++---- .../java/org/apache/doris/catalog/Catalog.java | 9 ++ .../java/org/apache/doris/common/ErrorCode.java | 5 +- .../java/org/apache/doris/common/util/Util.java | 28 ++++ .../org/apache/doris/datasource/DataSourceMgr.java | 27 +++- .../apache/doris/mysql/privilege/DbPrivTable.java | 18 +++ .../org/apache/doris/mysql/privilege/PaloAuth.java | 52 ++++++- .../doris/mysql/privilege/TablePrivTable.java | 17 +++ .../java/org/apache/doris/qe/StmtExecutor.java | 15 ++ fe/fe-core/src/main/jflex/sql_scanner.flex | 1 + .../doris/analysis/AlterCatalogNameStmtTest.java | 2 +- .../doris/analysis/AlterCatalogPropsStmtTest.java | 2 +- .../doris/analysis/CreateCatalogStmtTest.java | 2 +- .../apache/doris/analysis/DropCatalogStmtTest.java | 2 +- .../org/apache/doris/analysis/SwitchStmtTest.java | 161 +++++++++++++++++++++ .../org/apache/doris/utframe/UtFrameUtils.java | 14 +- 22 files changed, 406 insertions(+), 101 deletions(-) diff --git a/fe/fe-core/src/main/cup/sql_parser.cup b/fe/fe-core/src/main/cup/sql_parser.cup index 0a1b969218..3b1404fc2e 100644 --- a/fe/fe-core/src/main/cup/sql_parser.cup +++ b/fe/fe-core/src/main/cup/sql_parser.cup @@ -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; @@ -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; @@ -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 @@ -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 diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/AlterCatalogNameStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/AlterCatalogNameStmt.java index e8eb8bb473..67776bf510 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/AlterCatalogNameStmt.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/AlterCatalogNameStmt.java @@ -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; @@ -57,21 +53,15 @@ public class AlterCatalogNameStmt extends DdlStmt { @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); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/AlterCatalogPropertyStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/AlterCatalogPropertyStmt.java index 7f39780eca..a19bf67fa0 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/AlterCatalogPropertyStmt.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/AlterCatalogPropertyStmt.java @@ -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; @@ -51,12 +54,11 @@ public class AlterCatalogPropertyStmt extends DdlStmt { @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)) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateCatalogStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateCatalogStmt.java index ee89675d6c..d7ddd3320c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateCatalogStmt.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateCatalogStmt.java @@ -19,12 +19,12 @@ 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 org.apache.doris.mysql.privilege.PrivPredicate; import org.apache.doris.qe.ConnectContext; @@ -64,17 +64,14 @@ public class CreateCatalogStmt extends DdlStmt { @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); diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/DropCatalogStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/DropCatalogStmt.java index aa620b17a4..6e5233916f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/DropCatalogStmt.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/DropCatalogStmt.java @@ -19,16 +19,14 @@ 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.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. */ @@ -52,21 +50,16 @@ public class DropCatalogStmt extends DdlStmt { @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); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/GrantStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/GrantStmt.java index 4ad8fe8073..9d5cf88967 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/GrantStmt.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/GrantStmt.java @@ -168,15 +168,21 @@ public class GrantStmt extends DdlStmt { 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"); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/DropCatalogStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/SwitchStmt.java similarity index 52% copy from fe/fe-core/src/main/java/org/apache/doris/analysis/DropCatalogStmt.java copy to fe/fe-core/src/main/java/org/apache/doris/analysis/SwitchStmt.java index aa620b17a4..cf47511863 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/DropCatalogStmt.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/SwitchStmt.java @@ -18,65 +18,48 @@ 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.UserException; -import org.apache.doris.datasource.InternalDataSource; +import org.apache.doris.common.util.Util; import org.apache.doris.mysql.privilege.PrivPredicate; import org.apache.doris.qe.ConnectContext; -import com.google.common.base.Strings; - -/** - * Statement for drop a catalog. - */ -public class DropCatalogStmt extends DdlStmt { - private final boolean ifExists; +public class SwitchStmt extends StatementBase { private final String catalogName; - public DropCatalogStmt(boolean ifExists, String catalogName) { - this.ifExists = ifExists; + public SwitchStmt(String catalogName) { this.catalogName = catalogName; } - public boolean isSetIfExists() { - return ifExists; + public String getCatalogName() { + return catalogName; } - public String getCatalogName() { - return this.catalogName; + @Override + public String toSql() { + return "SWITCH `" + catalogName + "`"; } @Override + public String toString() { + return toSql(); + } + 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"); - } - if (catalogName.equals(InternalDataSource.INTERNAL_DS_NAME)) { - throw new AnalysisException("Internal catalog can't be drop."); - } + Util.checkCatalogAllRules(catalogName); - 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.SHOW)) { + ErrorReport.reportAnalysisException( + ErrorCode.ERR_CATALOG_ACCESS_DENIED, analyzer.getQualifiedUser(), catalogName); } } @Override - public String toSql() { - return "DROP CATALOG " + "`" + catalogName + "`"; - } - - @Override - public String toString() { - return toSql(); + public RedirectStatus getRedirectStatus() { + return RedirectStatus.NO_FORWARD; } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Catalog.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/Catalog.java index 4abd66d200..4b8c6a14da 100755 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Catalog.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Catalog.java @@ -4218,6 +4218,15 @@ public class Catalog { 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)) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/ErrorCode.java b/fe/fe-core/src/main/java/org/apache/doris/common/ErrorCode.java index a8f73b9773..4fdd640b4e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/common/ErrorCode.java +++ b/fe/fe-core/src/main/java/org/apache/doris/common/ErrorCode.java @@ -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; diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/util/Util.java b/fe/fe-core/src/main/java/org/apache/doris/common/util/Util.java index a63c40223e..b2857d26f3 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/common/util/Util.java +++ b/fe/fe-core/src/main/java/org/apache/doris/common/util/Util.java @@ -20,6 +20,9 @@ package org.apache.doris.common.util; 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; @@ -457,4 +460,29 @@ public class Util { } 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); + } + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/DataSourceMgr.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/DataSourceMgr.java index 1192eb2b22..d77cc9a18d 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/DataSourceMgr.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/DataSourceMgr.java @@ -25,11 +25,15 @@ import org.apache.doris.analysis.ShowCatalogStmt; import org.apache.doris.catalog.Catalog; import org.apache.doris.common.AnalysisException; 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.common.io.Text; import org.apache.doris.common.io.Writable; +import org.apache.doris.mysql.privilege.PrivPredicate; import org.apache.doris.persist.OperationType; import org.apache.doris.persist.gson.GsonUtils; +import org.apache.doris.qe.ConnectContext; import org.apache.doris.qe.ShowResultSet; import com.google.common.collect.Lists; @@ -150,6 +154,13 @@ public class DataSourceMgr implements Writable { Catalog.getCurrentCatalog().getEditLog().logDatasourceLog(OperationType.OP_ALTER_DS_PROPS, log); } + /** + * Get catalog, or null if not exists. + */ + public DataSourceIf getCatalogNullable(String catalogName) { + return nameToCatalogs.get(catalogName); + } + /** * List all catalog or get the special catalog with a name. */ @@ -159,16 +170,24 @@ public class DataSourceMgr implements Writable { try { if (showStmt.getCatalogName() == null) { for (DataSourceIf ds : nameToCatalogs.values()) { - List<String> row = Lists.newArrayList(); - row.add(ds.getName()); - row.add(ds.getType()); - rows.add(row); + if (Catalog.getCurrentCatalog().getAuth().checkCtlPriv( + ConnectContext.get(), ds.getName(), PrivPredicate.SHOW)) { + List<String> row = Lists.newArrayList(); + row.add(ds.getName()); + row.add(ds.getType()); + rows.add(row); + } } } else { if (!nameToCatalogs.containsKey(showStmt.getCatalogName())) { throw new AnalysisException("No catalog found with name: " + showStmt.getCatalogName()); } DataSourceIf ds = nameToCatalogs.get(showStmt.getCatalogName()); + if (!Catalog.getCurrentCatalog().getAuth().checkCtlPriv( + ConnectContext.get(), ds.getName(), PrivPredicate.SHOW)) { + ErrorReport.reportAnalysisException(ErrorCode.ERR_CATALOG_ACCESS_DENIED, + ConnectContext.get().getQualifiedUser(), ds.getName()); + } for (Map.Entry<String, String> elem : ds.getProperties().entrySet()) { List<String> row = Lists.newArrayList(); row.add(elem.getKey()); diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/DbPrivTable.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/DbPrivTable.java index 87ef9ad50e..961cd1cb8c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/DbPrivTable.java +++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/DbPrivTable.java @@ -21,6 +21,7 @@ import org.apache.doris.analysis.UserIdentity; import org.apache.doris.common.io.Text; import org.apache.doris.qe.ConnectContext; +import com.google.common.base.Preconditions; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -66,6 +67,23 @@ public class DbPrivTable extends PrivTable { savedPrivs.or(matchedEntry.getPrivSet()); } + public boolean hasPrivsOfCatalog(UserIdentity currentUser, String ctl) { + for (PrivEntry entry : entries) { + DbPrivEntry dbPrivEntry = (DbPrivEntry) entry; + + if (!dbPrivEntry.match(currentUser, true)) { + continue; + } + + // check catalog + Preconditions.checkState(!dbPrivEntry.isAnyCtl()); + if (dbPrivEntry.getCtlPattern().match(ctl)) { + return true; + } + } + return false; + } + public boolean hasClusterPriv(ConnectContext ctx, String clusterName) { for (PrivEntry entry : entries) { DbPrivEntry dbPrivEntry = (DbPrivEntry) entry; diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PaloAuth.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PaloAuth.java index 9459f14ed9..e54232e024 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PaloAuth.java +++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PaloAuth.java @@ -353,6 +353,35 @@ public class PaloAuth implements Writable { return false; } + public boolean checkCtlPriv(ConnectContext ctx, String ctl, PrivPredicate wanted) { + return checkCtlPriv(ctx.getCurrentUserIdentity(), ctl, wanted); + } + + public boolean checkCtlPriv(UserIdentity currentUser, String ctl, PrivPredicate wanted) { + if (!Config.enable_auth_check) { + return true; + } + if (wanted.getPrivs().containsNodePriv()) { + LOG.debug("should not check NODE priv in catalog level. user: {}, catalog: {}", + currentUser, ctl); + return false; + } + + PrivBitSet savedPrivs = PrivBitSet.of(); + if (checkGlobalInternal(currentUser, wanted, savedPrivs) + || checkCatalogInternal(currentUser, ctl, wanted, savedPrivs)) { + return true; + } + + // if user has any privs of databases or tables in this catalog, and the wanted priv is SHOW, return true + if (ctl != null && wanted == PrivPredicate.SHOW && checkAnyPrivWithinCatalog(currentUser, ctl)) { + return true; + } + + LOG.debug("failed to get wanted privs: {}, granted: {}", wanted, savedPrivs); + return false; + } + public boolean checkDbPriv(ConnectContext ctx, String qualifiedDb, PrivPredicate wanted) { return checkDbPriv(ctx.getCurrentUserIdentity(), qualifiedDb, wanted); } @@ -361,6 +390,10 @@ public class PaloAuth implements Writable { return checkDbPriv(currentUser, DEFAULT_CATALOG, db, wanted); } + public boolean checkDbPriv(ConnectContext ctx, String ctl, String db, PrivPredicate wanted) { + return checkDbPriv(ctx.getCurrentUserIdentity(), ctl, db, wanted); + } + /* * Check if 'user'@'host' on 'db' has 'wanted' priv. * If the given db is null, which means it will no check if database name is matched. @@ -383,7 +416,7 @@ public class PaloAuth implements Writable { } // if user has any privs of table in this db, and the wanted priv is SHOW, return true - if (ctl != null && db != null && wanted == PrivPredicate.SHOW && checkTblWithDb(currentUser, ctl, db)) { + if (ctl != null && db != null && wanted == PrivPredicate.SHOW && checkAnyPrivWithinDb(currentUser, ctl, db)) { return true; } @@ -391,12 +424,27 @@ public class PaloAuth implements Writable { return false; } + /* + * User may not have privs on a catalog, but have privs of databases or tables in this catalog. + * So we have to check if user has any privs of databases or tables in this catalog. + * if so, the catalog should be visible to this user. + */ + private boolean checkAnyPrivWithinCatalog(UserIdentity currentUser, String ctl) { + readLock(); + try { + return dbPrivTable.hasPrivsOfCatalog(currentUser, ctl) + || tablePrivTable.hasPrivsOfCatalog(currentUser, ctl); + } finally { + readUnlock(); + } + } + /* * User may not have privs on a database, but have privs of tables in this database. * So we have to check if user has any privs of tables in this database. * if so, the database should be visible to this user. */ - private boolean checkTblWithDb(UserIdentity currentUser, String ctl, String db) { + private boolean checkAnyPrivWithinDb(UserIdentity currentUser, String ctl, String db) { readLock(); try { return (isLdapAuthEnabled() && LdapPrivsChecker.hasPrivsOfDb(currentUser, db)) diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/TablePrivTable.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/TablePrivTable.java index 475452ac29..c4ded036f1 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/TablePrivTable.java +++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/TablePrivTable.java @@ -69,6 +69,23 @@ public class TablePrivTable extends PrivTable { savedPrivs.or(matchedEntry.getPrivSet()); } + public boolean hasPrivsOfCatalog(UserIdentity currentUser, String ctl) { + for (PrivEntry entry : entries) { + TablePrivEntry tblPrivEntry = (TablePrivEntry) entry; + + if (!tblPrivEntry.match(currentUser, true)) { + continue; + } + + // check catalog + Preconditions.checkState(!tblPrivEntry.isAnyCtl()); + if (tblPrivEntry.getCtlPattern().match(ctl)) { + return true; + } + } + return false; + } + public boolean hasPrivsOfDb(UserIdentity currentUser, String ctl, String db) { for (PrivEntry entry : entries) { TablePrivEntry tblPrivEntry = (TablePrivEntry) entry; diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java index e9e6d4e215..ba4ab0d200 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java @@ -44,6 +44,7 @@ import org.apache.doris.analysis.SqlScanner; import org.apache.doris.analysis.StatementBase; import org.apache.doris.analysis.StmtRewriter; import org.apache.doris.analysis.StringLiteral; +import org.apache.doris.analysis.SwitchStmt; import org.apache.doris.analysis.TransactionBeginStmt; import org.apache.doris.analysis.TransactionCommitStmt; import org.apache.doris.analysis.TransactionRollbackStmt; @@ -414,6 +415,8 @@ public class StmtExecutor implements ProfileWriter { handleSetStmt(); } else if (parsedStmt instanceof EnterStmt) { handleEnterStmt(); + } else if (parsedStmt instanceof SwitchStmt) { + handleSwitchStmt(); } else if (parsedStmt instanceof UseStmt) { handleUseStmt(); } else if (parsedStmt instanceof TransactionStmt) { @@ -1410,6 +1413,18 @@ public class StmtExecutor implements ProfileWriter { context.getState().setOk(); } + // Process switch catalog + private void handleSwitchStmt() throws AnalysisException { + SwitchStmt switchStmt = (SwitchStmt) parsedStmt; + try { + context.getCatalog().changeCatalog(context, switchStmt.getCatalogName()); + } catch (DdlException e) { + context.getState().setError(e.getMysqlErrorCode(), e.getMessage()); + return; + } + context.getState().setOk(); + } + // Process use statement. private void handleUseStmt() throws AnalysisException { UseStmt useStmt = (UseStmt) parsedStmt; diff --git a/fe/fe-core/src/main/jflex/sql_scanner.flex b/fe/fe-core/src/main/jflex/sql_scanner.flex index f7d3638c2a..ecc4a59b65 100644 --- a/fe/fe-core/src/main/jflex/sql_scanner.flex +++ b/fe/fe-core/src/main/jflex/sql_scanner.flex @@ -435,6 +435,7 @@ import org.apache.doris.qe.SqlModeHelper; keywordMap.put("not_null", new Integer(SqlParserSymbols.KW_NOT_NULL)); keywordMap.put("catalog", new Integer(SqlParserSymbols.KW_CATALOG)); keywordMap.put("catalogs", new Integer(SqlParserSymbols.KW_CATALOGS)); + keywordMap.put("switch", new Integer(SqlParserSymbols.KW_SWITCH)); } // map from token id to token description diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterCatalogNameStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterCatalogNameStmtTest.java index c7f3e393d0..25c05d05dd 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterCatalogNameStmtTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterCatalogNameStmtTest.java @@ -43,7 +43,7 @@ public class AlterCatalogNameStmtTest { Config.enable_multi_catalog = true; analyzer = AccessTestUtil.fetchAdminAnalyzer(false); MockedAuth.mockedAuth(auth); - MockedAuth.mockedConnectContext(ctx, "root", "127.0.0.1"); + MockedAuth.mockedConnectContext(ctx, "root", "%"); } @Test diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterCatalogPropsStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterCatalogPropsStmtTest.java index 821d65498a..d1b8f09b55 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterCatalogPropsStmtTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterCatalogPropsStmtTest.java @@ -46,7 +46,7 @@ public class AlterCatalogPropsStmtTest { Config.enable_multi_catalog = true; analyzer = AccessTestUtil.fetchAdminAnalyzer(false); MockedAuth.mockedAuth(auth); - MockedAuth.mockedConnectContext(ctx, "root", "127.0.0.1"); + MockedAuth.mockedConnectContext(ctx, "root", "%"); } @Test diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateCatalogStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateCatalogStmtTest.java index 4d61e6c219..1313991c03 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateCatalogStmtTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateCatalogStmtTest.java @@ -47,7 +47,7 @@ public class CreateCatalogStmtTest { Config.enable_multi_catalog = true; analyzer = AccessTestUtil.fetchAdminAnalyzer(true); MockedAuth.mockedAuth(auth); - MockedAuth.mockedConnectContext(ctx, "root", "127.0.0.1"); + MockedAuth.mockedConnectContext(ctx, "root", "%"); } @Test diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/DropCatalogStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/DropCatalogStmtTest.java index 36357bfc7e..5ff0ce6056 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/analysis/DropCatalogStmtTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/DropCatalogStmtTest.java @@ -44,7 +44,7 @@ public class DropCatalogStmtTest { Config.enable_multi_catalog = true; analyzer = AccessTestUtil.fetchAdminAnalyzer(true); MockedAuth.mockedAuth(auth); - MockedAuth.mockedConnectContext(ctx, "root", "127.0.0.1"); + MockedAuth.mockedConnectContext(ctx, "root", "%"); } @Test diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/SwitchStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/SwitchStmtTest.java new file mode 100644 index 0000000000..d90a8a68d2 --- /dev/null +++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/SwitchStmtTest.java @@ -0,0 +1,161 @@ +// 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.AnalysisException; +import org.apache.doris.common.Config; +import org.apache.doris.datasource.InternalDataSource; +import org.apache.doris.mysql.privilege.PaloAuth; +import org.apache.doris.qe.ConnectContext; +import org.apache.doris.utframe.DorisAssert; +import org.apache.doris.utframe.UtFrameUtils; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.List; +import java.util.UUID; + +public class SwitchStmtTest { + private static String runningDir = "fe/mocked/DemoTest/" + UUID.randomUUID().toString() + "/"; + private static DorisAssert dorisAssert; + private static String clusterName = "default_cluster"; + + private static PaloAuth auth; + private static Catalog catalog; + private static UserIdentity user1; + private static UserIdentity user2; + + @AfterClass + public static void tearDown() throws Exception { + UtFrameUtils.cleanDorisFeDir(runningDir); + } + + @BeforeClass + public static void setUp() throws Exception { + Config.enable_multi_catalog = true; + UtFrameUtils.createDorisCluster(runningDir); + + // use root to initialize. + ConnectContext rootCtx = UtFrameUtils.createDefaultCtx(); + catalog = Catalog.getCurrentCatalog(); + auth = catalog.getAuth(); + + // grant with no catalog is switched, internal catalog works. + CreateRoleStmt createRole1 = (CreateRoleStmt) UtFrameUtils.parseAndAnalyzeStmt("create role role1;", rootCtx); + auth.createRole(createRole1); + GrantStmt grantRole1 = (GrantStmt) UtFrameUtils.parseAndAnalyzeStmt( + "grant grant_priv on tpch.* to role 'role1';", rootCtx); + auth.grant(grantRole1); + // user1 can't switch to hive + auth.createUser((CreateUserStmt) UtFrameUtils.parseAndAnalyzeStmt( + "create user 'user1'@'%' identified by 'pwd1' default role 'role1';", rootCtx)); + user1 = new UserIdentity("user1", "%"); + user1.analyze(clusterName); + + // create catalog + CreateCatalogStmt hiveCatalog = (CreateCatalogStmt) UtFrameUtils.parseAndAnalyzeStmt( + "create catalog hive properties('type' = 'hms', 'hive.metastore.uris' = 'thrift://192.168.0.1:9083');", + rootCtx); + catalog.getDataSourceMgr().createCatalog(hiveCatalog); + CreateCatalogStmt iceBergCatalog = (CreateCatalogStmt) UtFrameUtils.parseAndAnalyzeStmt( + "create catalog iceberg properties('type' = 'hms', 'iceberg.hive.metastore.uris' = 'thrift://192.168.0.1:9083');", + rootCtx); + catalog.getDataSourceMgr().createCatalog(iceBergCatalog); + + // switch to hive. + SwitchStmt switchHive = (SwitchStmt) UtFrameUtils.parseAndAnalyzeStmt("switch hive;", rootCtx); + catalog.changeCatalog(rootCtx, switchHive.getCatalogName()); + CreateRoleStmt createRole2 = (CreateRoleStmt) UtFrameUtils.parseAndAnalyzeStmt("create role role2;", rootCtx); + auth.createRole(createRole2); + GrantStmt grantRole2 = (GrantStmt) UtFrameUtils.parseAndAnalyzeStmt( + "grant grant_priv on tpch.customer to role 'role2';", rootCtx); + auth.grant(grantRole2); + auth.createUser((CreateUserStmt) UtFrameUtils.parseAndAnalyzeStmt( + "create user 'user2'@'%' identified by 'pwd2' default role 'role2';", rootCtx)); + user2 = new UserIdentity("user2", "%"); + user2.analyze(clusterName); + } + + @Test + public void testSwitchCommand() throws Exception { + // mock the login of user1 + ConnectContext user1Ctx = UtFrameUtils.createDefaultCtx(user1, "127.0.0.1"); + // user1 can switch to internal catalog + UtFrameUtils.parseAndAnalyzeStmt("switch " + InternalDataSource.INTERNAL_DS_NAME + ";", user1Ctx); + Assert.assertEquals(InternalDataSource.INTERNAL_DS_NAME, user1Ctx.getDefaultCatalog()); + // user1 can't switch to hive + try { + UtFrameUtils.parseAndAnalyzeStmt("switch hive;", user1Ctx); + Assert.fail("user1 switch to hive with no privilege."); + } catch (AnalysisException e) { + Assert.assertEquals(e.getMessage(), + "errCode = 2, detailMessage = Access denied for user 'default_cluster:user1' to catalog 'hive'"); + } + Assert.assertEquals(InternalDataSource.INTERNAL_DS_NAME, user1Ctx.getDefaultCatalog()); + + // mock the login of user2 + ConnectContext user2Ctx = UtFrameUtils.createDefaultCtx(user2, "127.0.0.1"); + // user2 can switch to internal catalog + UtFrameUtils.parseAndAnalyzeStmt("switch " + InternalDataSource.INTERNAL_DS_NAME + ";", user2Ctx); + Assert.assertEquals(InternalDataSource.INTERNAL_DS_NAME, user2Ctx.getDefaultCatalog()); + // user2 can switch to hive + SwitchStmt switchHive = (SwitchStmt) UtFrameUtils.parseAndAnalyzeStmt("switch hive;", user2Ctx); + catalog.changeCatalog(user2Ctx, switchHive.getCatalogName()); + Assert.assertEquals(user2Ctx.getDefaultCatalog(), "hive"); + // user2 can grant select_priv to tpch.customer + GrantStmt user2GrantHiveTable = (GrantStmt) UtFrameUtils.parseAndAnalyzeStmt( + "grant select_priv on tpch.customer to 'user2'@'%';", user2Ctx); + auth.grant(user2GrantHiveTable); + } + + @Test + public void testShowCatalogStmtWithPrivileges() throws Exception { + // mock the login of user1 + ConnectContext user1Ctx = UtFrameUtils.createDefaultCtx(user1, "127.0.0.1"); + ShowCatalogStmt user1Show = (ShowCatalogStmt) UtFrameUtils.parseAndAnalyzeStmt("show catalogs;", user1Ctx); + List<List<String>> user1ShowResult = catalog.getDataSourceMgr().showCatalogs(user1Show).getResultRows(); + Assert.assertEquals(user1ShowResult.size(), 1); + Assert.assertEquals(user1ShowResult.get(0).get(0), InternalDataSource.INTERNAL_DS_NAME); + + // mock the login of user1 + ConnectContext user2Ctx = UtFrameUtils.createDefaultCtx(user2, "127.0.0.1"); + ShowCatalogStmt user2Show = (ShowCatalogStmt) UtFrameUtils.parseAndAnalyzeStmt("show catalogs;", user2Ctx); + List<List<String>> user2ShowResult = catalog.getDataSourceMgr().showCatalogs(user2Show).getResultRows(); + Assert.assertEquals(user2ShowResult.size(), 2); + Assert.assertTrue(user2ShowResult.stream().map(l -> l.get(0)).anyMatch(c -> c.equals("hive"))); + + // access denied + ShowCatalogStmt user2ShowHive = (ShowCatalogStmt) UtFrameUtils.parseAndAnalyzeStmt("show catalog hive;", + user2Ctx); + List<List<String>> user2ShowHiveResult = catalog.getDataSourceMgr().showCatalogs(user2ShowHive).getResultRows(); + Assert.assertTrue( + user2ShowHiveResult.stream().map(l -> l.get(0)).anyMatch(c -> c.equals("hive.metastore.uris"))); + try { + catalog.getDataSourceMgr().showCatalogs( + (ShowCatalogStmt) UtFrameUtils.parseAndAnalyzeStmt("show catalog iceberg;", user2Ctx)); + Assert.fail(""); + } catch (AnalysisException e) { + Assert.assertEquals(e.getMessage(), + "errCode = 2, detailMessage = Access denied for user 'default_cluster:user2' to catalog 'iceberg'"); + } + } +} diff --git a/fe/fe-core/src/test/java/org/apache/doris/utframe/UtFrameUtils.java b/fe/fe-core/src/test/java/org/apache/doris/utframe/UtFrameUtils.java index 9bbf6278b7..e822667383 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/utframe/UtFrameUtils.java +++ b/fe/fe-core/src/test/java/org/apache/doris/utframe/UtFrameUtils.java @@ -31,7 +31,6 @@ import org.apache.doris.common.Config; import org.apache.doris.common.DdlException; import org.apache.doris.common.FeConstants; import org.apache.doris.common.util.SqlParserUtils; -import org.apache.doris.mysql.privilege.PaloAuth; import org.apache.doris.planner.Planner; import org.apache.doris.qe.ConnectContext; import org.apache.doris.qe.OriginStatement; @@ -74,18 +73,23 @@ import java.util.UUID; public class UtFrameUtils { // Help to create a mocked ConnectContext. - public static ConnectContext createDefaultCtx() throws IOException { + public static ConnectContext createDefaultCtx(UserIdentity userIdentity, String remoteIp) throws IOException { SocketChannel channel = SocketChannel.open(); ConnectContext ctx = new ConnectContext(channel); ctx.setCluster(SystemInfoService.DEFAULT_CLUSTER); - ctx.setCurrentUserIdentity(UserIdentity.ROOT); - ctx.setQualifiedUser(PaloAuth.ROOT_USER); - ctx.setRemoteIP("127.0.0.1"); + ctx.setCurrentUserIdentity(userIdentity); + ctx.setQualifiedUser(userIdentity.getQualifiedUser()); + ctx.setRemoteIP(remoteIp); ctx.setCatalog(Catalog.getCurrentCatalog()); ctx.setThreadLocalInfo(); return ctx; } + // Help to create a mocked ConnectContext for root. + public static ConnectContext createDefaultCtx() throws IOException { + return createDefaultCtx(UserIdentity.ROOT, "127.0.0.1"); + } + // Parse an origin stmt and analyze it. Return a StatementBase instance. public static StatementBase parseAndAnalyzeStmt(String originStmt, ConnectContext ctx) throws Exception { --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org