Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ and missing syntax gets added on demand — [open an issue](https://github.com/J
| **DML** | `INSERT` · `UPDATE` · `UPSERT` · `MERGE` · `DELETE` · `TRUNCATE TABLE` |
| **DDL** | `CREATE …` · `ALTER …` · `DROP …` |
| **MySQL table maintenance** | `ANALYZE` · `CHECK` · `OPTIMIZE` · `REPAIR TABLE` |
| **MySQL account management** | `CREATE`/`ALTER`/`RENAME USER` · `CREATE ROLE` · `SET ROLE` · `SET DEFAULT ROLE` · `SET PASSWORD` |
| **PostgreSQL RLS** | `CREATE POLICY` · `ALTER TABLE … ENABLE`/`DISABLE`/`FORCE`/`NO FORCE ROW LEVEL SECURITY` |
| **Informix constraints** | `ALTER TABLE … ADD CONSTRAINT` with trailing constraint names for primary, unique, foreign and check constraints; enable with `parser.withDialect(Dialect.INFORMIX)` |
| **Salesforce SOQL** | `INCLUDES` · `EXCLUDES` |
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/net/sf/jsqlparser/parser/feature/Feature.java
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,17 @@ public enum Feature {
* @see Grant
*/
grant, revoke, createRole, alterRole, alterDefaultPrivileges,
/**
* MySQL/MariaDB account management: "ALTER USER", "RENAME USER", "SET ROLE", "SET DEFAULT ROLE"
* and "SET PASSWORD"
*
* @see net.sf.jsqlparser.statement.alter.AlterUser
* @see net.sf.jsqlparser.statement.alter.RenameUser
* @see net.sf.jsqlparser.statement.SetRoleStatement
* @see net.sf.jsqlparser.statement.SetDefaultRoleStatement
* @see net.sf.jsqlparser.statement.SetPasswordStatement
*/
alterUser, renameUser, setRole, setDefaultRole, setPassword,
/**
* @see Function
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*-
* #%L
* JSQLParser library
* %%
* Copyright (C) 2004 - 2026 JSQLParser
* %%
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
* #L%
*/
package net.sf.jsqlparser.statement;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import net.sf.jsqlparser.statement.create.user.RoleSelection;
import net.sf.jsqlparser.statement.create.user.UserAccount;

/**
* MySQL {@code SET DEFAULT ROLE {NONE | ALL | role, ...} TO user, ...}. MariaDB's
* {@code SET DEFAULT ROLE {role | NONE} [FOR user]} is kept with {@link #isForKeyword()}; without
* accounts the statement applies to the current user.
*/
public class SetDefaultRoleStatement implements Statement {

private RoleSelection roles;
private final List<UserAccount> accounts = new ArrayList<>();
private boolean forKeyword;

public RoleSelection getRoles() {
return roles;
}

public void setRoles(RoleSelection roles) {
this.roles = roles;
}

/** The accounts after {@code TO} or {@code FOR}; empty when omitted. */
public List<UserAccount> getAccounts() {
return Collections.unmodifiableList(accounts);
}

public void setAccounts(Collection<? extends UserAccount> accounts) {
this.accounts.clear();
if (accounts != null) {
this.accounts.addAll(accounts);
}
}

/** Whether the accounts follow MariaDB's {@code FOR} instead of {@code TO}. */
public boolean isForKeyword() {
return forKeyword;
}

public void setForKeyword(boolean forKeyword) {
this.forKeyword = forKeyword;
}

@Override
public <T, S> T accept(StatementVisitor<T> statementVisitor, S context) {
return statementVisitor.visit(this, context);
}

@Override
public String toString() {
StringBuilder builder = new StringBuilder("SET DEFAULT ROLE ").append(roles);
if (!accounts.isEmpty()) {
builder.append(forKeyword ? " FOR " : " TO ").append(
accounts.stream().map(Object::toString).collect(Collectors.joining(", ")));
}
return builder.toString();
}

public SetDefaultRoleStatement withRoles(RoleSelection roles) {
setRoles(roles);
return this;
}

public SetDefaultRoleStatement withAccounts(Collection<? extends UserAccount> accounts) {
setAccounts(accounts);
return this;
}

public SetDefaultRoleStatement addAccounts(UserAccount... accounts) {
Collections.addAll(this.accounts, accounts);
return this;
}

public SetDefaultRoleStatement withForKeyword(boolean forKeyword) {
setForKeyword(forKeyword);
return this;
}
}
130 changes: 130 additions & 0 deletions src/main/java/net/sf/jsqlparser/statement/SetPasswordStatement.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*-
* #%L
* JSQLParser library
* %%
* Copyright (C) 2004 - 2026 JSQLParser
* %%
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
* #L%
*/
package net.sf.jsqlparser.statement;

import java.util.function.Consumer;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.statement.create.user.UserAccount;

/**
* MySQL/MariaDB {@code SET PASSWORD [FOR user] {= password | TO RANDOM}
* [REPLACE 'current'] [RETAIN CURRENT PASSWORD]}. The password is an expression, usually a string
* literal; MariaDB also accepts {@code PASSWORD('...')}.
*/
public class SetPasswordStatement implements Statement {

private UserAccount account;
private Expression password;
private boolean random;
private StringValue currentCredential;
private boolean retainCurrentPassword;

/** The account after {@code FOR}, or null for the current user. */
public UserAccount getAccount() {
return account;
}

public void setAccount(UserAccount account) {
this.account = account;
}

/** The password after {@code =}; null for {@code TO RANDOM}. */
public Expression getPassword() {
return password;
}

public void setPassword(Expression password) {
this.password = password;
}

/** Whether the statement generates a password with {@code TO RANDOM}. */
public boolean isRandom() {
return random;
}

public void setRandom(boolean random) {
this.random = random;
}

/** The current password of {@code REPLACE 'current'}, or null when omitted. */
public StringValue getCurrentCredential() {
return currentCredential;
}

public void setCurrentCredential(StringValue currentCredential) {
this.currentCredential = currentCredential;
}

public boolean isRetainCurrentPassword() {
return retainCurrentPassword;
}

public void setRetainCurrentPassword(boolean retainCurrentPassword) {
this.retainCurrentPassword = retainCurrentPassword;
}

/** Shares statement rendering while letting deparsers render the password expression. */
public StringBuilder appendTo(StringBuilder builder, Consumer<Expression> expressionRenderer) {
builder.append("SET PASSWORD");
if (account != null) {
builder.append(" FOR ").append(account);
}
if (random) {
builder.append(" TO RANDOM");
} else {
builder.append(" = ");
expressionRenderer.accept(password);
}
if (currentCredential != null) {
builder.append(" REPLACE ").append(currentCredential);
}
if (retainCurrentPassword) {
builder.append(" RETAIN CURRENT PASSWORD");
}
return builder;
}

@Override
public <T, S> T accept(StatementVisitor<T> statementVisitor, S context) {
return statementVisitor.visit(this, context);
}

@Override
public String toString() {
StringBuilder builder = new StringBuilder();
return appendTo(builder, builder::append).toString();
}

public SetPasswordStatement withAccount(UserAccount account) {
setAccount(account);
return this;
}

public SetPasswordStatement withPassword(Expression password) {
setPassword(password);
return this;
}

public SetPasswordStatement withRandom(boolean random) {
setRandom(random);
return this;
}

public SetPasswordStatement withCurrentCredential(StringValue currentCredential) {
setCurrentCredential(currentCredential);
return this;
}

public SetPasswordStatement withRetainCurrentPassword(boolean retainCurrentPassword) {
setRetainCurrentPassword(retainCurrentPassword);
return this;
}
}
52 changes: 52 additions & 0 deletions src/main/java/net/sf/jsqlparser/statement/SetRoleStatement.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*-
* #%L
* JSQLParser library
* %%
* Copyright (C) 2004 - 2026 JSQLParser
* %%
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
* #L%
*/
package net.sf.jsqlparser.statement;

import net.sf.jsqlparser.statement.create.user.RoleSelection;

/**
* MySQL/MariaDB {@code SET ROLE {DEFAULT | NONE | ALL [EXCEPT role, ...] | role, ...}}. PostgreSQL
* {@code SET [SESSION | LOCAL] ROLE name} remains a {@link SetStatement}.
*/
public class SetRoleStatement implements Statement {

private RoleSelection roles;

public SetRoleStatement() {
// empty constructor
}

public SetRoleStatement(RoleSelection roles) {
this.roles = roles;
}

public RoleSelection getRoles() {
return roles;
}

public void setRoles(RoleSelection roles) {
this.roles = roles;
}

@Override
public <T, S> T accept(StatementVisitor<T> statementVisitor, S context) {
return statementVisitor.visit(this, context);
}

@Override
public String toString() {
return "SET ROLE " + roles;
}

public SetRoleStatement withRoles(RoleSelection roles) {
setRoles(roles);
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
import net.sf.jsqlparser.statement.alter.AlterType;
import net.sf.jsqlparser.statement.alter.AlterUserMapping;
import net.sf.jsqlparser.statement.alter.RenameTableStatement;
import net.sf.jsqlparser.statement.alter.AlterUser;
import net.sf.jsqlparser.statement.alter.RenameUser;
import net.sf.jsqlparser.statement.alter.database.AlterDatabase;
import net.sf.jsqlparser.statement.alter.schema.AlterSchema;
import net.sf.jsqlparser.statement.alter.sequence.AlterSequence;
Expand Down Expand Up @@ -867,6 +869,11 @@ public <S> Void visit(SetIdentityInsertStatement statement, S context) {
return sessionOnly();
}

@Override
public <S> Void visit(SetRoleStatement statement, S context) {
return sessionOnly();
}

@Override
public <S> Void visit(UseStatement use, S context) {
return sessionOnly();
Expand Down Expand Up @@ -1216,6 +1223,26 @@ public <S> Void visit(CreateUser statement, S context) {
return schemaOnly();
}

@Override
public <S> Void visit(AlterUser statement, S context) {
return schemaOnly();
}

@Override
public <S> Void visit(RenameUser statement, S context) {
return schemaOnly();
}

@Override
public <S> Void visit(SetDefaultRoleStatement statement, S context) {
return schemaOnly();
}

@Override
public <S> Void visit(SetPasswordStatement statement, S context) {
return schemaOnly();
}

// These statements store definitions; visiting their children must not make a stored
// rule action or policy predicate appear to execute during the DDL statement itself.

Expand Down
Loading
Loading