Skip to content

Commit 186fb5d

Browse files
authored
feat: parse MySQL resource group statements (#2907)
CREATE RESOURCE GROUP and ALTER RESOURCE GROUP were read as UnsupportedStatement, SET RESOURCE GROUP and DROP RESOURCE GROUP ... FORCE failed, and DROP RESOURCE GROUP rg was a Drop of type RESOURCE named GROUP. Add CreateResourceGroup and AlterResourceGroup, which share the name, the VCPU list (VcpuRange), the thread priority and the ENABLE or DISABLE state through ResourceGroupDefinition, and SetResourceGroup with its thread IDs. DROP RESOURCE GROUP is a Drop with the object type RESOURCE_GROUP and the existing force flag. The statements are read with the MySQL dialect or none and follow MySQL's grammar: the option order, the optional = or :=, the optional commas, a signed THREAD_PRIORITY, and FORCE after ALTER and DROP. RESOURCE, VCPU and THREAD_PRIORITY stay usable as names; no token is added. Wire the statements into the deparser, visitors, table finder, feature analysis and validation, with new createResourceGroup, alterResourceGroup and setResourceGroup features. Signed-off-by: minleejae <mmj9808@gmail.com>
1 parent fcfb6c9 commit 186fb5d

22 files changed

Lines changed: 1499 additions & 4 deletions

File tree

‎README.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ and missing syntax gets added on demand — [open an issue](https://github.com/J
151151
| **MySQL table maintenance** | `ANALYZE` · `CHECK` · `CHECKSUM` · `OPTIMIZE` · `REPAIR TABLE` |
152152
| **PostgreSQL maintenance** | `VACUUM` · `ANALYZE` · `CLUSTER` · `CHECKPOINT` |
153153
| **MySQL locks** | `LOCK TABLES` · `UNLOCK TABLES` · `LOCK INSTANCE FOR BACKUP` · `UNLOCK INSTANCE` |
154+
| **MySQL resource groups** | `CREATE`/`ALTER`/`DROP RESOURCE GROUP` · `SET RESOURCE GROUP` |
154155
| **PostgreSQL session statements** | `DISCARD` · `LISTEN` · `UNLISTEN` · `SHOW`/`RESET TIME ZONE`/`TRANSACTION ISOLATION LEVEL`/`SESSION AUTHORIZATION` · `COPY` options from before 9.0 |
155156
| **MySQL server administration** | `FLUSH` · `KILL` · `RESET PERSIST` · `HANDLER … OPEN`/`READ`/`CLOSE` |
156157
| **MySQL account management** | `CREATE`/`ALTER`/`RENAME USER` · `CREATE ROLE` · `SET ROLE` · `SET DEFAULT ROLE` · `SET PASSWORD` |

‎src/main/java/net/sf/jsqlparser/parser/feature/Feature.java‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@
6363
import net.sf.jsqlparser.statement.merge.Merge;
6464
import net.sf.jsqlparser.statement.refresh.RefreshMaterializedViewStatement;
6565
import net.sf.jsqlparser.statement.reindex.Reindex;
66+
import net.sf.jsqlparser.statement.resourcegroup.AlterResourceGroup;
67+
import net.sf.jsqlparser.statement.resourcegroup.CreateResourceGroup;
68+
import net.sf.jsqlparser.statement.resourcegroup.SetResourceGroup;
6669
import net.sf.jsqlparser.statement.role.ReassignOwned;
6770
import net.sf.jsqlparser.statement.select.Fetch;
6871
import net.sf.jsqlparser.statement.select.First;
@@ -825,6 +828,24 @@ public enum Feature {
825828
* @see BackupLockStatement
826829
*/
827830
backupLock,
831+
/**
832+
* MySQL "CREATE RESOURCE GROUP" statement is allowed
833+
*
834+
* @see CreateResourceGroup
835+
*/
836+
createResourceGroup,
837+
/**
838+
* MySQL "ALTER RESOURCE GROUP" statement is allowed
839+
*
840+
* @see AlterResourceGroup
841+
*/
842+
alterResourceGroup,
843+
/**
844+
* MySQL "SET RESOURCE GROUP" statement is allowed
845+
*
846+
* @see SetResourceGroup
847+
*/
848+
setResourceGroup,
828849
/**
829850
* SQL "COMMENT ON" statement is allowed
830851
*

‎src/main/java/net/sf/jsqlparser/statement/StatementFeatureVisitor.java‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@
114114
import net.sf.jsqlparser.statement.oracle.OracleNullStatement;
115115
import net.sf.jsqlparser.statement.refresh.RefreshMaterializedViewStatement;
116116
import net.sf.jsqlparser.statement.reindex.Reindex;
117+
import net.sf.jsqlparser.statement.resourcegroup.AlterResourceGroup;
118+
import net.sf.jsqlparser.statement.resourcegroup.CreateResourceGroup;
119+
import net.sf.jsqlparser.statement.resourcegroup.SetResourceGroup;
117120
import net.sf.jsqlparser.statement.securitylabel.SecurityLabel;
118121
import net.sf.jsqlparser.statement.role.AlterRole;
119122
import net.sf.jsqlparser.statement.role.CreateRole;
@@ -973,6 +976,21 @@ public <S> Void visit(XaStatement statement, S context) {
973976
: transactionOnly();
974977
}
975978

979+
@Override
980+
public <S> Void visit(CreateResourceGroup statement, S context) {
981+
return schemaOnly();
982+
}
983+
984+
@Override
985+
public <S> Void visit(AlterResourceGroup statement, S context) {
986+
return schemaOnly();
987+
}
988+
989+
@Override
990+
public <S> Void visit(SetResourceGroup statement, S context) {
991+
return sessionOnly();
992+
}
993+
976994
@Override
977995
public <S> Void visit(Commit commit, S context) {
978996
return transactionOnly();

‎src/main/java/net/sf/jsqlparser/statement/StatementVisitor.java‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@
103103
import net.sf.jsqlparser.statement.merge.Merge;
104104
import net.sf.jsqlparser.statement.refresh.RefreshMaterializedViewStatement;
105105
import net.sf.jsqlparser.statement.reindex.Reindex;
106+
import net.sf.jsqlparser.statement.resourcegroup.AlterResourceGroup;
107+
import net.sf.jsqlparser.statement.resourcegroup.CreateResourceGroup;
108+
import net.sf.jsqlparser.statement.resourcegroup.SetResourceGroup;
106109
import net.sf.jsqlparser.statement.securitylabel.SecurityLabel;
107110
import net.sf.jsqlparser.statement.select.Select;
108111
import net.sf.jsqlparser.statement.show.ShowCreateStatement;
@@ -200,6 +203,30 @@ default void visit(XaStatement statement) {
200203
visit(statement, null);
201204
}
202205

206+
default <S> T visit(CreateResourceGroup statement, S context) {
207+
return null;
208+
}
209+
210+
default void visit(CreateResourceGroup statement) {
211+
visit(statement, null);
212+
}
213+
214+
default <S> T visit(AlterResourceGroup statement, S context) {
215+
return null;
216+
}
217+
218+
default void visit(AlterResourceGroup statement) {
219+
visit(statement, null);
220+
}
221+
222+
default <S> T visit(SetResourceGroup statement, S context) {
223+
return null;
224+
}
225+
226+
default void visit(SetResourceGroup statement) {
227+
visit(statement, null);
228+
}
229+
203230
<S> T visit(Commit commit, S context);
204231

205232
default void visit(Commit commit) {

‎src/main/java/net/sf/jsqlparser/statement/StatementVisitorAdapter.java‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@
108108
import net.sf.jsqlparser.statement.merge.MergeOperationVisitorAdapter;
109109
import net.sf.jsqlparser.statement.refresh.RefreshMaterializedViewStatement;
110110
import net.sf.jsqlparser.statement.reindex.Reindex;
111+
import net.sf.jsqlparser.statement.resourcegroup.AlterResourceGroup;
112+
import net.sf.jsqlparser.statement.resourcegroup.CreateResourceGroup;
113+
import net.sf.jsqlparser.statement.resourcegroup.SetResourceGroup;
111114
import net.sf.jsqlparser.statement.securitylabel.SecurityLabel;
112115
import net.sf.jsqlparser.statement.select.FromItem;
113116
import net.sf.jsqlparser.statement.select.FromItemVisitor;
@@ -265,6 +268,21 @@ public <S> T visit(XaStatement statement, S context) {
265268
return null;
266269
}
267270

271+
@Override
272+
public <S> T visit(CreateResourceGroup statement, S context) {
273+
return null;
274+
}
275+
276+
@Override
277+
public <S> T visit(AlterResourceGroup statement, S context) {
278+
return null;
279+
}
280+
281+
@Override
282+
public <S> T visit(SetResourceGroup statement, S context) {
283+
return null;
284+
}
285+
268286
@Override
269287
public <S> T visit(Commit commit, S context) {
270288

‎src/main/java/net/sf/jsqlparser/statement/drop/Drop.java‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
public class Drop extends ASTNodeAccessImpl implements Statement {
3636

3737
public enum ObjectType {
38-
DATABASE, EVENT, FUNCTION, INDEX, PROCEDURE, SCHEMA, SEQUENCE, SERVER, TABLE, TABLESPACE, TRIGGER, VIEW, FOREIGN_TABLE, FOREIGN_DATA_WRAPPER, AGGREGATE, DOMAIN, EVENT_TRIGGER, GROUP, OWNED, ROLE, ROUTINE, RULE, TYPE, USER, SYNONYM, ACCESS_METHOD, LANGUAGE, OPERATOR_CLASS, OPERATOR_FAMILY, TEXT_SEARCH_CONFIGURATION, TEXT_SEARCH_DICTIONARY, TEXT_SEARCH_PARSER, TEXT_SEARCH_TEMPLATE, CAST, OPERATOR, TRANSFORM, OTHER;
38+
DATABASE, EVENT, FUNCTION, INDEX, PROCEDURE, SCHEMA, SEQUENCE, SERVER, TABLE, TABLESPACE, TRIGGER, VIEW, FOREIGN_TABLE, FOREIGN_DATA_WRAPPER, AGGREGATE, DOMAIN, EVENT_TRIGGER, GROUP, OWNED, ROLE, ROUTINE, RULE, TYPE, USER, SYNONYM, ACCESS_METHOD, LANGUAGE, OPERATOR_CLASS, OPERATOR_FAMILY, TEXT_SEARCH_CONFIGURATION, TEXT_SEARCH_DICTIONARY, TEXT_SEARCH_PARSER, TEXT_SEARCH_TEMPLATE, CAST, OPERATOR, TRANSFORM, RESOURCE_GROUP, OTHER;
3939

4040
/** Targets are {@link RoutineReference}s, each with an optional argument signature. */
4141
public boolean hasRoutineTargets() {
@@ -432,7 +432,10 @@ public Drop withUndo(boolean undo) {
432432
return this;
433433
}
434434

435-
/** PostgreSQL DROP DATABASE ... WITH (FORCE), or Oracle DROP SYNONYM ... FORCE. */
435+
/**
436+
* PostgreSQL DROP DATABASE ... WITH (FORCE), or Oracle DROP SYNONYM ... FORCE and MySQL DROP
437+
* RESOURCE GROUP ... FORCE.
438+
*/
436439
public boolean isForce() {
437440
return force;
438441
}
@@ -634,7 +637,8 @@ public StringBuilder appendTo(StringBuilder builder, Consumer<Table> tablePrinte
634637
builder.append(" USING ").append(accessMethod);
635638
}
636639
if (force) {
637-
builder.append(objectType == ObjectType.SYNONYM ? " FORCE" : " WITH (FORCE)");
640+
builder.append(objectType == ObjectType.SYNONYM
641+
|| objectType == ObjectType.RESOURCE_GROUP ? " FORCE" : " WITH (FORCE)");
638642
}
639643
if (engine != null) {
640644
builder.append(engineUseEquals ? " ENGINE = " : " ENGINE ").append(engine);
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*-
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2026 JSQLParser
6+
* %%
7+
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
8+
* #L%
9+
*/
10+
package net.sf.jsqlparser.statement.resourcegroup;
11+
12+
import java.util.Collection;
13+
import java.util.List;
14+
import net.sf.jsqlparser.statement.StatementVisitor;
15+
16+
/**
17+
* MySQL {@code ALTER RESOURCE GROUP group_name [VCPU [=] vcpu_spec [, vcpu_spec] ...]
18+
* [THREAD_PRIORITY [=] N] [ENABLE | DISABLE] [FORCE]}. MySQL's grammar takes FORCE without DISABLE
19+
* too.
20+
*
21+
* @see <a href="https://dev.mysql.com/doc/refman/8.4/en/alter-resource-group.html">MySQL ALTER
22+
* RESOURCE GROUP Statement</a>
23+
*/
24+
public class AlterResourceGroup extends ResourceGroupDefinition {
25+
private boolean force;
26+
27+
public AlterResourceGroup() {
28+
// the parser fills the statement in
29+
}
30+
31+
public AlterResourceGroup(String name) {
32+
super(name);
33+
}
34+
35+
/** Whether FORCE is written: the group is changed although threads are assigned to it. */
36+
public boolean isForce() {
37+
return force;
38+
}
39+
40+
public void setForce(boolean force) {
41+
this.force = force;
42+
}
43+
44+
public AlterResourceGroup withForce(boolean force) {
45+
setForce(force);
46+
return this;
47+
}
48+
49+
public AlterResourceGroup withVcpus(List<VcpuRange> vcpus) {
50+
setVcpus(vcpus);
51+
return this;
52+
}
53+
54+
public AlterResourceGroup addVcpuRanges(Collection<? extends VcpuRange> vcpus) {
55+
addVcpus(vcpus);
56+
return this;
57+
}
58+
59+
public AlterResourceGroup withThreadPriority(Integer threadPriority) {
60+
setThreadPriority(threadPriority);
61+
return this;
62+
}
63+
64+
public AlterResourceGroup withState(State state) {
65+
setState(state);
66+
return this;
67+
}
68+
69+
@Override
70+
public StringBuilder appendTo(StringBuilder builder) {
71+
appendOptionsTo(builder.append("ALTER RESOURCE GROUP ").append(getName()));
72+
return force ? builder.append(" FORCE") : builder;
73+
}
74+
75+
@Override
76+
public <T, S> T accept(StatementVisitor<T> statementVisitor, S context) {
77+
return statementVisitor.visit(this, context);
78+
}
79+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*-
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2026 JSQLParser
6+
* %%
7+
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
8+
* #L%
9+
*/
10+
package net.sf.jsqlparser.statement.resourcegroup;
11+
12+
import java.util.Collection;
13+
import java.util.List;
14+
import java.util.Objects;
15+
import net.sf.jsqlparser.statement.StatementVisitor;
16+
17+
/**
18+
* MySQL {@code CREATE RESOURCE GROUP group_name TYPE [=] {SYSTEM | USER} [VCPU [=] vcpu_spec [,
19+
* vcpu_spec] ...] [THREAD_PRIORITY [=] N] [ENABLE | DISABLE]}.
20+
*
21+
* @see <a href="https://dev.mysql.com/doc/refman/8.4/en/create-resource-group.html">MySQL CREATE
22+
* RESOURCE GROUP Statement</a>
23+
*/
24+
public class CreateResourceGroup extends ResourceGroupDefinition {
25+
/** Whether the group takes system threads or user threads. */
26+
public enum Type {
27+
SYSTEM, USER
28+
}
29+
30+
private Type type;
31+
private OptionAssignment typeAssignment = OptionAssignment.EQUALS;
32+
33+
public CreateResourceGroup() {
34+
// the parser fills the statement in
35+
}
36+
37+
public CreateResourceGroup(String name, Type type) {
38+
super(name);
39+
setType(type);
40+
}
41+
42+
public Type getType() {
43+
return type;
44+
}
45+
46+
public final void setType(Type type) {
47+
this.type = Objects.requireNonNull(type, "type");
48+
}
49+
50+
public OptionAssignment getTypeAssignment() {
51+
return typeAssignment;
52+
}
53+
54+
public void setTypeAssignment(OptionAssignment typeAssignment) {
55+
this.typeAssignment = Objects.requireNonNull(typeAssignment, "typeAssignment");
56+
}
57+
58+
public CreateResourceGroup withTypeAssignment(OptionAssignment typeAssignment) {
59+
setTypeAssignment(typeAssignment);
60+
return this;
61+
}
62+
63+
public CreateResourceGroup withVcpus(List<VcpuRange> vcpus) {
64+
setVcpus(vcpus);
65+
return this;
66+
}
67+
68+
public CreateResourceGroup addVcpuRanges(Collection<? extends VcpuRange> vcpus) {
69+
addVcpus(vcpus);
70+
return this;
71+
}
72+
73+
public CreateResourceGroup withThreadPriority(Integer threadPriority) {
74+
setThreadPriority(threadPriority);
75+
return this;
76+
}
77+
78+
public CreateResourceGroup withState(State state) {
79+
setState(state);
80+
return this;
81+
}
82+
83+
@Override
84+
public StringBuilder appendTo(StringBuilder builder) {
85+
builder.append("CREATE RESOURCE GROUP ").append(getName()).append(' ');
86+
typeAssignment.appendTo(builder, "TYPE").append(type);
87+
return appendOptionsTo(builder);
88+
}
89+
90+
@Override
91+
public <T, S> T accept(StatementVisitor<T> statementVisitor, S context) {
92+
return statementVisitor.visit(this, context);
93+
}
94+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*-
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2026 JSQLParser
6+
* %%
7+
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
8+
* #L%
9+
*/
10+
package net.sf.jsqlparser.statement.resourcegroup;
11+
12+
/**
13+
* How a MySQL resource group option is joined to its value: {@code TYPE USER}, {@code TYPE = USER}
14+
* or {@code TYPE := USER}. MySQL reads the three alike.
15+
*/
16+
public enum OptionAssignment {
17+
NONE(""), EQUALS("="), COLON_EQUALS(":=");
18+
19+
private final String symbol;
20+
21+
OptionAssignment(String symbol) {
22+
this.symbol = symbol;
23+
}
24+
25+
/** The symbol as written, empty for {@link #NONE}. */
26+
public String getSymbol() {
27+
return symbol;
28+
}
29+
30+
/** Appends the option name, the symbol if there is one, and a space before the value. */
31+
StringBuilder appendTo(StringBuilder builder, String option) {
32+
builder.append(option).append(' ');
33+
return this == NONE ? builder : builder.append(symbol).append(' ');
34+
}
35+
}

0 commit comments

Comments
 (0)