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 <[email protected]>
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: [email protected]
For additional commands, e-mail: [email protected]