Repository navigation
feat: parse MySQL 8.4 SHOW statements for variables, status, grants, logs and other server metadata - #2916
Open
minleejae wants to merge 1 commit into
Open
feat: parse MySQL 8.4 SHOW statements for variables, status, grants, logs and other server metadata#2916minleejae wants to merge 1 commit into
minleejae wants to merge 1 commit into
Conversation
…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>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose
Parse the MySQL 8.4
SHOWstatements that still came back asUnsupportedStatement(or as a bareShowStatementname), following the server grammar (sql_yacc.yy,show_*_stmt):SHOW [GLOBAL | SESSION | LOCAL] VARIABLESandSTATUS,SHOW [FULL] PROCESSLIST,SHOW DATABASES,CHARACTER SET,COLLATION,[FULL] TRIGGERS,EVENTS,OPEN TABLES,PROCEDURE/FUNCTION STATUSandCODE,SHOW GRANTS [FOR account [USING role, …]],SHOW WARNINGS/ERRORSwithLIMITorCOUNT(*),SHOW PROFILE,SHOW ENGINE name {STATUS | MUTEX | LOGS},ENGINES,PLUGINS,PRIVILEGES,PROFILES,SHOW BINARY LOG STATUS,BINARY LOGS,BINLOG EVENTS,RELAYLOG EVENTS,REPLICA STATUS,REPLICAS,SHOW [EXTENDED] {INDEX | INDEXES | KEYS} {FROM | IN} t [{FROM | IN} db] [WHERE expr].Current design (As-is)
Show()typesSHOW TABLES,SHOW INDEX FROM t, and theSHOW [FULL] COLUMNS,SHOW TABLE STATUSandSHOW CREATEforms of Parse MySQL SHOW FULL COLUMNS, SHOW TABLE STATUS and SHOW CREATE statements #2824. Every otherSHOWgoes tocaptureRest(): one word becomesShowStatement("DATABASES"), more words anUnsupportedStatement. SoSHOW GLOBAL VARIABLES LIKE 'a%',SHOW GRANTS FOR 'u'@'h',SHOW WARNINGS LIMIT 5orSHOW ENGINE INNODB STATUScarry no structure.ShowIndexStatementholds a table name string and readsINDEX FROM nameonly:SHOW INDEX FROM t FROM db,SHOW KEYS IN torSHOW EXTENDED INDEX FROM t WHERE …fail or are unsupported, andTablesNamesFinderthrows for it.{FROM | IN} dbclause and theLIKE | WHEREfilter are written out separately inShowTables(),ShowColumns()andShowTableStatus(), with four fields per class.WHEREexpression (the rest is read byprattExpressionRest()), soSHOW COLUMNS FROM t WHERE a = 1 AND b = 2becomes anUnsupportedStatement.LIKEpattern is any simple expression in every dialect, although MySQL takes a string literal only (SHOW TABLES LIKE ais a syntax error there).Target design (To-be)
Shared clauses
ShowDbSelection({FROM | IN} db) andShowFilter(LIKE 'pattern' | WHERE expr, aKindand one expression) are value types with one production each, used bySHOW TABLES,COLUMNS,TABLE STATUS,INDEXand the new statement.ShowTablesStatement,ShowColumnsStatementandShowTableStatusStatementhold them as their single state;getSelectionMode()/getDbSelectionMode(),getDbName(),getLikeExpression(),getWhereCondition()and their setters remain and read and write that state. A statement holds one filter, sosetWhereConditionreplaces aLIKEfilter (the classes used to keep both fields and render one or both).Dialect.MYSQLandDialect.MARIADBtheLIKEpattern is a string literal ('…'or"…", aStringValue), as in the server; a statement with another pattern is left to the catch-all. Without a dialect it stays any simple expression. This is a behaviour change forSHOW TABLES/COLUMNS/TABLE STATUS … LIKE exprin those two dialects, for input MySQL rejects.WHEREfilter, so a condition withAND/ORis read by the typed statements (also those of Parse MySQL SHOW FULL COLUMNS, SHOW TABLE STATUS and SHOW CREATE statements #2824); text after the condition that the expression does not take is a parse error, as in MySQL.StatementDeParserprints these statements throughappendTo(builder, printer), shared withtoString(), so filter and limit expressions go through theExpressionDeParser.ShowIndexStatementShowColumnsStatementin Parse MySQL SHOW FULL COLUMNS, SHOW TABLE STATUS and SHOW CREATE statements #2824:isExtended(),getKeyword()(INDEX,INDEXES,KEYS),getTableSelectionMode(),getTable()(aTable),getDbSelection()andgetWhereCondition(). TheStringconstructor,getTableName()andsetTableName(String)remain and derive from the table.TablesNamesFinderand the validator report the table, qualified by the trailingFROM db.MySqlShowStatementOne statement for the other forms instead of a class per keyword.
Kindnames the statement and lists theParts it allows;getKeyword()keeps the spelling (SCHEMAS,CHARSET,CHAR SET,STORAGE ENGINES).VARIABLES,STATUSScope(GLOBAL,SESSION,LOCAL), filterPROCESSLISTFULLDATABASES,CHARACTER_SET,COLLATION,PROCEDURE_STATUS,FUNCTION_STATUSTRIGGERS(withFULL),EVENTS,OPEN_TABLESPROCEDURE_CODE,FUNCTION_CODEnameordb.name)ENGINEALL),EngineInfo(STATUS,MUTEX,LOGS)GRANTSUSINGroles (UserAccount, read byMySqlAccountName()likeCREATE USER)WARNINGS,ERRORSCOUNT(*)or limitBINLOG_EVENTS,RELAYLOG_EVENTSRELAYLOGREPLICA_STATUSPROFILEProfileTypelist,FOR QUERY n, limitENGINES,PLUGINS,PRIVILEGES,PROFILES,BINARY_LOGS,BINARY_LOG_STATUS,REPLICASValues follow the server grammar: a limit is
LIMIT [offset,] n(Limit) orLIMIT n OFFSET offset(LimitandOffset, as in a query) with unsigned integers, names or?; log names and channels are strings; a log position is an unsigned number;COUNT(has no space, as the MySQL lexer requires.Setting a part the kind does not allow throws
IllegalArgumentException, andsetKinddrops such parts.Dialects:
Dialect.MYSQLandDialect.MARIADBread every form, including the one-word statements (SHOW DATABASESis now aMySqlShowStatementthere instead of aShowStatement).ShowStatementas before.SHOW MASTER STATUS,SHOW MASTER LOGS,SHOW SLAVE STATUSandSHOW SLAVE HOSTS, which MySQL 8.4 removed, are read withDialect.MARIADBand without a dialect, not withDialect.MYSQL.SHOW name,SHOW TIME ZONE,SHOW TRANSACTION ISOLATION LEVELandSHOW SESSION AUTHORIZATIONstayShowStatement, and other forms stayUnsupportedStatement.A
SHOWform that MySQL rejects (SHOW FULL EVENTS,SHOW WARNINGS LIKE 'a',SHOW BINLOG EVENTS FROM -1,SHOW REPLICA STATUS FOR CHANNEL c) keeps the catch-all result,UnsupportedStatement.No new token and no reserved word:
VARIABLES,STATUS,PROCESSLIST,GRANTS,WARNINGS,BINLOG,PROFILEand the others stay identifiers, matched in theSHOWproduction only.Wired into
StatementVisitor(default method),StatementVisitorAdapter,StatementDeParser,TablesNamesFinder(names no table),StatementFeatureVisitor(RETURNS_RESULT_SET) andStatementValidatorwith the new featuremySqlShow, enabled for MySQL and MariaDB. README,index.rstandusage.rstdescribe the statements.Not included:
SHOW PARSE_TREE(debug builds only; MySQL 8.4.11 reports a syntax error) and account names thatMySqlAccountName()does not read yet (u@h.example.comwithout quotes).Validation
New tests:
MySqlShowStatementTest(295 cases) andShowClausesTest(11 cases), more cases inShowIndexStatementTest,ShowIndexStatementValidatorTestandMySqlShowStatementValidatorTest, and entries inASTNodeCoverageTest. They cover each form withDialect.MYSQL,Dialect.MARIADBand without a dialect,toString, the deparser, reparse, AST fields and node spans, forms MySQL rejects, readings kept in other dialects, statement boundaries in scripts andIFblocks, visitors,TablesNamesFinderand validation features../gradlew spotlessApply cleanTest check jaron Java 17: 13,677 tests, 0 failures, 25 skipped;checkGrammarAmbiguity, Checkstyle, PMD, SpotBugs and JaCoCo pass.Compared with
master(e27929f76) on the MySQL and PostgreSQL DDL/DCL and non-DDL statement corpora (parsed with the dialect and without): no regression and no changed result. The 26 MySQLSHOWstatements of the non-DDL corpus that wereUnsupportedStatement, a bareShowStatementor a parse error (SHOW EXTENDED INDEX FROM t FROM db WHERE …) are now typed withDialect.MYSQL(21 of them without a dialect, where one-word statements stayShowStatement).MySQL 8.4.11: the 146 statements whose syntax the server accepts are all typed with
Dialect.MYSQL(131MySqlShowStatement, 12ShowIndexStatement, 2ShowColumnsStatement, 1ShowTableStatusStatement); some stop only at execution, for example with an unknown account or log file. Of the 125 statements the server rejects, 121 keep theUnsupportedStatementof the catch-all and 4 are parse errors (text after aWHEREcondition, aLIKEpattern that is not a string inSHOW TABLES). Two statements differ:SHOW ERRORS LIMIT ? OFFSET ?andSHOW BINLOG EVENTS LIMIT ?are typed, becauselimit_optionincludes the parameter marker, although the server takes?only in a prepared statement.AI assistance: prepared with Claude Code.