diff --git a/doc/src/sgml/ref/create_user.sgmlin b/doc/src/sgml/ref/create_user.sgmlin index 437e91978..0785b41b7 100755 --- a/doc/src/sgml/ref/create_user.sgmlin +++ b/doc/src/sgml/ref/create_user.sgmlin @@ -10,7 +10,7 @@ -CREATE USER user_name [ [ WITH ] option [ ... ] ] [ ENCRYPTED | UNENCRYPTED ] { PASSWORD | IDENTIFIED BY } { 'password' [ EXPIRED ] | DISABLE }; +CREATE USER [IF NOT EXISTS] user_name [ [ WITH ] option [ ... ] ] [ ENCRYPTED | UNENCRYPTED ] { PASSWORD | IDENTIFIED BY } { 'password' [ EXPIRED ] | DISABLE }; where option can be: {SYSADMIN | NOSYSADMIN} diff --git a/src/common/backend/nodes/copyfuncs.cpp b/src/common/backend/nodes/copyfuncs.cpp index fd8d69260..7b43d2a84 100644 --- a/src/common/backend/nodes/copyfuncs.cpp +++ b/src/common/backend/nodes/copyfuncs.cpp @@ -6086,6 +6086,7 @@ static CreateRoleStmt* _copyCreateRoleStmt(const CreateRoleStmt* from) COPY_SCALAR_FIELD(stmt_type); COPY_STRING_FIELD(role); + COPY_SCALAR_FIELD(missing_ok); COPY_NODE_FIELD(options); return newnode; diff --git a/src/common/backend/nodes/equalfuncs.cpp b/src/common/backend/nodes/equalfuncs.cpp index fed11c940..aec9e2cab 100644 --- a/src/common/backend/nodes/equalfuncs.cpp +++ b/src/common/backend/nodes/equalfuncs.cpp @@ -2177,6 +2177,7 @@ static bool _equalCreatePLangStmt(const CreatePLangStmt* a, const CreatePLangStm static bool _equalCreateRoleStmt(const CreateRoleStmt* a, const CreateRoleStmt* b) { COMPARE_SCALAR_FIELD(stmt_type); + COMPARE_SCALAR_FIELD(missing_ok); COMPARE_STRING_FIELD(role); COMPARE_NODE_FIELD(options); diff --git a/src/common/backend/parser/gram.y b/src/common/backend/parser/gram.y index 16084f2c7..4c341ef42 100644 --- a/src/common/backend/parser/gram.y +++ b/src/common/backend/parser/gram.y @@ -1639,6 +1639,18 @@ CreateUserStmt: IsValidIdentUsername($3); n->role = $3; n->options = $6; + n->missing_ok = false; + $$ = (Node *)n; + u_sess->parser_cxt.isForbidTruncate = false; + } + | CREATE USER IF_P NOT EXISTS RoleId opt_with {u_sess->parser_cxt.isForbidTruncate = true;} OptRoleList + { + CreateRoleStmt *n = makeNode(CreateRoleStmt); + n->stmt_type = ROLESTMT_USER; + IsValidIdentUsername($6); + n->role = $6; + n->options = $9; + n->missing_ok = true; $$ = (Node *)n; u_sess->parser_cxt.isForbidTruncate = false; } @@ -1831,6 +1843,7 @@ CreateGroupStmt: n->stmt_type = ROLESTMT_GROUP; n->role = $3; n->options = $5; + n->missing_ok = false; $$ = (Node *)n; } ; diff --git a/src/gausskernel/optimizer/commands/user.cpp b/src/gausskernel/optimizer/commands/user.cpp index dce160f79..fa384bbac 100755 --- a/src/gausskernel/optimizer/commands/user.cpp +++ b/src/gausskernel/optimizer/commands/user.cpp @@ -1184,7 +1184,12 @@ void CreateRole(CreateRoleStmt* stmt) if (OidIsValid(get_role_oid(stmt->role, true))) { str_reset(password); - ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("role \"%s\" already exists", stmt->role))); + int elevel = stmt->missing_ok ? NOTICE : ERROR; + ereport(elevel, (errmsg("role \"%s\" already exists", stmt->role))); + if (stmt->missing_ok) { + heap_close(pg_authid_rel, NoLock); + return; + } } /* Convert validBegin to internal form */ diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 32402c5ba..1cb346a2d 100755 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -1075,6 +1075,7 @@ typedef struct CreateRoleStmt { RoleStmtType stmt_type; /* ROLE/USER/GROUP */ char* role; /* role name */ List* options; /* List of DefElem nodes */ + bool missing_ok; /* skip error if a role is exists */ } CreateRoleStmt; /* ---------------------- diff --git a/src/test/regress/expected/test_if_not_exists.out b/src/test/regress/expected/test_if_not_exists.out index db0dc56f8..a36cdd06f 100644 --- a/src/test/regress/expected/test_if_not_exists.out +++ b/src/test/regress/expected/test_if_not_exists.out @@ -26,3 +26,10 @@ create user test_user_002 password 'test@1234'; create schema if not exists test_schema_002 authorization test_user_002; drop schema test_schema_002; drop user test_user_002; +CREATE USER ZZZ WITH PASSWORD 'openGauss@123'; +CREATE USER ZZZ WITH PASSWORD 'openGauss@123'; +ERROR: role "zzz" already exists +CREATE USER IF NOT EXISTS ZZZ WITH PASSWORD 'openGauss@123'; +NOTICE: role "zzz" already exists +DROP USER ZZZ; +CREATE USER IF NOT EXISTS ZZZ WITH PASSWORD 'openGauss@123'; diff --git a/src/test/regress/sql/test_if_not_exists.sql b/src/test/regress/sql/test_if_not_exists.sql index 5623b38cf..fe60cd037 100644 --- a/src/test/regress/sql/test_if_not_exists.sql +++ b/src/test/regress/sql/test_if_not_exists.sql @@ -24,3 +24,9 @@ create user test_user_002 password 'test@1234'; create schema if not exists test_schema_002 authorization test_user_002; drop schema test_schema_002; drop user test_user_002; + +CREATE USER ZZZ WITH PASSWORD 'openGauss@123'; +CREATE USER ZZZ WITH PASSWORD 'openGauss@123'; +CREATE USER IF NOT EXISTS ZZZ WITH PASSWORD 'openGauss@123'; +DROP USER ZZZ; +CREATE USER IF NOT EXISTS ZZZ WITH PASSWORD 'openGauss@123';