You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by mo...@apache.org on 2022/04/28 02:30:02 UTC

[incubator-doris] 02/09: [improvement](account) support to account management sql (#8849)

This is an automated email from the ASF dual-hosted git repository.

morningman pushed a commit to branch dev-1.0.1
in repository https://gitbox.apache.org/repos/asf/incubator-doris.git

commit eefe8ceab074fcdf509db56b4cc43e037c65ccab
Author: Jiading Guo <zi...@gmail.com>
AuthorDate: Fri Apr 8 09:08:08 2022 +0800

    [improvement](account) support to account management sql (#8849)
    
    Add [IF EXISTS] support to following statements:
    - CREATE [IF NOT EXISTS] USER
    - CREATE [IF NOT EXISTS] ROLE
    - DROP [IF EXISTS] USER
    - DROP [IF EXISTS] ROLE
---
 .../Account Management/CREATE ROLE.md              |  14 +--
 .../Account Management/CREATE USER.md              |  26 ++--
 .../sql-statements/Account Management/DROP ROLE.md |  16 +--
 .../sql-statements/Account Management/DROP USER.md |   6 +-
 fe/fe-core/src/main/cup/sql_parser.cup             |  12 +-
 .../org/apache/doris/analysis/CreateRoleStmt.java  |  10 ++
 .../org/apache/doris/analysis/DropRoleStmt.java    |  10 ++
 .../org/apache/doris/analysis/DropUserStmt.java    |  11 ++
 .../java/org/apache/doris/catalog/Catalog.java     |   2 +-
 .../org/apache/doris/mysql/privilege/PaloAuth.java |  67 ++++++----
 .../org/apache/doris/mysql/privilege/AuthTest.java | 140 ++++++++++++++++++++-
 11 files changed, 254 insertions(+), 60 deletions(-)

diff --git a/docs/zh-CN/sql-reference/sql-statements/Account Management/CREATE ROLE.md b/docs/zh-CN/sql-reference/sql-statements/Account Management/CREATE ROLE.md
index 6b430a2037..f8f4879d1c 100644
--- a/docs/zh-CN/sql-reference/sql-statements/Account Management/CREATE ROLE.md	
+++ b/docs/zh-CN/sql-reference/sql-statements/Account Management/CREATE ROLE.md	
@@ -5,7 +5,7 @@
 }
 ---
 
-<!-- 
+<!--
 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
@@ -27,19 +27,19 @@ under the License.
 # CREATE ROLE
 ## description
     该语句用户创建一个角色
-    
+
     语法:
-        CREATE ROLE role1;
-        
+        CREATE ROLE [IF NOT EXISTS] role1;
+
     该语句创建一个无权限的角色,可以后续通过 GRANT 命令赋予该角色权限。
     
 ## example
 
     1. 创建一个角色
-   
+
         CREATE ROLE role1;
-        
+
 ## keyword
 
     CREATE, ROLE
-   
+
diff --git a/docs/zh-CN/sql-reference/sql-statements/Account Management/CREATE USER.md b/docs/zh-CN/sql-reference/sql-statements/Account Management/CREATE USER.md
index 2222e987ef..7acb73e05d 100644
--- a/docs/zh-CN/sql-reference/sql-statements/Account Management/CREATE USER.md	
+++ b/docs/zh-CN/sql-reference/sql-statements/Account Management/CREATE USER.md	
@@ -5,7 +5,7 @@
 }
 ---
 
-<!-- 
+<!--
 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
@@ -28,40 +28,40 @@ under the License.
 ## description
 
 Syntax:
-    
-    CREATE USER user_identity [IDENTIFIED BY 'password'] [DEFAULT ROLE 'role_name']
+
+    CREATE USER [IF NOT EXISTS] user_identity [IDENTIFIED BY 'password'] [DEFAULT ROLE 'role_name']
 
     user_identity:
         'user_name'@'host'
-        
+
 CREATE USER 命令用于创建一个 Doris 用户。在 Doris 中,一个 user_identity 唯一标识一个用户。user_identity 由两部分组成,user_name 和 host,其中 username 为用户名。host 标识用户端连接所在的主机地址。host 部分可以使用 % 进行模糊匹配。如果不指定 host,默认为 '%',即表示该用户可以从任意 host 连接到 Doris。
-    
+
 host 部分也可指定为 domain,语法为:'user_name'@['domain'],即使用中括号包围,则 Doris 会认为这个是一个 domain,并尝试解析其 ip 地址。目前仅支持百度内部的 BNS 解析。
