Skip to content

Commit db1781f

Browse files
committed
feat: parse MySQL 8.4 SHOW statements for variables, status, grants, logs and other server metadata
MySQL SHOW VARIABLES, STATUS, PROCESSLIST, GRANTS, WARNINGS, ERRORS, PROFILE, ENGINE, BINARY LOGS, BINLOG and RELAYLOG EVENTS, REPLICA STATUS, TRIGGERS, EVENTS, OPEN TABLES, routine STATUS and CODE, CHARACTER SET, COLLATION and DATABASES became UnsupportedStatement, or a ShowStatement for a single word, and SHOW INDEX FROM t FROM db failed to parse. Add MySqlShowStatement for these forms. Its Kind lists the parts each statement allows, and the values follow the MySQL 8.4 grammar: string LIKE patterns, log names and channels, unsigned limits and positions. It is read with Dialect.MYSQL and MARIADB and without a dialect; without a dialect a single word stays a ShowStatement, and the spellings removed in MySQL 8.4 (MASTER, SLAVE) are not read with Dialect.MYSQL. Share the {FROM | IN} db clause and the LIKE | WHERE filter as ShowDbSelection and ShowFilter, each read by one production, in SHOW TABLES, COLUMNS, TABLE STATUS and INDEX; the existing accessors read and write them. Extend ShowIndexStatement with EXTENDED, INDEXES and KEYS, IN, a Table, the trailing database and WHERE, and report its table in TablesNamesFinder. Let the whole-statement lookahead of the typed SHOW forms accept a WHERE filter after its first condition, so conditions with AND or OR no longer fall back to UnsupportedStatement. Signed-off-by: minleejae <mmj9808@gmail.com>
1 parent cf057dd commit db1781f

32 files changed

