Skip to content

Commit 487ad0f

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 e27929f commit 487ad0f

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
@@ -156,7 +156,7 @@ and missing syntax gets added on demand — [open an issue](https://github.com/J
156156
| **Tablespaces** | MySQL and PostgreSQL `CREATE TABLESPACE` · `ALTER TABLESPACE` |
157157
| **PostgreSQL RLS** | `CREATE POLICY` · `ALTER TABLE … ENABLE`/`DISABLE`/`FORCE`/`NO FORCE ROW LEVEL SECURITY` |
158158
| **Routine changes** | `ALTER FUNCTION` · `ALTER PROCEDURE` · `ALTER ROUTINE` · PostgreSQL `ALTER TRIGGER` |
159-
| **MySQL metadata statements** | `SHOW [FULL] COLUMNS`/`FIELDS` · `SHOW TABLE STATUS` · `SHOW CREATE TABLE`/`VIEW`/`PROCEDURE`/`FUNCTION`/`TRIGGER`/`EVENT`/`DATABASE`/`USER` |
159+
| **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` |
160160
| **PostgreSQL administration** | `CREATE`/`ALTER EVENT TRIGGER` · `REINDEX` · `SECURITY LABEL` |
161161
| **Informix constraints** | `ALTER TABLE … ADD CONSTRAINT` with trailing constraint names for primary, unique, foreign and check constraints; enable with `parser.withDialect(Dialect.INFORMIX)` |
162162
| **Salesforce SOQL** | `INCLUDES` · `EXCLUDES` |

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -893,6 +893,13 @@ public enum Feature {
893893
* @see ShowCreateStatement
894894
*/
895895
showCreate,
896+
/**
897+
* The MySQL/MariaDB "SHOW" statements of server settings, state and object lists, such as "SHOW
898+
* VARIABLES", "SHOW GRANTS" or "SHOW BINLOG EVENTS"
899+
*
900+
* @see MySqlShowStatement
901+
*/
902+
mySqlShow,
896903
/**
897904
* @see UseStatement
898905
*/

‎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
@@ -129,6 +129,7 @@
129129
import net.sf.jsqlparser.statement.select.SelectVisitorAdapter;
130130
import net.sf.jsqlparser.statement.select.TableStatement;
131131
import net.sf.jsqlparser.statement.select.WithItem;
132+
import net.sf.jsqlparser.statement.show.MySqlShowStatement;
132133
import net.sf.jsqlparser.statement.show.ShowCreateStatement;
133134
import net.sf.jsqlparser.statement.show.ShowIndexStatement;
134135
import net.sf.jsqlparser.statement.show.ShowTableStatusStatement;
@@ -1065,6 +1066,11 @@ public <S> Void visit(ShowCreateStatement showCreate, S context) {
10651066
return metadataOnly();
10661067
}
10671068

1069+
@Override
1070+
public <S> Void visit(MySqlShowStatement mySqlShow, S context) {
1071+
return metadataOnly();
1072+
}
1073+
10681074
@Override
10691075
public <S> Void visit(DescribeStatement describe, S context) {
10701076
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
@@ -102,6 +102,7 @@
102102
import net.sf.jsqlparser.statement.reindex.Reindex;
103103
import net.sf.jsqlparser.statement.securitylabel.SecurityLabel;
104104
import net.sf.jsqlparser.statement.select.Select;
105+
import net.sf.jsqlparser.statement.show.MySqlShowStatement;
105106
import net.sf.jsqlparser.statement.show.ShowCreateStatement;
106107
import net.sf.jsqlparser.statement.show.ShowIndexStatement;
107108
import net.sf.jsqlparser.statement.show.ShowTableStatusStatement;
@@ -483,6 +484,14 @@ default void visit(ShowCreateStatement showCreate) {
483484
this.visit(showCreate, null);
484485
}
485486

487+
default <S> T visit(MySqlShowStatement mySqlShow, S context) {
488+
return null;
489+
}
490+
491+
default void visit(MySqlShowStatement mySqlShow) {
492+
this.visit(mySqlShow, null);
493+
}
494+
486495
<S> T visit(Merge merge, S context);
487496

488497
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
@@ -117,6 +117,7 @@
117117
import net.sf.jsqlparser.statement.select.SelectVisitor;
118118
import net.sf.jsqlparser.statement.select.SelectVisitorAdapter;
119119
import net.sf.jsqlparser.statement.select.WithItem;
120+
import net.sf.jsqlparser.statement.show.MySqlShowStatement;
120121
import net.sf.jsqlparser.statement.show.ShowCreateStatement;
121122
import net.sf.jsqlparser.statement.show.ShowIndexStatement;
122123
import net.sf.jsqlparser.statement.show.ShowTableStatusStatement;
@@ -691,6 +692,11 @@ public <S> T visit(ShowCreateStatement showCreate, S context) {
691692
return null;
692693
}
693694

695+
@Override
696+
public <S> T visit(MySqlShowStatement mySqlShow, S context) {
697+
return null;
698+
}
699+
694700
@Override
695701
public <S> T visit(DeclareStatement declareStatement, S context) {
696702
return null;

0 commit comments

Comments
 (0)