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 4cd0dae4b30 [improvement](auth) support show all properties (#25645) 4cd0dae4b30 is described below commit 4cd0dae4b3033e851b3f0b736f083e426dec2d8e Author: zhangdong <493738...@qq.com> AuthorDate: Tue Oct 24 17:27:59 2023 +0800 [improvement](auth) support show all properties (#25645) support `show all properties` --- .../sql-reference/Show-Statements/SHOW-PROPERTY.md | 35 +++++++++- .../sql-reference/Show-Statements/SHOW-PROPERTY.md | 33 ++++++++- fe/fe-core/src/main/cup/sql_parser.cup | 6 +- .../doris/analysis/ShowUserPropertyStmt.java | 78 +++++++++++++++++++--- .../doris/common/proc/UserPropertyProcNode.java | 4 ++ .../org/apache/doris/mysql/privilege/Auth.java | 3 + .../doris/analysis/ShowUserPropertyStmtTest.java | 36 +++++++++- 7 files changed, 177 insertions(+), 18 deletions(-) diff --git a/docs/en/docs/sql-manual/sql-reference/Show-Statements/SHOW-PROPERTY.md b/docs/en/docs/sql-manual/sql-reference/Show-Statements/SHOW-PROPERTY.md index 8eef274fa2d..9068a575b5c 100644 --- a/docs/en/docs/sql-manual/sql-reference/Show-Statements/SHOW-PROPERTY.md +++ b/docs/en/docs/sql-manual/sql-reference/Show-Statements/SHOW-PROPERTY.md @@ -31,7 +31,8 @@ under the License. This statement is used to view the attributes of the user ``` -SHOW PROPERTY [FOR user] [LIKE key]; +SHOW PROPERTY [FOR user] [LIKE key] +SHOW ALL PROPERTIES [LIKE key] ``` * `user` @@ -42,6 +43,10 @@ SHOW PROPERTY [FOR user] [LIKE key]; Fuzzy matching can be done by attribute name. +* `ALL` + + View the properties of all users (supported since version 2.0.3) + Return result description: ```sql @@ -62,6 +67,26 @@ mysql> show property like'%connection%'; Attribute value. + +```sql +mysql> show all properties like "%connection%"; ++-------------------+--------------------------------------+ +| User | Properties | ++-------------------+--------------------------------------+ +| root | {"max_user_connections": "100"} | +| admin | {"max_user_connections": "100"} | +| default_cluster:a | {"max_user_connections": "1000"} | ++-------------------+--------------------------------------+ +``` + +* `User` + + username. + +* `Properties` + + Key: value corresponding to each property of the user. + ### Example 1. View the attributes of the jack user @@ -76,8 +101,14 @@ mysql> show property like'%connection%'; SHOW PROPERTY FOR'jack' LIKE'%connection%'; ``` +3. View all users importing cluster related properties + + ```sql + SHOW ALL PROPERTIES LIKE '%load_cluster%' + ``` + ### Keywords - SHOW, PROPERTY + SHOW, PROPERTY, ALL ### Best Practice diff --git a/docs/zh-CN/docs/sql-manual/sql-reference/Show-Statements/SHOW-PROPERTY.md b/docs/zh-CN/docs/sql-manual/sql-reference/Show-Statements/SHOW-PROPERTY.md index 82ca0aa97d2..8f5685e2fe3 100644 --- a/docs/zh-CN/docs/sql-manual/sql-reference/Show-Statements/SHOW-PROPERTY.md +++ b/docs/zh-CN/docs/sql-manual/sql-reference/Show-Statements/SHOW-PROPERTY.md @@ -38,6 +38,7 @@ SHOW PROPERTY ```sql SHOW PROPERTY [FOR user] [LIKE key] +SHOW ALL PROPERTIES [LIKE key] ``` * `user` @@ -48,6 +49,10 @@ SHOW PROPERTY [FOR user] [LIKE key] 模糊匹配可以通过属性名来完成。 +* `ALL` + + 查看所有用户的属性(从2.0.3版本开始支持) + 返回结果说明: ```sql @@ -68,6 +73,26 @@ mysql> show property like'%connection%'; 属性值. + +```sql +mysql> show all properties like "%connection%"; ++-------------------+--------------------------------------+ +| User | Properties | ++-------------------+--------------------------------------+ +| root | {"max_user_connections": "100"} | +| admin | {"max_user_connections": "100"} | +| default_cluster:a | {"max_user_connections": "1000"} | ++-------------------+--------------------------------------+ +``` + +* `User` + + 用户名. + +* `Properties` + + 对应用户各个property的key:value. + ### Example 1. 查看 jack 用户的属性 @@ -82,8 +107,14 @@ mysql> show property like'%connection%'; SHOW PROPERTY FOR 'jack' LIKE '%load_cluster%' ``` +3. 查看所有用户导入cluster相关属性 + + ```sql + SHOW ALL PROPERTIES LIKE '%load_cluster%' + ``` + ### Keywords - SHOW, PROPERTY + SHOW, PROPERTY, ALL ### Best Practice diff --git a/fe/fe-core/src/main/cup/sql_parser.cup b/fe/fe-core/src/main/cup/sql_parser.cup index 930bbbbd97f..b0d487a6ca3 100644 --- a/fe/fe-core/src/main/cup/sql_parser.cup +++ b/fe/fe-core/src/main/cup/sql_parser.cup @@ -4122,7 +4122,11 @@ show_param ::= :} | KW_PROPERTY opt_user:user opt_wild_where {: - RESULT = new ShowUserPropertyStmt(user, parser.wild); + RESULT = new ShowUserPropertyStmt(user, parser.wild, false); + :} + | KW_ALL KW_PROPERTIES opt_wild_where + {: + RESULT = new ShowUserPropertyStmt(null, parser.wild, true); :} | KW_BACKUP opt_db:db opt_wild_where {: diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowUserPropertyStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowUserPropertyStmt.java index e6ed8f3670a..0c83376e048 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowUserPropertyStmt.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowUserPropertyStmt.java @@ -30,39 +30,55 @@ import org.apache.doris.common.PatternMatcherWrapper; import org.apache.doris.common.UserException; import org.apache.doris.common.proc.UserPropertyProcNode; import org.apache.doris.mysql.privilege.PrivPredicate; +import org.apache.doris.persist.gson.GsonUtils; import org.apache.doris.qe.ConnectContext; import org.apache.doris.qe.ShowResultSetMetaData; import com.google.common.base.Strings; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.util.List; +import java.util.Map; +import java.util.Set; // Show Property Stmt // syntax: -// SHOW PROPERTY [FOR user] [LIKE key pattern] +// SHOW [ALL] PROPERTY [FOR user] [LIKE key pattern] public class ShowUserPropertyStmt extends ShowStmt { private static final Logger LOG = LogManager.getLogger(ShowUserPropertyStmt.class); private String user; private String pattern; + private boolean isAll; - public ShowUserPropertyStmt(String user, String pattern) { + public ShowUserPropertyStmt(String user, String pattern, boolean isAll) { this.user = user; this.pattern = pattern; + this.isAll = isAll; } @Override public void analyze(Analyzer analyzer) throws AnalysisException, UserException { super.analyze(analyzer); - if (Strings.isNullOrEmpty(user)) { - user = analyzer.getQualifiedUser(); - // user can see itself's property, no need to check privs - } else { + boolean needCheckAuth = true; + if (!Strings.isNullOrEmpty(user)) { + if (isAll) { + throw new AnalysisException("Can not specified keyword ALL when specified user"); + } user = ClusterNamespace.getFullName(getClusterName(), user); + } else { + if (!isAll) { + // self + user = analyzer.getQualifiedUser(); + // user can see itself's property, no need to check privs + needCheckAuth = false; + } + } + if (needCheckAuth) { if (!Env.getCurrentEnv().getAccessManager().checkGlobalPriv(ConnectContext.get(), PrivPredicate.GRANT)) { ErrorReport.reportAnalysisException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR, "GRANT"); } @@ -72,6 +88,10 @@ public class ShowUserPropertyStmt extends ShowStmt { } public List<List<String>> getRows() throws AnalysisException { + return isAll ? getRowsForAllUser() : getRowsForOneUser(); + } + + public List<List<String>> getRowsForOneUser() throws AnalysisException { List<List<String>> rows = Env.getCurrentEnv().getAuth().getUserProperties(user); if (pattern == null) { @@ -91,10 +111,42 @@ public class ShowUserPropertyStmt extends ShowStmt { return result; } + public List<List<String>> getRowsForAllUser() throws AnalysisException { + Set<String> allUser = Env.getCurrentEnv().getAuth().getAllUser(); + List<List<String>> result = Lists.newArrayListWithCapacity(allUser.size()); + + for (String user : allUser) { + List<String> row = Lists.newArrayListWithCapacity(2); + row.add(user); + row.add(GsonUtils.GSON.toJson(getRowsForUser(user))); + result.add(row); + } + return result; + } + + private Map<String, String> getRowsForUser(String user) throws AnalysisException { + Map<String, String> result = Maps.newHashMap(); + List<List<String>> userProperties = Env.getCurrentEnv().getAuth() + .getUserProperties(ClusterNamespace.getFullName(getClusterName(), user)); + PatternMatcher matcher = null; + if (pattern != null) { + matcher = PatternMatcherWrapper.createMysqlPattern(pattern, + CaseSensibility.USER.getCaseSensibility()); + } + + for (List<String> row : userProperties) { + String key = row.get(0).split("\\" + SetUserPropertyVar.DOT_SEPARATOR)[0]; + if (matcher == null || matcher.match(key)) { + result.put(row.get(0), row.get(1)); + } + } + return result; + } + @Override public ShowResultSetMetaData getMetaData() { ShowResultSetMetaData.Builder builder = ShowResultSetMetaData.builder(); - for (String col : UserPropertyProcNode.TITLE_NAMES) { + for (String col : isAll ? UserPropertyProcNode.ALL_USER_TITLE_NAMES : UserPropertyProcNode.TITLE_NAMES) { builder.addColumn(new Column(col, ScalarType.createVarchar(30))); } return builder.build(); @@ -103,10 +155,14 @@ public class ShowUserPropertyStmt extends ShowStmt { @Override public String toSql() { StringBuilder sb = new StringBuilder(); - sb.append("SHOW PROPERTY FOR '"); - sb.append(user); - sb.append("'"); - + sb.append("SHOW "); + if (isAll) { + sb.append("ALL PROPERTIES"); + } else { + sb.append("PROPERTY FOR '"); + sb.append(user); + sb.append("'"); + } if (pattern != null) { sb.append(" LIKE '"); sb.append(pattern); diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/proc/UserPropertyProcNode.java b/fe/fe-core/src/main/java/org/apache/doris/common/proc/UserPropertyProcNode.java index 6a8c9eaec3f..db4ad520be4 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/common/proc/UserPropertyProcNode.java +++ b/fe/fe-core/src/main/java/org/apache/doris/common/proc/UserPropertyProcNode.java @@ -31,6 +31,10 @@ public class UserPropertyProcNode implements ProcNodeInterface { .add("Key").add("Value") .build(); + public static final ImmutableList<String> ALL_USER_TITLE_NAMES = new ImmutableList.Builder<String>() + .add("User").add("Properties") + .build(); + private Auth auth; private UserIdentity userIdent; diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Auth.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Auth.java index 9ebf6075aed..d07ba404c25 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Auth.java +++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Auth.java @@ -1581,6 +1581,9 @@ public class Auth implements Writable { userRoleManager.addUserRole(userIdent, roleManager.getUserDefaultRoleName(userIdent)); } + public Set<String> getAllUser() { + return userManager.getNameToUsers().keySet(); + } /** * This is a bug that if created a normal user and grant it with ADMIN_PRIV/RESOURCE_PRIV/NODE_PRIV diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/ShowUserPropertyStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/ShowUserPropertyStmtTest.java index 3e88d9884fb..53b63a568b0 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/analysis/ShowUserPropertyStmtTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/ShowUserPropertyStmtTest.java @@ -17,8 +17,9 @@ package org.apache.doris.analysis; -import org.apache.doris.common.AnalysisException; +import org.apache.doris.catalog.Column; import org.apache.doris.common.UserException; +import org.apache.doris.common.proc.UserPropertyProcNode; import org.apache.doris.mysql.privilege.AccessControllerManager; import org.apache.doris.mysql.privilege.MockedAuth; import org.apache.doris.qe.ConnectContext; @@ -28,6 +29,8 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import java.util.List; + public class ShowUserPropertyStmtTest { private Analyzer analyzer; @@ -44,9 +47,36 @@ public class ShowUserPropertyStmtTest { } @Test - public void testNormal() throws UserException, AnalysisException { - ShowUserPropertyStmt stmt = new ShowUserPropertyStmt("testUser", "%load_cluster%"); + public void testNormal() throws UserException { + ShowUserPropertyStmt stmt = new ShowUserPropertyStmt("testUser", "%load_cluster%", false); stmt.analyze(analyzer); Assert.assertEquals("SHOW PROPERTY FOR 'testCluster:testUser' LIKE '%load_cluster%'", stmt.toString()); + List<Column> columns = stmt.getMetaData().getColumns(); + for (int i = 0; i < columns.size(); i++) { + Assert.assertEquals(columns.get(i).getName(), UserPropertyProcNode.TITLE_NAMES.get(i)); + } + } + + @Test + public void testAll() throws UserException { + ShowUserPropertyStmt stmt = new ShowUserPropertyStmt(null, "%load_cluster%", true); + stmt.analyze(analyzer); + Assert.assertEquals("SHOW ALL PROPERTIES LIKE '%load_cluster%'", stmt.toString()); + List<Column> columns = stmt.getMetaData().getColumns(); + for (int i = 0; i < columns.size(); i++) { + Assert.assertEquals(columns.get(i).getName(), UserPropertyProcNode.ALL_USER_TITLE_NAMES.get(i)); + } + } + + @Test + public void testError() { + ShowUserPropertyStmt stmt = new ShowUserPropertyStmt("testUser", "%load_cluster%", true); + try { + stmt.analyze(analyzer); + Assert.fail(); + } catch (UserException e) { + Assert.assertTrue(e.getMessage().contains("ALL")); + } + } } --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org