Skip to content

Commit 27396f6

Browse files
feat: parse MySQL spatial reference system statements and ALTER INSTANCE (#2911)
CREATE SPATIAL REFERENCE SYSTEM and ALTER INSTANCE came back as UnsupportedStatement, and DROP SPATIAL REFERENCE SYSTEM failed to parse. CREATE [OR REPLACE] SPATIAL REFERENCE SYSTEM [IF NOT EXISTS] is the new CreateSpatialReferenceSystem: the SRID as written and the NAME, DEFINITION, ORGANIZATION ... IDENTIFIED BY and DESCRIPTION attributes in source order, with typed getters derived from that list. As in MySQL's grammar the attributes come in any order and number; the server reports a repeated or missing attribute when it runs the statement. DROP SPATIAL REFERENCE SYSTEM [IF EXISTS] srid is a Drop with the new object type SPATIAL_REFERENCE_SYSTEM, named by its SRID. ALTER INSTANCE is the new AlterInstance with an Action for the redo log, master key, TLS and keyring forms, and the channel and NO ROLLBACK ON ERROR of RELOAD TLS. The statements are read with the MySQL dialect and without a dialect, add no token, and are wired into the deparser, visitors, table finder, feature analysis and validation, with the new features createSpatialReferenceSystem and alterInstance. Signed-off-by: minleejae <mmj9808@gmail.com> Co-authored-by: manticore-projects <andreas@manticore-projects.com>
1 parent 1b33d15 commit 27396f6

20 files changed

Lines changed: 1694 additions & 3 deletions

File tree

‎README.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ and missing syntax gets added on demand — [open an issue](https://github.com/J
158158
| **PostgreSQL cursors** | `DECLARE … CURSOR` · `FETCH` · `MOVE` · `CLOSE` |
159159
| **MySQL account management** | `CREATE`/`ALTER`/`RENAME USER` · `CREATE ROLE` · `SET ROLE` · `SET DEFAULT ROLE` · `SET PASSWORD` |
160160
| **Tablespaces** | MySQL and PostgreSQL `CREATE TABLESPACE` · `ALTER TABLESPACE` |
161+
| **MySQL spatial reference systems and instance** | `CREATE`/`DROP SPATIAL REFERENCE SYSTEM` · `ALTER INSTANCE` |
161162
| **PostgreSQL RLS** | `CREATE POLICY` · `ALTER TABLE … ENABLE`/`DISABLE`/`FORCE`/`NO FORCE ROW LEVEL SECURITY` |
162163
| **Routine changes** | `ALTER FUNCTION` · `ALTER PROCEDURE` · `ALTER ROUTINE` · PostgreSQL `ALTER TRIGGER` |
163164
| **MySQL metadata statements** | `SHOW [FULL] COLUMNS`/`FIELDS` · `SHOW TABLE STATUS` · `SHOW CREATE TABLE`/`VIEW`/`PROCEDURE`/`FUNCTION`/`TRIGGER`/`EVENT`/`DATABASE`/`USER` |

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,18 @@ public enum Feature {
487487
* @see net.sf.jsqlparser.statement.alter.AlterTablespace
488488
*/
489489
alterTablespace,
490+
/**
491+
* MySQL "CREATE SPATIAL REFERENCE SYSTEM" statement is allowed
492+
*
493+
* @see net.sf.jsqlparser.statement.create.spatial.CreateSpatialReferenceSystem
494+
*/
495+
createSpatialReferenceSystem,
496+
/**
497+
* MySQL "ALTER INSTANCE" statement is allowed
498+
*
499+
* @see net.sf.jsqlparser.statement.alter.AlterInstance
500+
*/
501+
alterInstance,
490502

491503

492504
/**

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import net.sf.jsqlparser.statement.alter.AlterStatistics;
4343
import net.sf.jsqlparser.statement.alter.AlterSubscription;
4444
import net.sf.jsqlparser.statement.alter.AlterEventTrigger;
45+
import net.sf.jsqlparser.statement.alter.AlterInstance;
4546
import net.sf.jsqlparser.statement.alter.AlterSystemStatement;
4647
import net.sf.jsqlparser.statement.alter.AlterTablespace;
4748
import net.sf.jsqlparser.statement.alter.AlterTablespaceMove;
@@ -76,6 +77,7 @@
7677
import net.sf.jsqlparser.statement.create.subscription.SubscriptionOption;
7778
import net.sf.jsqlparser.statement.create.synonym.CreateSynonym;
7879
import net.sf.jsqlparser.statement.create.table.CreateTable;
80+
import net.sf.jsqlparser.statement.create.spatial.CreateSpatialReferenceSystem;
7981
import net.sf.jsqlparser.statement.create.tablespace.CreateTablespace;
8082
import net.sf.jsqlparser.statement.create.textsearch.CreateTextSearchConfiguration;
8183
import net.sf.jsqlparser.statement.create.trigger.CreateEventTrigger;
@@ -1482,6 +1484,17 @@ public <S> Void visit(CreateTablespace statement, S context) {
14821484
return schemaOnly();
14831485
}
14841486

1487+
@Override
1488+
public <S> Void visit(CreateSpatialReferenceSystem statement, S context) {
1489+
return schemaOnly();
1490+
}
1491+
1492+
/** A server operation, like ALTER SYSTEM. */
1493+
@Override
1494+
public <S> Void visit(AlterInstance statement, S context) {
1495+
return sessionOnly();
1496+
}
1497+
14851498
@Override
14861499
public <S> Void visit(AlterTablespace statement, S context) {
14871500
return schemaOnly();

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
import net.sf.jsqlparser.statement.alter.Alter;
6161
import net.sf.jsqlparser.statement.alter.AlterSession;
6262
import net.sf.jsqlparser.statement.alter.AlterEventTrigger;
63+
import net.sf.jsqlparser.statement.alter.AlterInstance;
6364
import net.sf.jsqlparser.statement.alter.AlterSystemStatement;
6465
import net.sf.jsqlparser.statement.alter.RenameTableStatement;
6566
import net.sf.jsqlparser.statement.alter.AlterUser;
@@ -76,6 +77,7 @@
7677
import net.sf.jsqlparser.statement.create.sequence.CreateSequence;
7778
import net.sf.jsqlparser.statement.create.synonym.CreateSynonym;
7879
import net.sf.jsqlparser.statement.create.table.CreateTable;
80+
import net.sf.jsqlparser.statement.create.spatial.CreateSpatialReferenceSystem;
7981
import net.sf.jsqlparser.statement.create.tablespace.CreateTablespace;
8082
import net.sf.jsqlparser.statement.create.trigger.CreateEventTrigger;
8183
import net.sf.jsqlparser.statement.create.trigger.CreateTrigger;
@@ -1026,6 +1028,22 @@ default void visit(CreateTablespace statement) {
10261028
visit(statement, null);
10271029
}
10281030

1031+
default <S> T visit(CreateSpatialReferenceSystem statement, S context) {
1032+
return null;
1033+
}
1034+
1035+
default void visit(CreateSpatialReferenceSystem statement) {
1036+
visit(statement, null);
1037+
}
1038+
1039+
default <S> T visit(AlterInstance statement, S context) {
1040+
return null;
1041+
}
1042+
1043+
default void visit(AlterInstance statement) {
1044+
visit(statement, null);
1045+
}
1046+
10291047
default <S> T visit(AlterTablespace statement, S context) {
10301048
return null;
10311049
}

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
import net.sf.jsqlparser.statement.alter.AlterExpression;
6363
import net.sf.jsqlparser.statement.alter.AlterSession;
6464
import net.sf.jsqlparser.statement.alter.AlterEventTrigger;
65+
import net.sf.jsqlparser.statement.alter.AlterInstance;
6566
import net.sf.jsqlparser.statement.alter.AlterSystemStatement;
6667
import net.sf.jsqlparser.statement.alter.RenameTableStatement;
6768
import net.sf.jsqlparser.statement.alter.AlterUser;
@@ -78,6 +79,7 @@
7879
import net.sf.jsqlparser.statement.create.sequence.CreateSequence;
7980
import net.sf.jsqlparser.statement.create.synonym.CreateSynonym;
8081
import net.sf.jsqlparser.statement.create.table.CreateTable;
82+
import net.sf.jsqlparser.statement.create.spatial.CreateSpatialReferenceSystem;
8183
import net.sf.jsqlparser.statement.create.tablespace.CreateTablespace;
8284
import net.sf.jsqlparser.statement.create.trigger.CreateEventTrigger;
8385
import net.sf.jsqlparser.statement.create.trigger.CreateTrigger;
@@ -1150,6 +1152,16 @@ public <S> T visit(CreateTablespace statement, S context) {
11501152
return null;
11511153
}
11521154

1155+
@Override
1156+
public <S> T visit(CreateSpatialReferenceSystem statement, S context) {
1157+
return null;
1158+
}
1159+
1160+
@Override
1161+
public <S> T visit(AlterInstance statement, S context) {
1162+
return null;
1163+
}
1164+
11531165
@Override
11541166
public <S> T visit(AlterTablespace statement, S context) {
11551167
statement.visitExpressions(expression -> expression.accept(expressionVisitor, context));
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
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.alter;
11+
12+
import java.util.Objects;
13+
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
14+
import net.sf.jsqlparser.statement.Statement;
15+
import net.sf.jsqlparser.statement.StatementVisitor;
16+
17+
/**
18+
* MySQL {@code ALTER INSTANCE}, which acts on the server instance:
19+
* {@code {ENABLE | DISABLE} INNODB REDO_LOG}, {@code ROTATE INNODB MASTER KEY},
20+
* {@code ROTATE BINLOG MASTER KEY}, {@code RELOAD TLS [FOR CHANNEL channel] [NO ROLLBACK ON ERROR]}
21+
* and {@code RELOAD KEYRING}.
22+
*
23+
* <p>
24+
* MySQL reads INNODB, BINLOG and REDO_LOG as identifiers, so they may be quoted; the statement
25+
* renders them as plain words. The channel is kept as written: MySQL's grammar takes any
26+
* identifier, and the server accepts {@code mysql_main} and {@code mysql_admin} when it runs the
27+
* statement.
28+
*
29+
* @see <a href="https://dev.mysql.com/doc/refman/8.4/en/alter-instance.html">MySQL ALTER
30+
* INSTANCE</a>
31+
*/
32+
public class AlterInstance extends ASTNodeAccessImpl implements Statement {
33+
/** The words after ALTER INSTANCE, without the options of RELOAD TLS. */
34+
public enum Action {
35+
ENABLE_INNODB_REDO_LOG("ENABLE INNODB REDO_LOG"), DISABLE_INNODB_REDO_LOG(
36+
"DISABLE INNODB REDO_LOG"), ROTATE_INNODB_MASTER_KEY(
37+
"ROTATE INNODB MASTER KEY"), ROTATE_BINLOG_MASTER_KEY(
38+
"ROTATE BINLOG MASTER KEY"), RELOAD_TLS(
39+
"RELOAD TLS"), RELOAD_KEYRING("RELOAD KEYRING");
40+
41+
private final String sql;
42+
43+
Action(String sql) {
44+
this.sql = sql;
45+
}
46+
47+
public String getSql() {
48+
return sql;
49+
}
50+
}
51+
52+
private Action action;
53+
private String channel;
54+
private boolean noRollbackOnError;
55+
56+
public AlterInstance(Action action) {
57+
this.action = Objects.requireNonNull(action, "action");
58+
}
59+
60+
public Action getAction() {
61+
return action;
62+
}
63+
64+
/**
65+
* Sets the action.
66+
*
67+
* @throws IllegalArgumentException if the statement has options of RELOAD TLS and the action is
68+
* another one
69+
*/
70+
public void setAction(Action action) {
71+
Objects.requireNonNull(action, "action");
72+
if (action != Action.RELOAD_TLS && (channel != null || noRollbackOnError)) {
73+
throw new IllegalArgumentException(
74+
"FOR CHANNEL and NO ROLLBACK ON ERROR belong to RELOAD TLS");
75+
}
76+
this.action = action;
77+
}
78+
79+
public AlterInstance withAction(Action action) {
80+
setAction(action);
81+
return this;
82+
}
83+
84+
/** The identifier of {@code RELOAD TLS FOR CHANNEL channel} as written, or null. */
85+
public String getChannel() {
86+
return channel;
87+
}
88+
89+
/**
90+
* Sets the channel of RELOAD TLS; null removes the clause.
91+
*
92+
* @throws IllegalArgumentException if the action is not RELOAD TLS
93+
*/
94+
public void setChannel(String channel) {
95+
if (channel != null && action != Action.RELOAD_TLS) {
96+
throw new IllegalArgumentException("FOR CHANNEL belongs to RELOAD TLS");
97+
}
98+
this.channel = channel;
99+
}
100+
101+
public AlterInstance withChannel(String channel) {
102+
setChannel(channel);
103+
return this;
104+
}
105+
106+
/** Whether RELOAD TLS ends with NO ROLLBACK ON ERROR. */
107+
public boolean isNoRollbackOnError() {
108+
return noRollbackOnError;
109+
}
110+
111+
/**
112+
* Sets NO ROLLBACK ON ERROR.
113+
*
114+
* @throws IllegalArgumentException if the action is not RELOAD TLS
115+
*/
116+
public void setNoRollbackOnError(boolean noRollbackOnError) {
117+
if (noRollbackOnError && action != Action.RELOAD_TLS) {
118+
throw new IllegalArgumentException("NO ROLLBACK ON ERROR belongs to RELOAD TLS");
119+
}
120+
this.noRollbackOnError = noRollbackOnError;
121+
}
122+
123+
public AlterInstance withNoRollbackOnError(boolean noRollbackOnError) {
124+
setNoRollbackOnError(noRollbackOnError);
125+
return this;
126+
}
127+
128+
public StringBuilder appendTo(StringBuilder builder) {
129+
builder.append("ALTER INSTANCE ").append(action.getSql());
130+
if (channel != null) {
131+
builder.append(" FOR CHANNEL ").append(channel);
132+
}
133+
if (noRollbackOnError) {
134+
builder.append(" NO ROLLBACK ON ERROR");
135+
}
136+
return builder;
137+
}
138+
139+
@Override
140+
public String toString() {
141+
return appendTo(new StringBuilder()).toString();
142+
}
143+
144+
@Override
145+
public <T, S> T accept(StatementVisitor<T> statementVisitor, S context) {
146+
return statementVisitor.visit(this, context);
147+
}
148+
}

0 commit comments

Comments
 (0)