This is an automated email from the ASF dual-hosted git repository.
starocean999 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 095bf84b822 [Enhancement] (nereids) implement alterUserCommand in
nereids (#48428)
095bf84b822 is described below
commit 095bf84b822cc231dc22d5317df49f459d897b05
Author: yaoxiao <[email protected]>
AuthorDate: Thu Apr 17 14:54:57 2025 +0800
[Enhancement] (nereids) implement alterUserCommand in nereids (#48428)
Issue Number: #42798
---
.../antlr4/org/apache/doris/nereids/DorisParser.g4 | 6 +-
.../AlterUserOpType.java} | 31 ++-----
.../org/apache/doris/analysis/AlterUserStmt.java | 25 ++----
.../org/apache/doris/mysql/privilege/Auth.java | 15 +++-
.../doris/nereids/parser/LogicalPlanBuilder.java | 46 ++++------
.../apache/doris/nereids/parser/ParserUtils.java | 14 ++++
.../apache/doris/nereids/trees/plans/PlanType.java | 4 +-
.../trees/plans/commands/AlterUserCommand.java | 60 +++++++++++++
.../trees/plans/commands/info/AlterUserInfo.java} | 98 ++++++----------------
.../trees/plans/visitor/CommandVisitor.java | 5 ++
.../doris/persist/AlterUserOperationLog.java | 11 ++-
.../trees/plans/commands/AlterUserCommandTest.java | 91 ++++++++++++++++++++
.../ddl/alter/test_alter_user_nereids.groovy | 37 +++-----
13 files changed, 263 insertions(+), 180 deletions(-)
diff --git a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
index 959f0cf0d43..d2c3dbbf36f 100644
--- a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
+++ b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
@@ -252,6 +252,8 @@ supportedAlterStatement
QUOTA (quota=identifier | INTEGER_VALUE)
#alterDatabaseSetQuota
| ALTER SYSTEM RENAME COMPUTE GROUP name=identifier newName=identifier
#alterSystemRenameComputeGroup
| ALTER REPOSITORY name=identifier properties=propertyClause?
#alterRepository
+ | ALTER USER (IF EXISTS)? grantUserIdentify
+ passwordOption (COMMENT STRING_LITERAL)?
#alterUser
;
supportedDropStatement
@@ -638,8 +640,8 @@ unsupportedAlterStatement
SET LEFT_PAREN propertyItemList RIGHT_PAREN
#alterColocateGroup
| ALTER ROUTINE LOAD FOR name=multipartIdentifier
properties=propertyClause?
(FROM type=identifier LEFT_PAREN propertyItemList RIGHT_PAREN)?
#alterRoutineLoad
- | ALTER USER (IF EXISTS)? grantUserIdentify
- passwordOption (COMMENT STRING_LITERAL)?
#alterUser
+ | ALTER STORAGE POLICY name=identifierOrText
+ properties=propertyClause
#alterStoragePlicy
;
alterSystemClause
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/ParserUtils.java
b/fe/fe-core/src/main/java/org/apache/doris/alter/AlterUserOpType.java
similarity index 52%
copy from
fe/fe-core/src/main/java/org/apache/doris/nereids/parser/ParserUtils.java
copy to fe/fe-core/src/main/java/org/apache/doris/alter/AlterUserOpType.java
index 0afc7ddce15..4b694c38ef9 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/ParserUtils.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/alter/AlterUserOpType.java
@@ -15,29 +15,14 @@
// specific language governing permissions and limitations
// under the License.
-package org.apache.doris.nereids.parser;
+package org.apache.doris.alter;
-import org.antlr.v4.runtime.CharStream;
-import org.antlr.v4.runtime.ParserRuleContext;
-import org.antlr.v4.runtime.Token;
-import org.antlr.v4.runtime.misc.Interval;
-import java.util.function.Supplier;
-
-/**
- * Utils for parser.
- */
-public class ParserUtils {
- public static <T> T withOrigin(ParserRuleContext ctx, Supplier<T> f) {
- return f.get();
- }
-
- public static String command(ParserRuleContext ctx) {
- CharStream stream = ctx.getStart().getInputStream();
- return stream.getText(Interval.of(0, stream.size() - 1));
- }
-
- public static Origin position(Token token) {
- return new Origin(token.getLine(), token.getCharPositionInLine());
- }
+public enum AlterUserOpType {
+ SET_PASSWORD,
+ SET_ROLE,
+ SET_PASSWORD_POLICY,
+ LOCK_ACCOUNT,
+ UNLOCK_ACCOUNT,
+ MODIFY_COMMENT
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/analysis/AlterUserStmt.java
b/fe/fe-core/src/main/java/org/apache/doris/analysis/AlterUserStmt.java
index aa5c69c29ac..cc340182970 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/AlterUserStmt.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/AlterUserStmt.java
@@ -17,6 +17,7 @@
package org.apache.doris.analysis;
+import org.apache.doris.alter.AlterUserOpType;
import org.apache.doris.catalog.Env;
import org.apache.doris.cluster.ClusterNamespace;
import org.apache.doris.common.AnalysisException;
@@ -48,17 +49,7 @@ public class AlterUserStmt extends DdlStmt implements
NotFallbackInParser {
private String comment;
- // Only support doing one of these operation at one time.
- public enum OpType {
- SET_PASSWORD,
- SET_ROLE,
- SET_PASSWORD_POLICY,
- LOCK_ACCOUNT,
- UNLOCK_ACCOUNT,
- MODIFY_COMMENT
- }
-
- private Set<OpType> ops = Sets.newHashSet();
+ private Set<AlterUserOpType> ops = Sets.newHashSet();
public AlterUserStmt(boolean ifExist, UserDesc userDesc, String role,
PasswordOptions passwordOptions,
String comment) {
@@ -92,7 +83,7 @@ public class AlterUserStmt extends DdlStmt implements
NotFallbackInParser {
return passwordOptions;
}
- public OpType getOpType() {
+ public AlterUserOpType getOpType() {
Preconditions.checkState(ops.size() == 1);
return ops.iterator().next();
}
@@ -108,27 +99,27 @@ public class AlterUserStmt extends DdlStmt implements
NotFallbackInParser {
userDesc.getPassVar().analyze();
if (userDesc.hasPassword()) {
- ops.add(OpType.SET_PASSWORD);
+ ops.add(AlterUserOpType.SET_PASSWORD);
}
if (!Strings.isNullOrEmpty(role)) {
- ops.add(OpType.SET_ROLE);
+ ops.add(AlterUserOpType.SET_ROLE);
}
// may be set comment to "", so not use `Strings.isNullOrEmpty`
if (comment != null) {
- ops.add(OpType.MODIFY_COMMENT);
+ ops.add(AlterUserOpType.MODIFY_COMMENT);
}
passwordOptions.analyze();
if (passwordOptions.getAccountUnlocked() ==
FailedLoginPolicy.LOCK_ACCOUNT) {
throw new AnalysisException("Not support lock account now");
} else if (passwordOptions.getAccountUnlocked() ==
FailedLoginPolicy.UNLOCK_ACCOUNT) {
- ops.add(OpType.UNLOCK_ACCOUNT);
+ ops.add(AlterUserOpType.UNLOCK_ACCOUNT);
} else if (passwordOptions.getExpirePolicySecond() !=
PasswordOptions.UNSET
|| passwordOptions.getHistoryPolicy() != PasswordOptions.UNSET
|| passwordOptions.getPasswordLockSecond() !=
PasswordOptions.UNSET
|| passwordOptions.getLoginAttempts() !=
PasswordOptions.UNSET) {
- ops.add(OpType.SET_PASSWORD_POLICY);
+ ops.add(AlterUserOpType.SET_PASSWORD_POLICY);
}
if (ops.size() != 1) {
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 cd8a682c4bc..aba0f9571f9 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
@@ -17,9 +17,9 @@
package org.apache.doris.mysql.privilege;
+import org.apache.doris.alter.AlterUserOpType;
import org.apache.doris.analysis.AlterRoleStmt;
import org.apache.doris.analysis.AlterUserStmt;
-import org.apache.doris.analysis.AlterUserStmt.OpType;
import org.apache.doris.analysis.CreateRoleStmt;
import org.apache.doris.analysis.CreateUserStmt;
import org.apache.doris.analysis.DropRoleStmt;
@@ -62,6 +62,7 @@ import org.apache.doris.mysql.MysqlPassword;
import org.apache.doris.mysql.authenticate.AuthenticateType;
import org.apache.doris.mysql.authenticate.ldap.LdapManager;
import org.apache.doris.mysql.authenticate.ldap.LdapUserInfo;
+import org.apache.doris.nereids.trees.plans.commands.info.AlterUserInfo;
import org.apache.doris.nereids.trees.plans.commands.info.CreateUserInfo;
import org.apache.doris.persist.AlterUserOperationLog;
import org.apache.doris.persist.LdapInfo;
@@ -1863,6 +1864,11 @@ public class Auth implements Writable {
stmt.getPasswordOptions(), stmt.getComment(), false);
}
+ public void alterUser(AlterUserInfo info) throws DdlException {
+ alterUserInternal(info.isIfExist(), info.getOpType(),
info.getUserIdent(), info.getPassword(),
+ null, info.getPasswordOptions(), info.getComment(), false);
+ }
+
public void replayAlterUser(AlterUserOperationLog log) {
try {
alterUserInternal(true, log.getOp(), log.getUserIdent(),
log.getPassword(), log.getRole(),
@@ -1872,8 +1878,9 @@ public class Auth implements Writable {
}
}
- private void alterUserInternal(boolean ifExists, OpType opType,
UserIdentity userIdent, byte[] password,
- String role, PasswordOptions passwordOptions, String comment,
boolean isReplay) throws DdlException {
+ private void alterUserInternal(boolean ifExists, AlterUserOpType opType,
UserIdentity userIdent, byte[] password,
+ String role, PasswordOptions
passwordOptions, String comment,
+ boolean isReplay) throws DdlException {
writeLock();
try {
if (!doesUserExist(userIdent)) {
@@ -1901,7 +1908,7 @@ public class Auth implements Writable {
default:
throw new DdlException("Unknown alter user operation type:
" + opType.name());
}
- if (opType != OpType.SET_PASSWORD && !isReplay) {
+ if (opType != AlterUserOpType.SET_PASSWORD && !isReplay) {
// For SET_PASSWORD:
// the edit log is wrote in "setPasswordInternal"
AlterUserOperationLog log = new AlterUserOperationLog(opType,
userIdent, password, role,
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java
index 67fa8eafdb6..65f6ce755f4 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java
@@ -544,6 +544,7 @@ import
org.apache.doris.nereids.trees.plans.commands.AlterSystemCommand;
import
org.apache.doris.nereids.trees.plans.commands.AlterSystemRenameComputeGroupCommand;
import org.apache.doris.nereids.trees.plans.commands.AlterTableCommand;
import org.apache.doris.nereids.trees.plans.commands.AlterTableStatsCommand;
+import org.apache.doris.nereids.trees.plans.commands.AlterUserCommand;
import org.apache.doris.nereids.trees.plans.commands.AlterViewCommand;
import org.apache.doris.nereids.trees.plans.commands.AlterWorkloadGroupCommand;
import
org.apache.doris.nereids.trees.plans.commands.AlterWorkloadPolicyCommand;
@@ -728,6 +729,7 @@ import
org.apache.doris.nereids.trees.plans.commands.info.AlterMTMVReplaceInfo;
import
org.apache.doris.nereids.trees.plans.commands.info.AlterMultiPartitionOp;
import org.apache.doris.nereids.trees.plans.commands.info.AlterSystemOp;
import org.apache.doris.nereids.trees.plans.commands.info.AlterTableOp;
+import org.apache.doris.nereids.trees.plans.commands.info.AlterUserInfo;
import org.apache.doris.nereids.trees.plans.commands.info.AlterViewInfo;
import org.apache.doris.nereids.trees.plans.commands.info.BuildIndexOp;
import org.apache.doris.nereids.trees.plans.commands.info.BulkLoadDataDesc;
@@ -6384,6 +6386,16 @@ public class LogicalPlanBuilder extends
DorisParserBaseVisitor<Object> {
return new DescribeCommand(tableValuedFunctionRef);
}
+ @Override
+ public LogicalPlan visitAlterUser(DorisParser.AlterUserContext ctx) {
+ boolean ifExist = ctx.EXISTS() != null;
+ UserDesc userDesc = visitGrantUserIdentify(ctx.grantUserIdentify());
+ PasswordOptions passwordOptions =
visitPasswordOption(ctx.passwordOption());
+ String comment = ctx.STRING_LITERAL() != null ?
stripQuotes(ctx.STRING_LITERAL().getText()) : null;
+ AlterUserInfo alterUserInfo = new AlterUserInfo(ifExist, userDesc,
passwordOptions, comment);
+ return new AlterUserCommand(alterUserInfo);
+ }
+
@Override
public LogicalPlan visitShowTableStats(DorisParser.ShowTableStatsContext
ctx) {
if (ctx.tableId != null) {
@@ -6517,9 +6529,7 @@ public class LogicalPlanBuilder extends
DorisParserBaseVisitor<Object> {
return new KillAnalyzeJobCommand(jobId);
}
- /**
- * PasswordOption
- */
+ @Override
public PasswordOptions
visitPasswordOption(DorisParser.PasswordOptionContext ctx) {
int historyPolicy = PasswordOptions.UNSET;
long expirePolicySecond = PasswordOptions.UNSET;
@@ -6540,7 +6550,7 @@ public class LogicalPlanBuilder extends
DorisParserBaseVisitor<Object> {
expirePolicySecond = 0;
} else if (ctx.expireValue != null) {
long value = Long.parseLong(ctx.expireValue.getText());
- expirePolicySecond = getSecond(value,
ctx.expireTimeUnit.getText());
+ expirePolicySecond = ParserUtils.getSecond(value,
ctx.expireTimeUnit.getText());
}
if (ctx.reuseValue != null) {
@@ -6555,7 +6565,7 @@ public class LogicalPlanBuilder extends
DorisParserBaseVisitor<Object> {
passwordLockSecond = -1;
} else if (ctx.lockValue != null) {
long value = Long.parseLong(ctx.lockValue.getText());
- passwordLockSecond = getSecond(value, ctx.lockTimeUint.getText());
+ passwordLockSecond = ParserUtils.getSecond(value,
ctx.lockTimeUint.getText());
}
if (ctx.ACCOUNT_LOCK() != null) {
@@ -6572,26 +6582,10 @@ public class LogicalPlanBuilder extends
DorisParserBaseVisitor<Object> {
accountUnlocked);
}
- private long getSecond(long value, String s) {
- long ans = 0;
-
- switch (s) {
- case "DAY":
- ans = value * 24 * 60 * 60;
- break;
- case "HOUR":
- ans = value * 60 * 60;
- break;
- default:
- ans = value;
- }
- return ans;
- }
-
@Override
public LogicalPlan visitCreateUser(CreateUserContext ctx) {
String comment = visitCommentSpec(ctx.commentSpec());
- PasswordOptions passwordOptions = (PasswordOptions)
ctx.passwordOption().accept(this);
+ PasswordOptions passwordOptions =
visitPasswordOption(ctx.passwordOption());
UserDesc userDesc = (UserDesc) ctx.grantUserIdentify().accept(this);
String role = null;
@@ -6610,16 +6604,12 @@ public class LogicalPlanBuilder extends
DorisParserBaseVisitor<Object> {
@Override
public UserDesc
visitGrantUserIdentify(DorisParser.GrantUserIdentifyContext ctx) {
- UserIdentity userIdentity = (UserIdentity)
ctx.userIdentify().accept(this);
-
+ UserIdentity userIdentity = visitUserIdentify(ctx.userIdentify());
if (ctx.IDENTIFIED() == null) {
return new UserDesc(userIdentity);
}
-
String password = stripQuotes(ctx.STRING_LITERAL().getText());
- boolean isPlain = !(ctx.PASSWORD() != null);
-
+ boolean isPlain = ctx.PASSWORD() == null;
return new UserDesc(userIdentity, new PassVar(password, isPlain));
}
}
-
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/ParserUtils.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/ParserUtils.java
index 0afc7ddce15..c829fe01c35 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/ParserUtils.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/ParserUtils.java
@@ -40,4 +40,18 @@ public class ParserUtils {
public static Origin position(Token token) {
return new Origin(token.getLine(), token.getCharPositionInLine());
}
+
+ /**
+ * getSecond
+ */
+ public static long getSecond(long value, String s) {
+ switch (s) {
+ case "DAY":
+ return value * 24 * 60 * 60;
+ case "HOUR":
+ return value * 60 * 60;
+ default:
+ return value;
+ }
+ }
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanType.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanType.java
index 96db0af6fd4..3bfe92a2b72 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanType.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanType.java
@@ -313,6 +313,9 @@ public enum PlanType {
DROP_TABLE_COMMAND,
ANALYZE_DATABASE,
ANALYZE_TABLE,
+ ALTER_SYSTEM,
+ ALTER_SYSTEM_RENAME_COMPUTE_GROUP,
+ ALTER_USER_COMMAND,
ALTER_SYSTEM_ADD_BACKEND,
ALTER_SYSTEM_DROP_BACKEND,
ALTER_SYSTEM_DECOMMISSION_BACKEND,
@@ -326,7 +329,6 @@ public enum PlanType {
ALTER_SYSTEM_SET_LOAD_ERRORS_HU,
ALTER_SYSTEM_MODIFY_BACKEND,
ALTER_SYSTEM_MODIFY_FRONTEND_OR_BACKEND_HOSTNAME,
- ALTER_SYSTEM_RENAME_COMPUTE_GROUP,
SHOW_TABLE_STATS_COMMAND,
DROP_STATS_COMMAND,
DROP_CACHED_STATS_COMMAND,
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AlterUserCommand.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AlterUserCommand.java
new file mode 100644
index 00000000000..e1bde5ac549
--- /dev/null
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AlterUserCommand.java
@@ -0,0 +1,60 @@
+// 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.nereids.trees.plans.commands;
+
+import org.apache.doris.analysis.StmtType;
+import org.apache.doris.catalog.Env;
+import org.apache.doris.common.UserException;
+import org.apache.doris.nereids.trees.plans.PlanType;
+import org.apache.doris.nereids.trees.plans.commands.info.AlterUserInfo;
+import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
+import org.apache.doris.qe.ConnectContext;
+import org.apache.doris.qe.StmtExecutor;
+
+/**
+ * AlterUserCommand
+ */
+public class AlterUserCommand extends AlterCommand {
+
+ private final AlterUserInfo alterUserInfo;
+
+ public AlterUserCommand(AlterUserInfo alterUserInfo) {
+ super(PlanType.ALTER_USER_COMMAND);
+ this.alterUserInfo = alterUserInfo;
+ }
+
+ @Override
+ public <R, C> R accept(PlanVisitor<R, C> visitor, C context) {
+ return visitor.visitAlterUserCommand(this, context);
+ }
+
+ @Override
+ public void doRun(ConnectContext ctx, StmtExecutor executor) throws
Exception {
+ validate();
+ Env.getCurrentEnv().getAuth().alterUser(alterUserInfo);
+ }
+
+ public void validate() throws UserException {
+ alterUserInfo.validate();
+ }
+
+ @Override
+ public StmtType stmtType() {
+ return StmtType.ALTER;
+ }
+}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/analysis/AlterUserStmt.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/AlterUserInfo.java
similarity index 57%
copy from fe/fe-core/src/main/java/org/apache/doris/analysis/AlterUserStmt.java
copy to
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/AlterUserInfo.java
index aa5c69c29ac..40c1ef7d781 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/AlterUserStmt.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/AlterUserInfo.java
@@ -15,8 +15,12 @@
// specific language governing permissions and limitations
// under the License.
-package org.apache.doris.analysis;
+package org.apache.doris.nereids.trees.plans.commands.info;
+import org.apache.doris.alter.AlterUserOpType;
+import org.apache.doris.analysis.PasswordOptions;
+import org.apache.doris.analysis.UserDesc;
+import org.apache.doris.analysis.UserIdentity;
import org.apache.doris.catalog.Env;
import org.apache.doris.cluster.ClusterNamespace;
import org.apache.doris.common.AnalysisException;
@@ -24,47 +28,28 @@ import org.apache.doris.common.ErrorCode;
import org.apache.doris.common.ErrorReport;
import org.apache.doris.common.UserException;
import org.apache.doris.mysql.privilege.Auth;
-import org.apache.doris.mysql.privilege.PasswordPolicy.FailedLoginPolicy;
+import org.apache.doris.mysql.privilege.PasswordPolicy;
import org.apache.doris.mysql.privilege.PrivPredicate;
import org.apache.doris.qe.ConnectContext;
import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
import com.google.common.collect.Sets;
import java.util.Set;
-// ALTER USER user@host [IDENTIFIED BY "password"] [DEFAULT ROLE role]
[password_options]
-// password_options:
-// PASSWORD_HISTORY
-// ACCOUNT_LOCK[ACCOUNT_UNLOCK]
-// FAILED_LOGIN_ATTEMPTS
-// PASSWORD_LOCK_TIME
-public class AlterUserStmt extends DdlStmt implements NotFallbackInParser {
+/**
+ * AlterUserInfo
+ */
+public class AlterUserInfo {
private boolean ifExist;
private UserDesc userDesc;
- private String role;
private PasswordOptions passwordOptions;
-
private String comment;
+ private Set<AlterUserOpType> ops = Sets.newHashSet();
- // Only support doing one of these operation at one time.
- public enum OpType {
- SET_PASSWORD,
- SET_ROLE,
- SET_PASSWORD_POLICY,
- LOCK_ACCOUNT,
- UNLOCK_ACCOUNT,
- MODIFY_COMMENT
- }
-
- private Set<OpType> ops = Sets.newHashSet();
-
- public AlterUserStmt(boolean ifExist, UserDesc userDesc, String role,
PasswordOptions passwordOptions,
- String comment) {
+ public AlterUserInfo(boolean ifExist, UserDesc userDesc, PasswordOptions
passwordOptions, String comment) {
this.ifExist = ifExist;
this.userDesc = userDesc;
- this.role = role;
this.passwordOptions = passwordOptions;
this.comment = comment;
}
@@ -84,15 +69,11 @@ public class AlterUserStmt extends DdlStmt implements
NotFallbackInParser {
return null;
}
- public String getRole() {
- return role;
- }
-
public PasswordOptions getPasswordOptions() {
return passwordOptions;
}
- public OpType getOpType() {
+ public AlterUserOpType getOpType() {
Preconditions.checkState(ops.size() == 1);
return ops.iterator().next();
}
@@ -101,38 +82,36 @@ public class AlterUserStmt extends DdlStmt implements
NotFallbackInParser {
return comment;
}
- @Override
- public void analyze(Analyzer analyzer) throws UserException {
- super.analyze(analyzer);
+ /**
+ * validate
+ */
+ public void validate() throws UserException {
userDesc.getUserIdent().analyze();
userDesc.getPassVar().analyze();
if (userDesc.hasPassword()) {
- ops.add(OpType.SET_PASSWORD);
- }
-
- if (!Strings.isNullOrEmpty(role)) {
- ops.add(OpType.SET_ROLE);
+ ops.add(AlterUserOpType.SET_PASSWORD);
}
// may be set comment to "", so not use `Strings.isNullOrEmpty`
if (comment != null) {
- ops.add(OpType.MODIFY_COMMENT);
+ ops.add(AlterUserOpType.MODIFY_COMMENT);
}
passwordOptions.analyze();
- if (passwordOptions.getAccountUnlocked() ==
FailedLoginPolicy.LOCK_ACCOUNT) {
+ if (passwordOptions.getAccountUnlocked() ==
PasswordPolicy.FailedLoginPolicy.LOCK_ACCOUNT) {
throw new AnalysisException("Not support lock account now");
- } else if (passwordOptions.getAccountUnlocked() ==
FailedLoginPolicy.UNLOCK_ACCOUNT) {
- ops.add(OpType.UNLOCK_ACCOUNT);
+ } else if (passwordOptions.getAccountUnlocked() ==
PasswordPolicy.FailedLoginPolicy.UNLOCK_ACCOUNT) {
+ ops.add(AlterUserOpType.UNLOCK_ACCOUNT);
} else if (passwordOptions.getExpirePolicySecond() !=
PasswordOptions.UNSET
|| passwordOptions.getHistoryPolicy() != PasswordOptions.UNSET
|| passwordOptions.getPasswordLockSecond() !=
PasswordOptions.UNSET
|| passwordOptions.getLoginAttempts() !=
PasswordOptions.UNSET) {
- ops.add(OpType.SET_PASSWORD_POLICY);
+ ops.add(AlterUserOpType.SET_PASSWORD_POLICY);
}
if (ops.size() != 1) {
- throw new AnalysisException("Only support doing one type of
operation at one time");
+ throw new org.apache.doris.common.AnalysisException("Only support
doing one type of operation at one time,"
+ + "actual number of type is " + ops.size());
}
if (userDesc.getUserIdent().getQualifiedUser().equals(Auth.ROOT_USER)
@@ -145,31 +124,4 @@ public class AlterUserStmt extends DdlStmt implements
NotFallbackInParser {
ErrorReport.reportAnalysisException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR,
"GRANT");
}
}
-
- @Override
- public String toSql() {
- StringBuilder sb = new StringBuilder();
- sb.append("ALTER USER ").append(userDesc.getUserIdent());
- if (!Strings.isNullOrEmpty(userDesc.getPassVar().getText())) {
- if (userDesc.getPassVar().isPlain()) {
- sb.append(" IDENTIFIED BY '").append("*XXX").append("'");
- } else {
- sb.append(" IDENTIFIED BY PASSWORD
'").append(userDesc.getPassVar().getText()).append("'");
- }
- }
-
- if (!Strings.isNullOrEmpty(role)) {
- sb.append(" DEFAULT ROLE '").append(role).append("'");
- }
- if (passwordOptions != null) {
- sb.append(passwordOptions.toSql());
- }
-
- return sb.toString();
- }
-
- @Override
- public StmtType stmtType() {
- return StmtType.ALTER;
- }
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/CommandVisitor.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/CommandVisitor.java
index c60ae160429..429228c2a54 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/CommandVisitor.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/CommandVisitor.java
@@ -36,6 +36,7 @@ import
org.apache.doris.nereids.trees.plans.commands.AlterSqlBlockRuleCommand;
import org.apache.doris.nereids.trees.plans.commands.AlterStoragePolicyCommand;
import org.apache.doris.nereids.trees.plans.commands.AlterTableCommand;
import org.apache.doris.nereids.trees.plans.commands.AlterTableStatsCommand;
+import org.apache.doris.nereids.trees.plans.commands.AlterUserCommand;
import org.apache.doris.nereids.trees.plans.commands.AlterViewCommand;
import org.apache.doris.nereids.trees.plans.commands.AlterWorkloadGroupCommand;
import
org.apache.doris.nereids.trees.plans.commands.AlterWorkloadPolicyCommand;
@@ -896,6 +897,10 @@ public interface CommandVisitor<R, C> {
return visitCommand(describeCommand, context);
}
+ default R visitAlterUserCommand(AlterUserCommand alterUserCommand, C
context) {
+ return visitCommand(alterUserCommand, context);
+ }
+
default R visitShowTableStatusCommand(ShowTableStatusCommand
showTableStatusCommand, C context) {
return visitCommand(showTableStatusCommand, context);
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/persist/AlterUserOperationLog.java
b/fe/fe-core/src/main/java/org/apache/doris/persist/AlterUserOperationLog.java
index 472cda7874e..90580c012f7 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/persist/AlterUserOperationLog.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/persist/AlterUserOperationLog.java
@@ -17,8 +17,7 @@
package org.apache.doris.persist;
-import org.apache.doris.analysis.AlterUserStmt;
-import org.apache.doris.analysis.AlterUserStmt.OpType;
+import org.apache.doris.alter.AlterUserOpType;
import org.apache.doris.analysis.PasswordOptions;
import org.apache.doris.analysis.UserIdentity;
import org.apache.doris.common.io.Text;
@@ -41,13 +40,13 @@ public class AlterUserOperationLog implements Writable {
@SerializedName(value = "passwordOptions")
private PasswordOptions passwordOptions;
@SerializedName(value = "op")
- private AlterUserStmt.OpType op;
+ private AlterUserOpType op;
@SerializedName(value = "comment")
private String comment;
- public AlterUserOperationLog(OpType opType, UserIdentity userIdent, byte[]
password,
- String role, PasswordOptions passwordOptions, String comment) {
+ public AlterUserOperationLog(AlterUserOpType opType, UserIdentity
userIdent, byte[] password,
+ String role, PasswordOptions passwordOptions,
String comment) {
this.op = opType;
this.userIdent = userIdent;
this.password = password;
@@ -56,7 +55,7 @@ public class AlterUserOperationLog implements Writable {
this.comment = comment;
}
- public OpType getOp() {
+ public AlterUserOpType getOp() {
return op;
}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/AlterUserCommandTest.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/AlterUserCommandTest.java
new file mode 100644
index 00000000000..1d3c51ef70c
--- /dev/null
+++
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/AlterUserCommandTest.java
@@ -0,0 +1,91 @@
+// 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.nereids.trees.plans.commands;
+
+import org.apache.doris.analysis.PassVar;
+import org.apache.doris.analysis.PasswordOptions;
+import org.apache.doris.analysis.UserDesc;
+import org.apache.doris.analysis.UserIdentity;
+import org.apache.doris.catalog.Env;
+import org.apache.doris.common.AnalysisException;
+import org.apache.doris.mysql.privilege.AccessControllerManager;
+import org.apache.doris.mysql.privilege.Auth;
+import org.apache.doris.mysql.privilege.PrivPredicate;
+import org.apache.doris.nereids.trees.plans.commands.info.AlterUserInfo;
+import org.apache.doris.qe.ConnectContext;
+import org.apache.doris.utframe.TestWithFeService;
+
+import mockit.Expectations;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+
+public class AlterUserCommandTest extends TestWithFeService {
+ private ConnectContext connectContext;
+ private Env env;
+ private AccessControllerManager accessControllerManager;
+ private UserDesc userDesc;
+
+ private void runBefore() throws IOException {
+ connectContext = createDefaultCtx();
+ env = Env.getCurrentEnv();
+ accessControllerManager = env.getAccessManager();
+ }
+
+ @Test
+ public void testValidateNormal() throws Exception {
+ runBefore();
+ new Expectations() {
+ {
+ connectContext.isSkipAuth();
+ minTimes = 0;
+ result = true;
+
+ accessControllerManager.checkGlobalPriv(connectContext,
PrivPredicate.GRANT);
+ minTimes = 0;
+ result = true;
+ }
+ };
+ // init
+ UserIdentity userIdentity = new UserIdentity(Auth.ROOT_USER, "%");
+ connectContext.setQualifiedUser("root");
+ PassVar passVar = new PassVar("", true);
+ userDesc = new UserDesc(userIdentity, passVar);
+ PasswordOptions passwordOptions = PasswordOptions.UNSET_OPTION;
+ AlterUserInfo alterUserInfo = new AlterUserInfo(true, userDesc,
passwordOptions, null);
+ AlterUserCommand alterUserCommand = new
AlterUserCommand(alterUserInfo);
+ Assertions.assertDoesNotThrow(() -> alterUserCommand.validate());
+
+ //test ops.size() > 1
+ AlterUserInfo alterUserInfo02 = new AlterUserInfo(true, userDesc,
passwordOptions, "alterUserInfo02");
+ AlterUserCommand alterUserCommand02 = new
AlterUserCommand(alterUserInfo02);
+ Assertions.assertThrows(AnalysisException.class, () ->
alterUserCommand02.validate(),
+ "Only support doing one type of operation at one time,actual
number of type is 2");
+
+ //testUser to modify root user
+ connectContext.setQualifiedUser("testUser");
+ Assertions.assertThrows(AnalysisException.class, () ->
alterUserCommand.validate(), "Only root user can modify root user");
+
+ //test PasswordOptions
+ PasswordOptions passwordOptions02 = new
PasswordOptions(PasswordOptions.UNSET, PasswordOptions.UNSET,
PasswordOptions.UNSET, PasswordOptions.UNSET, PasswordOptions.UNSET, -1);
+ AlterUserInfo alterUserInfo03 = new AlterUserInfo(true, userDesc,
passwordOptions02, null);
+ AlterUserCommand alterUserCommand03 = new
AlterUserCommand(alterUserInfo03);
+ Assertions.assertThrows(AnalysisException.class, () ->
alterUserCommand03.validate(), "Not support lock account now");
+ }
+}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/ParserUtils.java
b/regression-test/suites/nereids_p0/ddl/alter/test_alter_user_nereids.groovy
similarity index 52%
copy from
fe/fe-core/src/main/java/org/apache/doris/nereids/parser/ParserUtils.java
copy to
regression-test/suites/nereids_p0/ddl/alter/test_alter_user_nereids.groovy
index 0afc7ddce15..f2d24bbed4e 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/ParserUtils.java
+++ b/regression-test/suites/nereids_p0/ddl/alter/test_alter_user_nereids.groovy
@@ -15,29 +15,14 @@
// specific language governing permissions and limitations
// under the License.
-package org.apache.doris.nereids.parser;
-
-import org.antlr.v4.runtime.CharStream;
-import org.antlr.v4.runtime.ParserRuleContext;
-import org.antlr.v4.runtime.Token;
-import org.antlr.v4.runtime.misc.Interval;
-
-import java.util.function.Supplier;
-
-/**
- * Utils for parser.
- */
-public class ParserUtils {
- public static <T> T withOrigin(ParserRuleContext ctx, Supplier<T> f) {
- return f.get();
- }
-
- public static String command(ParserRuleContext ctx) {
- CharStream stream = ctx.getStart().getInputStream();
- return stream.getText(Interval.of(0, stream.size() - 1));
- }
-
- public static Origin position(Token token) {
- return new Origin(token.getLine(), token.getCharPositionInLine());
- }
-}
+suite("test_alter_user_nereids") {
+ sql "SET enable_nereids_planner=true;"
+ sql "SET enable_fallback_to_original_planner=false;"
+
+ sql """CREATE USER 'fjytf';"""
+
+ sql """ALTER USER fjytf@'%' IDENTIFIED BY "12345";"""
+ sql """ALTER USER fjytf@'%' FAILED_LOGIN_ATTEMPTS 3 PASSWORD_LOCK_TIME 1
DAY;"""
+ sql """ALTER USER fjytf@'%' ACCOUNT_UNLOCK;"""
+ sql """ALTER USER fjytf@'%' COMMENT "this is my first user";"""
+}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]