Skip to content

Parse MySQL SHOW FULL COLUMNS, SHOW TABLE STATUS and SHOW CREATE statements - #2824

Open
minleejae wants to merge 2 commits into
JSQLParser:masterfrom
minleejae:feat/mysql-show-statements-20261014
Open

minleejae wants to merge 2 commits into
JSQLParser:masterfrom
minleejae:feat/mysql-show-statements-20261014

Conversation

@minleejae

@minleejae minleejae commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Builds on #2806, which shares MySQL account name parsing (MySqlAccountName()); SHOW CREATE USER uses that rule.

Purpose

Parse the MySQL statements that tools use to read table and column comments and object definitions. MySQL 8.4 accepts all of them, but only the plain SHOW COLUMNS FROM t is typed today:

  • SHOW FULL COLUMNS FROM t, SHOW FULL FIELDS FROM t, SHOW COLUMNS IN t become UnsupportedStatement.
  • SHOW COLUMNS FROM t FROM db, SHOW COLUMNS FROM t LIKE 'p', ... WHERE expr and SHOW COLUMNS FROM db.t fail to parse.
  • SHOW TABLE STATUS [{FROM | IN} db] [LIKE 'p' | WHERE expr] becomes UnsupportedStatement.
  • SHOW CREATE {TABLE | VIEW | PROCEDURE | FUNCTION | TRIGGER | EVENT} name, SHOW CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db and SHOW CREATE USER account become UnsupportedStatement.

Current design (As-is)

  • Show() commits to ShowColumns() after two tokens (COLUMNS FROM). ShowColumns() reads one RelObjectName(), so any further clause is a parse error.
  • ShowColumnsStatement holds only a String tableName. Its deparser always writes SHOW COLUMNS FROM.
  • Every other SHOW form is captured as raw tokens: ShowStatement for one token, otherwise UnsupportedStatement.
  • TablesNamesFinder throws UnsupportedOperationException for ShowColumnsStatement.

Target design (To-be)

  • ShowColumnsStatement (extended, compatible):
    • isExtended(), isFull(), isFieldsKeyword().
    • getTableSelectionMode() and getDbSelectionMode() record the FROM/IN spelling, reusing ShowTablesStatement.SelectionMode.
    • getTable() is a Table; getDbName(), getLikeExpression() and getWhereCondition() hold the optional clauses.
    • getTableName(), setTableName(String), withTableName and both constructors remain, derived from the Table.
  • ShowTableStatusStatement (new, statement.show): getSelectionMode(), getDbName(), getLikeExpression() and getWhereCondition(), like ShowTablesStatement.
  • ShowCreateStatement (new, statement.show):
    • getObjectType(): TABLE, VIEW, PROCEDURE, FUNCTION, TRIGGER, EVENT, DATABASE or USER.
    • The first six use getName(), a qualified Table, as the other routine, trigger and event statements do.
    • DATABASE uses getDatabaseName(), isSchemaKeyword() and isIfNotExists().
    • USER uses getAccount(), a UserAccount read with the shared MySqlAccountName() of Share MySQL account names across CREATE USER and DEFINER #2806, so every account spelling of CREATE USER works (app@'%', 'app'@localhost, `app`@`%`, "app"@"%"); isCurrentUser() and isCurrentUserParentheses() cover CURRENT_USER and CURRENT_USER().
  • Grammar:
    • Show() chooses a typed form only when it spans the whole statement, up to ;, the input end, ELSE/END, or the next statement (the new lookahead-only ShowStatementEnd()).
    • Other dialects' SHOW variants therefore still become UnsupportedStatement, for example Snowflake SHOW COLUMNS IN SCHEMA s and ClickHouse SHOW CREATE TABLE t FORMAT f. SHOW INDEX, SHOW TABLES and single-word SHOW x are unchanged.
    • STATUS is matched with ContextualKeyword; no new tokens or reserved words. No grammar choice conflicts.
  • Wiring:
    • toString and StatementDeParser; ShowColumnsStatementDeParser renders the full statement.
    • StatementVisitor default methods and StatementVisitorAdapter.
    • TablesNamesFinder: reports the table of SHOW COLUMNS (qualified by its FROM db clause) and of SHOW CREATE TABLE/VIEW; SHOW TABLE STATUS and the other SHOW CREATE kinds name no table.
    • Validation: new Feature.showTableStatus and Feature.showCreate, enabled in the MySQL and MariaDB capabilities. Metadata validation looks up the SHOW COLUMNS table in its FROM db database and the SHOW CREATE table, view, procedure or database.
    • StatementFeatureVisitor: metadata read, RETURNS_RESULT_SET.
    • Usage guide section, README and index rows.
  • Behaviour changes:
    • TablesNamesFinder now returns the table of SHOW COLUMNS instead of throwing.
    • show create table t is a ShowCreateStatement; its SQL is unchanged.