-    
+
 如果指定了角色(ROLE),则会自动将该角色所拥有的权限赋予新创建的这个用户。如果不指定,则该用户默认没有任何权限。指定的 ROLE 必须已经存在。
 
 ## example
 
 1. 创建一个无密码用户(不指定 host,则等价于 jack@'%')
-   
+
     CREATE USER 'jack';
 
 2. 创建一个有密码用户,允许从 '172.10.1.10' 登陆
-   
+
     CREATE USER jack@'172.10.1.10' IDENTIFIED BY '123456';
 
 3. 为了避免传递明文,用例2也可以使用下面的方式来创建
-   
+
     CREATE USER jack@'172.10.1.10' IDENTIFIED BY PASSWORD '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9';
-   
+
     后面加密的内容可以通过PASSWORD()获得到,例如:
-    
+
     SELECT PASSWORD('123456');
 
 4. 创建一个允许从 '192.168' 子网登陆的用户,同时指定其角色为 example_role
-   
+
     CREATE USER 'jack'@'192.168.%' DEFAULT ROLE 'example_role';
-        
+
 5. 创建一个允许从域名 'example_domain' 登陆的用户
 
     CREATE USER 'jack'@['example_domain'] IDENTIFIED BY '12345';
diff --git a/docs/zh-CN/sql-reference/sql-statements/Account Management/DROP ROLE.md b/docs/zh-CN/sql-reference/sql-statements/Account Management/DROP ROLE.md
index ee0cc980bc..d9cf9fca17 100644
--- a/docs/zh-CN/sql-reference/sql-statements/Account Management/DROP ROLE.md	
+++ b/docs/zh-CN/sql-reference/sql-statements/Account Management/DROP ROLE.md	
@@ -5,7 +5,7 @@
 }
 ---
 
-<!-- 
+<!--
 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
@@ -27,18 +27,18 @@ under the License.
 # DROP ROLE
 ## description
     该语句用户删除一个角色
-    
+
     语法:
-        DROP ROLE role1;
-        
+        DROP ROLE [IF EXISTS] role1;
+
     删除一个角色,不会影响之前属于该角色的用户的权限。仅相当于将该角色与用户解耦。用户已经从该角色中获取到的权限,不会改变。
-    
+
 ## example
 
     1. 删除一个角色
-   
+
         DROP ROLE role1;
-        
+
 ## keyword
-   DROP, ROLE     
+   DROP, ROLE
 
diff --git a/docs/zh-CN/sql-reference/sql-statements/Account Management/DROP USER.md b/docs/zh-CN/sql-reference/sql-statements/Account Management/DROP USER.md
index dbdebd164a..43e7fc8b12 100644
--- a/docs/zh-CN/sql-reference/sql-statements/Account Management/DROP USER.md	
+++ b/docs/zh-CN/sql-reference/sql-statements/Account Management/DROP USER.md	
@@ -5,7 +5,7 @@
 }
 ---
 
-<!-- 
+<!--
 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
@@ -29,7 +29,7 @@ under the License.
 
 Syntax:
 
-    DROP USER 'user_identity'
+    DROP USER [IF EXISTS] 'user_identity'
 
     `user_identity`:
 
@@ -41,7 +41,7 @@ Syntax:
 ## example
 
 1. 删除用户 jack@'192.%'
-   
+
     DROP USER 'jack'@'192.%'
 
 ## keyword
diff --git a/fe/fe-core/src/main/cup/sql_parser.cup b/fe/fe-core/src/main/cup/sql_parser.cup
index 529022f94a..3078d8f068 100644
--- a/fe/fe-core/src/main/cup/sql_parser.cup
+++ b/fe/fe-core/src/main/cup/sql_parser.cup
@@ -1309,9 +1309,9 @@ create_stmt ::=
     {:
         RESULT = new CreateRepositoryStmt(isReadOnly, repoName, storage);
     :}
-    | KW_CREATE KW_ROLE ident:role
+    | KW_CREATE KW_ROLE opt_if_not_exists:ifNotExists ident:role
     {:
-        RESULT = new CreateRoleStmt(role);
+        RESULT = new CreateRoleStmt(ifNotExists, role);
     :}
     | KW_CREATE KW_FILE STRING_LITERAL:fileName opt_db:db KW_PROPERTIES LPAREN key_value_map:properties RPAREN
     {:
@@ -2009,9 +2009,9 @@ drop_stmt ::=
         RESULT = new DropTableStmt(ifExists, name, force);
     :}
     /* User */
-    | KW_DROP KW_USER user_identity:userId
+    | KW_DROP KW_USER opt_if_exists:ifExists user_identity:userId
     {:
-        RESULT = new DropUserStmt(userId);
+        RESULT = new DropUserStmt(ifExists, userId);
     :}
     /* View */
     | KW_DROP KW_VIEW opt_if_exists:ifExists table_name:name
@@ -2022,9 +2022,9 @@ drop_stmt ::=
     {:
         RESULT = new DropRepositoryStmt(repoName);
     :}
-    | KW_DROP KW_ROLE ident:role
+    | KW_DROP KW_ROLE opt_if_exists:ifExists ident:role
     {:
-        RESULT = new DropRoleStmt(role);
+        RESULT = new DropRoleStmt(ifExists, role);
     :}
     | KW_DROP KW_FILE STRING_LITERAL:fileName opt_db:dbName KW_PROPERTIES LPAREN key_value_map:properties RPAREN
     {:
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateRoleStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateRoleStmt.java
index a35e10eb5b..d93632127e 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateRoleStmt.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateRoleStmt.java
@@ -28,12 +28,22 @@ import org.apache.doris.qe.ConnectContext;
 
 public class CreateRoleStmt extends DdlStmt {
 
+    private boolean ifNotExists;
     private String role;
 
     public CreateRoleStmt(String role) {
         this.role = role;
     }
 
+    public CreateRoleStmt(boolean ifNotExists, String role) {
+        this.ifNotExists = ifNotExists;
+        this.role = role;
+    }
+
+    public boolean isSetIfNotExists() {
+        return ifNotExists;
+    }
+
     public String getQualifiedRole() {
         return role;
     }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/DropRoleStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/DropRoleStmt.java
index 2852b0a2f1..522aebf4bf 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/DropRoleStmt.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/DropRoleStmt.java
@@ -28,12 +28,22 @@ import org.apache.doris.qe.ConnectContext;
 
 public class DropRoleStmt extends DdlStmt {
 
+    private boolean ifExists;
     private String role;
 
     public DropRoleStmt(String role) {
         this.role = role;
     }
 
+    public DropRoleStmt(boolean ifExists, String role) {
+        this.ifExists = ifExists;
+        this.role = role;
+    }
+
+    public boolean isSetIfExists() {
+        return ifExists;
+    }
+
     public String getQualifiedRole() {
         return role;
     }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/DropUserStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/DropUserStmt.java
index d7c5402eae..9c8453e23d 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/DropUserStmt.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/DropUserStmt.java
@@ -29,12 +29,23 @@ import org.apache.doris.qe.ConnectContext;
 // drop user cmy  <==> drop user cmy@'%'
 // drop user cmy@'192.168.1.%'
 public class DropUserStmt extends DdlStmt {
+
+    private boolean ifExists;
     private UserIdentity userIdent;
 
     public DropUserStmt(UserIdentity userIdent) {
         this.userIdent = userIdent;
     }
 
+    public DropUserStmt(boolean ifExists, UserIdentity userIdent) {
+        this.ifExists = ifExists;
+        this.userIdent = userIdent;
+    }
+
+    public boolean isSetIfExists() {
+        return ifExists;
+    }
+
     public UserIdentity getUserIdentity() {
         return userIdent;
     }
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 f115f4e63c..f3e187065a 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
@@ -6104,7 +6104,7 @@ public class Catalog {
         idToDb.remove(infoSchemaDb.getId());
     }
 
-    public void replayDropCluster(ClusterInfo info) {
+    public void replayDropCluster(ClusterInfo info) throws DdlException {
         tryLock(true);
         try {
             unprotectDropCluster(info, true/* is replay */);
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 27fc99289f..ec072bfdec 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
@@ -554,12 +554,12 @@ public class PaloAuth implements Writable {
 
     // create user
     public void createUser(CreateUserStmt stmt) throws DdlException {
-        createUserInternal(stmt.getUserIdent(), stmt.getQualifiedRole(), stmt.getPassword(), false);
+        createUserInternal(stmt.getUserIdent(), stmt.getQualifiedRole(), stmt.getPassword(), stmt.isIfNotExist(), false);
     }
 
     public void replayCreateUser(PrivInfo privInfo) {
         try {
-            createUserInternal(privInfo.getUserIdent(), privInfo.getRole(), privInfo.getPasswd(), true);
+            createUserInternal(privInfo.getUserIdent(), privInfo.getRole(), privInfo.getPasswd(), false, true);
         } catch (DdlException e) {
             LOG.error("should not happen", e);
         }
@@ -568,12 +568,12 @@ public class PaloAuth implements Writable {
     /*
      * Do following steps:
      * 1. Check does specified role exist. If not, throw exception.
-     * 2. Check does user already exist. If yes, throw exception.
+     * 2. Check does user already exist. If yes && ignoreIfExists, just return. Otherwise, throw exception.
      * 3. set password for specified user.
      * 4. grant privs of role to user, if role is specified.
      */
     private void createUserInternal(UserIdentity userIdent, String roleName, byte[] password,
-            boolean isReplay) throws DdlException {
+            boolean ignoreIfExists, boolean isReplay) throws DdlException {
         writeLock();
         try {
             // 1. check if role exist
@@ -584,9 +584,13 @@ public class PaloAuth implements Writable {
                     throw new DdlException("Role: " + roleName + " does not exist");
                 }
             }
-            
+
             // 2. check if user already exist
             if (userPrivTable.doesUserExist(userIdent)) {
+                if (ignoreIfExists) {
+                    LOG.debug("user exists, ignored to create user: {}, is replay: {}", userIdent, isReplay);
+                    return;
+                }
                 throw new DdlException("User " + userIdent + " already exist");
             }
 
@@ -646,22 +650,33 @@ public class PaloAuth implements Writable {
 
     // drop user
     public void dropUser(DropUserStmt stmt) throws DdlException {
-        dropUserInternal(stmt.getUserIdentity(), false);
+        dropUserInternal(stmt.getUserIdentity(), stmt.isSetIfExists(), false);
     }
 
-    public void replayDropUser(UserIdentity userIdent) {
-        dropUserInternal(userIdent, true);
+    public void replayDropUser(UserIdentity userIdent) throws DdlException {
+        dropUserInternal(userIdent, false, true);
     }
 
-    public void replayOldDropUser(String userName) {
+    public void replayOldDropUser(String userName) throws DdlException {
         UserIdentity userIdentity = new UserIdentity(userName, "%");
         userIdentity.setIsAnalyzed();
-        dropUserInternal(userIdentity, true /* is replay */);
+        dropUserInternal(userIdentity, false /* ignore if non exists */, true /* is replay */);
     }
 
-    private void dropUserInternal(UserIdentity userIdent, boolean isReplay) {
+    private void dropUserInternal(UserIdentity userIdent, boolean ignoreIfNonExists, boolean isReplay) throws DdlException {
         writeLock();
         try {
+            // check if user exists
+            if (!doesUserExist(userIdent)) {
+                if (ignoreIfNonExists) {
+                    LOG.info("user non exists, ignored to drop user: {}, is replay: {}",
+                            userIdent.getQualifiedUser(), isReplay);
+                    return;
+                }
+                throw new DdlException(String.format("User `%s`@`%s` does not exist.",
+                        userIdent.getQualifiedUser(), userIdent.getHost()));
+            }
+
             // we don't check if user exists
             userPrivTable.dropUser(userIdent);
             dbPrivTable.dropUser(userIdent);
@@ -1047,21 +1062,26 @@ public class PaloAuth implements Writable {
 
     // create role
     public void createRole(CreateRoleStmt stmt) throws DdlException {
-        createRoleInternal(stmt.getQualifiedRole(), false);
+        createRoleInternal(stmt.getQualifiedRole(), stmt.isSetIfNotExists(), false);
     }
 
     public void replayCreateRole(PrivInfo info) {
         try {
-            createRoleInternal(info.getRole(), true);
+            createRoleInternal(info.getRole(), false, true);
         } catch (DdlException e) {
             LOG.error("should not happened", e);
         }
     }
 
-    private void createRoleInternal(String role, boolean isReplay) throws DdlException {
+    private void createRoleInternal(String role, boolean ignoreIfExists, boolean isReplay) throws DdlException {
         PaloRole emptyPrivsRole = new PaloRole(role);
         writeLock();
         try {
+            if (ignoreIfExists && roleManager.getRole(role) != null) {
+                LOG.info("role exists, ignored to create role: {}, is replay: {}", role, isReplay);
+                return;
+            }
+
             roleManager.addRole(emptyPrivsRole, true /* err on exist */);
 
             if (!isReplay) {
@@ -1076,20 +1096,25 @@ public class PaloAuth implements Writable {
 
     // drop role
     public void dropRole(DropRoleStmt stmt) throws DdlException {
-        dropRoleInternal(stmt.getQualifiedRole(), false);
+        dropRoleInternal(stmt.getQualifiedRole(), stmt.isSetIfExists(), false);
     }
 
     public void replayDropRole(PrivInfo info) {
         try {
-            dropRoleInternal(info.getRole(), true);
+            dropRoleInternal(info.getRole(), false, true);
         } catch (DdlException e) {
             LOG.error("should not happened", e);
         }
     }
 
-    private void dropRoleInternal(String role, boolean isReplay) throws DdlException {
+    private void dropRoleInternal(String role, boolean ignoreIfNonExists, boolean isReplay) throws DdlException {
         writeLock();
         try {
+            if (ignoreIfNonExists && roleManager.getRole(role) == null) {
+                LOG.info("role non exists, ignored to drop role: {}, is replay: {}", role, isReplay);
+                return;
+            }
+
             roleManager.dropRole(role, true /* err on non exist */);
 
             if (!isReplay) {
@@ -1429,13 +1454,13 @@ public class PaloAuth implements Writable {
         }
     }
 
-    public void dropUserOfCluster(String clusterName, boolean isReplay) {
+    public void dropUserOfCluster(String clusterName, boolean isReplay) throws DdlException {
         writeLock();
         try {
             Set<UserIdentity> allUserIdents = getAllUserIdents(true);
             for (UserIdentity userIdent : allUserIdents) {
                 if (userIdent.getQualifiedUser().startsWith(clusterName)) {
-                    dropUserInternal(userIdent, isReplay);
+                    dropUserInternal(userIdent, false, isReplay);
                 }
             }
         } finally {
@@ -1478,10 +1503,10 @@ public class PaloAuth implements Writable {
         try {
             UserIdentity rootUser = new UserIdentity(ROOT_USER, "%");
             rootUser.setIsAnalyzed();
-            createUserInternal(rootUser, PaloRole.OPERATOR_ROLE, new byte[0], true /* is replay */);
+            createUserInternal(rootUser, PaloRole.OPERATOR_ROLE, new byte[0], false /* ignore if exists */, true /* is replay */);
             UserIdentity adminUser = new UserIdentity(ADMIN_USER, "%");
             adminUser.setIsAnalyzed();
-            createUserInternal(adminUser, PaloRole.ADMIN_ROLE, new byte[0], true /* is replay */);
+            createUserInternal(adminUser, PaloRole.ADMIN_ROLE, new byte[0], false /* ignore if exists */, true /* is replay */);
         } catch (DdlException e) {
             LOG.error("should not happened", e);
         }
diff --git a/fe/fe-core/src/test/java/org/apache/doris/mysql/privilege/AuthTest.java b/fe/fe-core/src/test/java/org/apache/doris/mysql/privilege/AuthTest.java
index f05a341a3d..91182dc4cf 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/mysql/privilege/AuthTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/mysql/privilege/AuthTest.java
@@ -161,6 +161,43 @@ public class AuthTest {
             Assert.fail();
         }
 
+        // 1.1 create cmy@% again with IF NOT EXISTS
+        userIdentity = new UserIdentity("cmy", "%");
+        userDesc = new UserDesc(userIdentity, "54321", true);
+        createUserStmt = new CreateUserStmt(true, userDesc, null);
+        try {
+            createUserStmt.analyze(analyzer);
+        } catch (UserException e) {
+            e.printStackTrace();
+            Assert.fail();
+        }
+
+        try {
+            auth.createUser(createUserStmt);
+        } catch (DdlException e) {
+            Assert.fail();
+        }
+
+        // 1.2 create cmy@% again without IF NOT EXISTS
+        userIdentity = new UserIdentity("cmy", "%");
+        userDesc = new UserDesc(userIdentity, "54321", true);
+        createUserStmt = new CreateUserStmt(false, userDesc, null);
+        try {
+            createUserStmt.analyze(analyzer);
+        } catch (UserException e) {
+            e.printStackTrace();
+            Assert.fail();
+        }
+
+        boolean hasException = false;
+        try {
+            auth.createUser(createUserStmt);
+        } catch (DdlException e) {
+            e.printStackTrace();
+            hasException = true;
+        }
+        Assert.assertTrue(hasException);
+
         // 2. check if cmy from specified ip can access to palo
         List<UserIdentity> currentUser = Lists.newArrayList();
         Assert.assertTrue(auth.checkPlainPassword(SystemInfoService.DEFAULT_CLUSTER + ":cmy", "192.168.0.1", "12345",
@@ -205,7 +242,7 @@ public class AuthTest {
             Assert.fail();
         }
 
-        boolean hasException = false;
+        hasException = false;
         try {
             auth.createUser(createUserStmt);
         } catch (DdlException e) {
@@ -769,6 +806,40 @@ public class AuthTest {
             Assert.fail();
         }
 
+        // 24.1 create role again with IF NOT EXISTS
+        roleStmt = new CreateRoleStmt(true, "role1");
+        try {
+            roleStmt.analyze(analyzer);
+        } catch (UserException e1) {
+            e1.printStackTrace();
+            Assert.fail();
+        }
+
+        try {
+            auth.createRole(roleStmt);
+        } catch (DdlException e1) {
+            e1.printStackTrace();
+            Assert.fail();
+        }
+
+        // 24.2 create role again without IF NOT EXISTS
+        roleStmt = new CreateRoleStmt(false, "role1");
+        try {
+            roleStmt.analyze(analyzer);
+        } catch (UserException e1) {
+            e1.printStackTrace();
+            Assert.fail();
+        }
+
+        hasException = false;
+        try {
+            auth.createRole(roleStmt);
+        } catch (DdlException e1) {
+            e1.printStackTrace();
+            hasException = true;
+        }
+        Assert.assertTrue(hasException);
+
         // 25. grant auth to non exist role, will create this new role
         privileges = Lists.newArrayList(AccessPrivilege.DROP_PRIV, AccessPrivilege.SELECT_PRIV);
         grantStmt = new GrantStmt(null, "role2", new TablePattern("*", "*"), privileges);
@@ -917,6 +988,40 @@ public class AuthTest {
         Assert.assertFalse(auth.checkDbPriv(currentUser2.get(0), SystemInfoService.DEFAULT_CLUSTER + ":db4",
                 PrivPredicate.DROP));
 
+        // 31.1 drop role again with IF EXISTS
+        dropRoleStmt = new DropRoleStmt(true, "role1");
+        try {
+            dropRoleStmt.analyze(analyzer);
+        } catch (UserException e) {
+            e.printStackTrace();
+            Assert.fail();
+        }
+
+        try {
+            auth.dropRole(dropRoleStmt);
+        } catch (DdlException e) {
+            e.printStackTrace();
+            Assert.fail();
+        }
+
+        // 31.2 drop role again without IF EXISTS
+        dropRoleStmt = new DropRoleStmt(false, "role1");
+        try {
+            dropRoleStmt.analyze(analyzer);
+        } catch (UserException e) {
+            e.printStackTrace();
+            Assert.fail();
+        }
+
+        hasException = false;
+        try {
+            auth.dropRole(dropRoleStmt);
+        } catch (DdlException e) {
+            e.printStackTrace();
+            hasException = true;
+        }
+        Assert.assertTrue(hasException);
+
         // 32. drop user cmy@"%"
         DropUserStmt dropUserStmt = new DropUserStmt(new UserIdentity("cmy", "%"));
         try {
@@ -936,6 +1041,39 @@ public class AuthTest {
         Assert.assertTrue(auth.checkPlainPassword(SystemInfoService.DEFAULT_CLUSTER + ":zhangsan", "192.168.0.1",
                 "12345", null));
 
+        // 32.1 drop user cmy@"%" again with IF EXISTS
+        dropUserStmt = new DropUserStmt(true, new UserIdentity("cmy", "%"));
+        try {
+            dropUserStmt.analyze(analyzer);
+        } catch (UserException e) {
+            e.printStackTrace();
+            Assert.fail();
+        }
+
+        try {
+            auth.dropUser(dropUserStmt);
+        } catch (DdlException e) {
+            Assert.fail();
+        }
+
+        // 32.2 drop user cmy@"%" again without IF EXISTS
+        dropUserStmt = new DropUserStmt(false, new UserIdentity("cmy", "%"));
+        try {
+            dropUserStmt.analyze(analyzer);
+        } catch (UserException e) {
+            e.printStackTrace();
+            Assert.fail();
+        }
+
+        hasException = false;
+        try {
+            auth.dropUser(dropUserStmt);
+        } catch (DdlException e) {
+            e.printStackTrace();
+            hasException = true;
+        }
+        Assert.assertTrue(hasException);
+
         // 33. drop user zhangsan@"192.%"
         dropUserStmt = new DropUserStmt(new UserIdentity("zhangsan", "192.%"));
         try {


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org