Lines changed: 3401 additions & 194 deletions

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ and missing syntax gets added on demand — [open an issue](https://github.com/J
158158
| **Tablespaces** | MySQL and PostgreSQL `CREATE TABLESPACE` · `ALTER TABLESPACE` |
159159
| **PostgreSQL RLS** | `CREATE POLICY` · `ALTER TABLE … ENABLE`/`DISABLE`/`FORCE`/`NO FORCE ROW LEVEL SECURITY` |
160160
| **Routine changes** | `ALTER FUNCTION` · `ALTER PROCEDURE` · `ALTER ROUTINE` · PostgreSQL `ALTER TRIGGER` |
161-
| **MySQL metadata statements** | `SHOW [FULL] COLUMNS`/`FIELDS` · `SHOW TABLE STATUS` · `SHOW CREATE TABLE`/`VIEW`/`PROCEDURE`/`FUNCTION`/`TRIGGER`/`EVENT`/`DATABASE`/`USER` |
161+
| **MySQL metadata statements** | `SHOW [FULL] COLUMNS`/`FIELDS` · `SHOW INDEX`/`INDEXES`/`KEYS` · `SHOW TABLE STATUS` · `SHOW CREATE TABLE`/`VIEW`/`PROCEDURE`/`FUNCTION`/`TRIGGER`/`EVENT`/`DATABASE`/`USER` · `SHOW [GLOBAL | SESSION] VARIABLES`/`STATUS` · `SHOW [FULL] PROCESSLIST` · `SHOW GRANTS [FOR …]` · `SHOW WARNINGS`/`ERRORS` · `SHOW BINARY LOGS`/`BINLOG EVENTS`/`RELAYLOG EVENTS` · `SHOW ENGINE …` · `SHOW PROFILE` · `SHOW DATABASES`/`TRIGGERS`/`EVENTS`/`OPEN TABLES`/`CHARACTER SET`/`COLLATION` · `SHOW PROCEDURE`/`FUNCTION STATUS`/`CODE` · `SHOW REPLICA STATUS`/`REPLICAS` |
162162
| **MySQL utility statements** | `EXPLAIN`/`DESCRIBE [ANALYZE] FORMAT = …` · `EXPLAIN FOR CONNECTION` · `DESCRIBE t col` · `PREPARE … FROM` · `EXECUTE … USING` · `DROP PREPARE` · `DO` |
163163
| **PostgreSQL administration** | `CREATE`/`ALTER EVENT TRIGGER` · `REINDEX` · `SECURITY LABEL` |
164164
| **PostgreSQL types and rules** | `CREATE TYPE` (shell, composite, enum, range and base types) · `ALTER TYPE` · `CREATE RULE` · `ALTER RULE` |

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -943,6 +943,13 @@ public enum Feature {
943943
* @see ShowCreateStatement
944944
*/
945945
showCreate,
946+
/**
947+
* The MySQL/MariaDB "SHOW" statements of server settings, state and object lists, such as "SHOW
948+
* VARIABLES", "SHOW GRANTS" or "SHOW BINLOG EVENTS"
949+
*
950+
* @see MySqlShowStatement
951+
*/
952+
mySqlShow,
946953
/**
947954
* @see UseStatement
948955
*/

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

Lines changed: 69 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@
99
*/
1010
package net.sf.jsqlparser.statement;
1111

12+
import java.util.function.Consumer;
1213
import net.sf.jsqlparser.expression.Expression;
1314
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
1415
import net.sf.jsqlparser.schema.Table;
16+
import net.sf.jsqlparser.statement.show.ShowDbSelection;
17+
import net.sf.jsqlparser.statement.show.ShowFilter;
1518
import net.sf.jsqlparser.statement.show.ShowTablesStatement.SelectionMode;
1619

1720
/**
@@ -27,10 +30,8 @@ public class ShowColumnsStatement extends ASTNodeAccessImpl implements Statement
2730
private boolean fieldsKeyword;
2831
private SelectionMode tableSelectionMode = SelectionMode.FROM;
2932
private Table table;
30-
private SelectionMode dbSelectionMode = SelectionMode.FROM;
31-
private String dbName;
32-
private Expression likeExpression;
33-
private Expression whereCondition;
33+
private ShowDbSelection dbSelection;
34+
private ShowFilter filter;
3435

3536
public ShowColumnsStatement() {
3637
// empty constructor
@@ -97,41 +98,73 @@ public void setTableName(String tableName) {
9798

9899
/** The keyword before the database name, {@code FROM} unless {@code IN} was written. */
99100
public SelectionMode getDbSelectionMode() {
100-
return dbSelectionMode;
101+
return dbSelection == null ? SelectionMode.FROM : dbSelection.getSelectionMode();
101102
}
102103

104+
/** Sets the keyword before the database name, which is kept until the name is set. */
103105
public void setDbSelectionMode(SelectionMode dbSelectionMode) {
104-
this.dbSelectionMode = dbSelectionMode;
106+
dbSelection = ShowDbSelection.updateSelectionMode(dbSelection, dbSelectionMode);
105107
}
106108

107109
/** The database of the trailing {@code FROM db} or {@code IN db} clause, or null. */
108110
public String getDbName() {
109-
return dbName;
111+
return ShowDbSelection.name(dbSelection);
110112
}
111113

112114
public void setDbName(String dbName) {
113-
this.dbName = dbName;
115+
dbSelection = ShowDbSelection.updateName(dbSelection, dbName);
116+
}
117+
118+
/** The trailing {@code {FROM | IN} db} clause, or null. */
119+
public ShowDbSelection getDbSelection() {
120+
return dbSelection;
121+
}
122+
123+
public void setDbSelection(ShowDbSelection dbSelection) {
124+
this.dbSelection = dbSelection;
125+
}
126+
127+
/** The {@code LIKE} or {@code WHERE} filter, or null. */
128+
public ShowFilter getFilter() {
129+
return filter;
130+
}
131+
132+
public void setFilter(ShowFilter filter) {
133+
this.filter = filter;
114134
}
115135

116136
public Expression getLikeExpression() {
117-
return likeExpression;
137+
return ShowFilter.likeExpression(filter);
118138
}
119139

140+
/** Sets a {@code LIKE} filter, which replaces a {@code WHERE} filter; null removes it. */
120141
public void setLikeExpression(Expression likeExpression) {
121-
this.likeExpression = likeExpression;
142+
filter = ShowFilter.replace(filter, ShowFilter.Kind.LIKE, likeExpression);
122143
}
123144

124145
public Expression getWhereCondition() {
125-
return whereCondition;
146+
return ShowFilter.whereCondition(filter);
126147
}
127148

149+
/** Sets a {@code WHERE} filter, which replaces a {@code LIKE} filter; null removes it. */
128150
public void setWhereCondition(Expression whereCondition) {
129-
this.whereCondition = whereCondition;
151+
filter = ShowFilter.replace(filter, ShowFilter.Kind.WHERE, whereCondition);
130152
}
131153

132-
@Override
133-
public String toString() {
134-
StringBuilder builder = new StringBuilder("SHOW");
154+
/**
155+
* The table the statement reads: {@link #getTable()}, or the table in the database of the
156+
* trailing {@code FROM db} clause, which MySQL reads as {@code db.table}.
157+
*/
158+
public Table getQualifiedTable() {
159+
if (table == null || !ShowDbSelection.isPresent(dbSelection)) {
160+
return table;
161+
}
162+
return new Table(dbSelection.getName(), table.getName());
163+
}
164+
165+
/** Appends the statement, printing the filter expression with the given printer. */
166+
public StringBuilder appendTo(StringBuilder builder, Consumer<Expression> printer) {
167+
builder.append("SHOW");
135168
if (extended) {
136169
builder.append(" EXTENDED");
137170
}
@@ -141,17 +174,19 @@ public String toString() {
141174
builder.append(fieldsKeyword ? " FIELDS " : " COLUMNS ")
142175
.append(tableSelectionMode == null ? SelectionMode.FROM : tableSelectionMode)
143176
.append(' ').append(table);
144-
if (dbName != null) {
145-
builder.append(' ')
146-
.append(dbSelectionMode == null ? SelectionMode.FROM : dbSelectionMode)
147-
.append(' ').append(dbName);
177+
if (ShowDbSelection.isPresent(dbSelection)) {
178+
builder.append(' ').append(dbSelection);
148179
}
149-
if (likeExpression != null) {
150-
builder.append(" LIKE ").append(likeExpression);
151-
} else if (whereCondition != null) {
152-
builder.append(" WHERE ").append(whereCondition);
180+
if (filter != null) {
181+
filter.appendTo(builder.append(' '), printer);
153182
}
154-
return builder.toString();
183+
return builder;
184+
}
185+
186+
@Override
187+
public String toString() {
188+
StringBuilder builder = new StringBuilder();
189+
return appendTo(builder, builder::append).toString();
155190
}
156191

157192
@Override
@@ -208,4 +243,14 @@ public ShowColumnsStatement withWhereCondition(Expression whereCondition) {
208243
this.setWhereCondition(whereCondition);
209244
return this;
210245
}
246+
247+
public ShowColumnsStatement withDbSelection(ShowDbSelection dbSelection) {
248+
this.setDbSelection(dbSelection);
249+
return this;
250+
}
251+
252+
public ShowColumnsStatement withFilter(ShowFilter filter) {
253+
this.setFilter(filter);
254+
return this;
255+
}
211256
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@
136136
import net.sf.jsqlparser.statement.select.SelectVisitorAdapter;
137137
import net.sf.jsqlparser.statement.select.TableStatement;
138138
import net.sf.jsqlparser.statement.select.WithItem;
139+
import net.sf.jsqlparser.statement.show.MySqlShowStatement;
139140
import net.sf.jsqlparser.statement.show.ShowCreateStatement;
140141
import net.sf.jsqlparser.statement.show.ShowIndexStatement;
141142
import net.sf.jsqlparser.statement.show.ShowTableStatusStatement;
@@ -1129,6 +1130,11 @@ public <S> Void visit(ShowCreateStatement showCreate, S context) {
11291130
return metadataOnly();
11301131
}
11311132

1133+
@Override
1134+
public <S> Void visit(MySqlShowStatement mySqlShow, S context) {
1135+
return metadataOnly();
1136+
}
1137+
11321138
@Override
11331139
public <S> Void visit(DescribeStatement describe, S context) {
11341140
return metadataOnly();

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@
109109
import net.sf.jsqlparser.statement.resourcegroup.SetResourceGroup;
110110
import net.sf.jsqlparser.statement.securitylabel.SecurityLabel;
111111
import net.sf.jsqlparser.statement.select.Select;
112+
import net.sf.jsqlparser.statement.show.MySqlShowStatement;
112113
import net.sf.jsqlparser.statement.show.ShowCreateStatement;
113114
import net.sf.jsqlparser.statement.show.ShowIndexStatement;
114115
import net.sf.jsqlparser.statement.show.ShowTableStatusStatement;
@@ -538,6 +539,14 @@ default void visit(ShowCreateStatement showCreate) {
538539
this.visit(showCreate, null);
539540
}
540541

542+
default <S> T visit(MySqlShowStatement mySqlShow, S context) {
543+
return null;
544+
}
545+
546+
default void visit(MySqlShowStatement mySqlShow) {
547+
this.visit(mySqlShow, null);
548+
}
549+
541550
<S> T visit(Merge merge, S context);
542551

543552
default void visit(Merge merge) {

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@
124124
import net.sf.jsqlparser.statement.select.SelectVisitor;
125125
import net.sf.jsqlparser.statement.select.SelectVisitorAdapter;
126126
import net.sf.jsqlparser.statement.select.WithItem;
127+
import net.sf.jsqlparser.statement.show.MySqlShowStatement;
127128
import net.sf.jsqlparser.statement.show.ShowCreateStatement;
128129
import net.sf.jsqlparser.statement.show.ShowIndexStatement;
129130
import net.sf.jsqlparser.statement.show.ShowTableStatusStatement;
@@ -714,6 +715,11 @@ public <S> T visit(ShowCreateStatement showCreate, S context) {
714715
return null;
715716
}
716717

718+
@Override
719+
public <S> T visit(MySqlShowStatement mySqlShow, S context) {
720+
return null;
721+
}
722+
717723
@Override
718724
public <S> T visit(DeclareStatement declareStatement, S context) {
719725
return null;

0 commit comments

Comments
 (0)