Validation

  • 72 new tests (ShowColumnsStatementTest, ShowTableStatusStatementTest, ShowCreateStatementTest and three validator tests):
    • every form parsed, deparsed with toString and StatementDeParser, and reparsed, without a dialect and with Dialect.MYSQL and Dialect.MARIADB;
    • AST fields, the legacy ShowColumnsStatement accessors, builders;
    • forms that stay UnsupportedStatement, statement boundaries (;, IF ... ELSE);
    • table names, statement features, feature validation and metadata lookups.
  • Java 17 offline Gradle spotlessApply check on top of Share MySQL account names across CREATE USER and DEFINER #2806: 10,472 tests, 10,447 passed, 25 skipped, zero failures/errors. The grammar choice conflict check passes.
  • Compared with master (bdf8ac31) on the DDL/DCL survey corpora (MySQL 8.4 and PostgreSQL 18, with and without a dialect): no regressions and no status changes.
  • On the MySQL comment-reading corpus with Dialect.MYSQL, the 8 SHOW FULL COLUMNS/FIELDS, SHOW TABLE STATUS and SHOW CREATE TABLE/PROCEDURE statements change from UnsupportedStatement to typed statements with identical SQL. SHOW COLUMNS FROM t and SHOW INDEX FROM t are unchanged.
  • MySQL 8.4 and PostgreSQL 18.3: every corpus statement this branch parses ran as written on one server and as rendered by toString() on a second, identical server, in the same order. All 205 MySQL and 327 PostgreSQL statements give the same result (success, or the same error).
  • The same check on the comment corpora (statements that create, alter and read MySQL and PostgreSQL comments): all 52 MySQL and 65 PostgreSQL statements this branch parses give the same results. Afterwards, every stored comment (MySQL table, column, index, partition, routine and event comments; PostgreSQL pg_description) is byte-identical on both servers.
  • An extra set of MySQL comment cases continued on the same servers: the 23 statements this branch parses give the same results. Then each of the 11 SHOW statements of the MySQL comment corpora ran as written and as rendered on the same server, and the outputs are byte-identical: SHOW FULL COLUMNS/FIELDS (with FROM db and LIKE), SHOW COLUMNS, SHOW TABLE STATUS (with LIKE and WHERE), SHOW CREATE TABLE/PROCEDURE and SHOW INDEX.

Integration validation

Applied this PR together with the other comment PRs (#2820, #2821, #2822, #2823), the DDL/DCL PRs #2806–#2819 and #2778 on master (bdf8ac31), with the stacked PRs on top of their bases (#2814 → #2821, #2816 → #2822, #2806 → #2824 and #2811 → #2812 → #2823).

  • Each branch merges cleanly into master. Between the branches, conflicts are limited to adjacent additions (README/index rows, usage sections, imports, test methods, visitor and feature lists, an enum line and an alias guard).
  • The integrated build passes Java 17 offline Gradle spotlessApply check: 11,877 tests, 11,852 passed, 25 skipped, zero failures/errors. The grammar choice conflict check passes.
  • On the corpus of 635 MySQL 8.4 and PostgreSQL 18 DDL/DCL statements, the integrated build parses 265 of 271 MySQL statements (master: 206) and 363 of 364 PostgreSQL statements (master: 328), the same as Share MySQL account names across CREATE USER and DEFINER #2806–Render single spaces in ALTER visibility, FORCE and row level security actions #2819 together. There are no regressions.
  • On the comment corpora and an extra set of comment edge cases, the integrated build returns a typed statement for all 80 MySQL statements (master: 67) and for 118 of 119 PostgreSQL statements (master: 76). The exception is a CREATE AGGREGATE setup statement. Every table, column, index, partition, routine, event, user and COMMENT ON comment literal is a StringValue, except COMMENT = _utf8mb4'x', which MySQL rejects.
  • On paired MySQL 8.4 and PostgreSQL 18.3 servers, all 263 MySQL and 362 PostgreSQL DDL/DCL statements and all 56 MySQL and 90 PostgreSQL comment statements rendered by the integrated build give the same results as the originals. The stored comments are identical on both servers.

CREATE USER and DEFINER read user@host with their own copies of the
same rule. Neither accepted app@'%' or 'app'@localhost, because the
lexer reads app@ and @localhost as single tokens. Without a dialect a
double-quoted part also lost its quotes, so CREATE USER "app"@"%"
rendered as app@%.

Add one MySqlAccountName() production that splits those tokens, keep
the quote character of double-quoted and backquoted parts apart from
their value, and use it for CREATE USER and DEFINER.

Signed-off-by: minleejae <mmj9808@gmail.com>
…E statements

MySQL tools read table and column definitions and comments with
SHOW FULL COLUMNS, SHOW TABLE STATUS and SHOW CREATE. Only plain
SHOW COLUMNS FROM t was typed; the other forms became
UnsupportedStatement, and LIKE, WHERE or a qualified table after
SHOW COLUMNS failed to parse.

Extend ShowColumnsStatement with EXTENDED, FULL, the FIELDS spelling,
FROM/IN, a Table name, the trailing database and LIKE/WHERE, keeping
getTableName() and setTableName(String). Add ShowTableStatusStatement
and ShowCreateStatement for TABLE, VIEW, PROCEDURE, FUNCTION, TRIGGER,
EVENT, DATABASE/SCHEMA [IF NOT EXISTS] and USER, whose account reuses
MySqlAccountNamePart and accepts CURRENT_USER[()].

A typed SHOW form is chosen only when it covers the whole statement,
so other dialects' SHOW variants still fall back to
UnsupportedStatement. Wire the statements into the deparser, table
finder, validation (showTableStatus, showCreate) and feature analysis.

Signed-off-by: minleejae <mmj9808@gmail.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant