Skip to content

Parse MySQL and PostgreSQL CREATE and ALTER TABLESPACE - #2817

Open
minleejae wants to merge 1 commit into
JSQLParser:masterfrom
minleejae:feat/tablespace-ddl-20261014
Open

minleejae wants to merge 1 commit into
JSQLParser:masterfrom
minleejae:feat/tablespace-ddl-20261014

Conversation

@minleejae

@minleejae minleejae commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Purpose

Parse MySQL and PostgreSQL CREATE TABLESPACE and ALTER TABLESPACE. Today CREATE TABLESPACE fails in every configuration, for example CREATE TABLESPACE ts1 ADD DATAFILE 'ts1.ibd' ENGINE=InnoDB and CREATE TABLESPACE fast OWNER u1 LOCATION '/ssd1/pg'. ALTER TABLESPACE fast RENAME TO faster parses only as an UnsupportedStatement token list. Tools that read schema scripts therefore cannot see a tablespace's name, data file, location or options.

Current design (As-is)

  • Create() has no tablespace alternative. CREATE TABLESPACE reaches CreateIndex() and fails there, at ADD (MySQL) or at the end of the statement (PostgreSQL).
  • Alter() captures every ALTER TABLESPACE statement as an UnsupportedStatement. Only the PostgreSQL bulk move ALTER TABLE|INDEX|MATERIALIZED VIEW ALL IN TABLESPACE … SET TABLESPACE … is modeled, as AlterTablespaceMove.
  • Option models for these clauses already exist:
    • MySQL ENGINE, ENCRYPTION, AUTOEXTEND_SIZE and ENGINE_ATTRIBUTE are TableOption kinds, parsed by the shared CREATE/ALTER TABLE option productions.
    • PostgreSQL WITH (…), SET (…) and RESET (…) lists are IndexOption lists or names, as in CREATE TABLE … WITH and ALTER INDEX … SET/RESET.

Target design (To-be)

  • Add CreateTablespace. It records:
    • the name, and the MySQL UNDO keyword;
    • PostgreSQL: the owner, the LOCATION (StringValue) and the WITH parameters (List<IndexOption>);
    • MySQL: the ADD DATAFILE file (StringValue) and the options (List<TableOption>) in source order.
  • Add AlterTablespace, with an explicit Action:
    • RENAME (RENAME TO);
    • PostgreSQL OWNER (OWNER TO), SET_PARAMETERS (SET (…)) and RESET_PARAMETERS (RESET (…));
    • MySQL SET_STATE (ALTER UNDO TABLESPACE … SET ACTIVE|INACTIVE) and OPTIONS.
  • Reuse the existing option models instead of adding parallel ones:
    • MySQL options go through the existing table option productions and become TableOption values. The only new kind is TableOption.Kind.FILE_BLOCK_SIZE, which only tablespaces use.
    • PostgreSQL parameters reuse PostgreSqlIndexOptions(); RESET keeps names, as ALTER INDEX … RESET does.
  • Accept only what the server grammars define (MySQL 8.4 sql_yacc.yy, PostgreSQL 18 gram.y):
    • CREATE UNDO TABLESPACE requires ADD DATAFILE, and undo tablespaces accept only ENGINE. ALTER rejects FILE_BLOCK_SIZE.
    • MySQL options may be separated by commas; the commas are not kept.
    • PostgreSQL requires LOCATION. A statement cannot mix PostgreSQL and MySQL clauses.
    • The clause words (UNDO, DATAFILE, LOCATION, OWNER, INACTIVE, FILE_BLOCK_SIZE) are matched in context. No new keywords are reserved.
  • Choose the statement as follows:
    • CREATE [UNDO] TABLESPACE always parses to CreateTablespace. It failed before, so invalid forms still raise a parse error.
    • ALTER [UNDO] TABLESPACE becomes AlterTablespace only when its grammar matches the whole statement. A known option that the clause does not define, such as FILE_BLOCK_SIZE after ALTER, raises a parse error.
    • Other ALTER TABLESPACE forms still parse to UnsupportedStatement, as before. These include Oracle ADD DATAFILE … SIZE, OFFLINE and ENCRYPTION ONLINE …, and NDB ADD DATAFILE and WAIT.
    • AlterTablespaceMove is unchanged.
  • Out of scope:
    • the NDB-only clauses (USE LOGFILE GROUP, INITIAL_SIZE, MAX_SIZE, EXTENT_SIZE, NODEGROUP, WAIT, COMMENT) and the STORAGE ENGINE spelling;
    • DROP TABLESPACE.
  • Wire both statements into:
    • the StatementVisitor defaults, StatementVisitorAdapter, StatementDeParser and TablesNamesFinder (no tables; parameter values are visited);
    • validation, through the new Feature.createTablespace and Feature.alterTablespace. The MySQL 8.0 and PostgreSQL capabilities and FeaturesAllowed.CREATE/ALTER enable them;
    • statement feature analysis: MODIFIES_SCHEMA.
  • Document the API in the usage guide and list the statements in README and index.

Validation

  • 46 new tests cover:
    • every MySQL and PostgreSQL form: parse, deparse and reparse with the dialect, plus the AST fields;
    • option order, optional commas, and the equality of tablespace and CREATE TABLE option tokens;
    • rejected forms, including UNDO restrictions, FILE_BLOCK_SIZE after ALTER, mixed PostgreSQL/MySQL clauses and PostgreSQL values without =;
    • Oracle and NDB ALTER TABLESPACE forms that stay UnsupportedStatement, also inside scripts;
    • unchanged AlterTablespaceMove, and clause words used as identifiers or tablespace names;
    • builder deparsing, expression visiting, script boundaries, statement features and validation capabilities.
  • Java 17 offline Gradle spotlessApply check: 10,412 tests, 10,387 passed, 25 skipped, zero failures/errors. The grammar choice conflict check passes.
  • Compared with master (bdf8ac31) on a corpus of 635 MySQL 8.4 and PostgreSQL 18 DDL/DCL statements, each accepted by the server, plus variants:
    • The six CREATE/ALTER TABLESPACE statements (two MySQL, four PostgreSQL) now parse to the new statements; four of them also without a dialect.
    • No case regressed, and no other case changed.
  • 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 207 MySQL and 329 PostgreSQL statements give the same result (success, or the same error).

Integration validation

Applied #2806–#2819 together on master (bdf8ac31), with the stacked PRs on top of their bases (#2806 → #2807 → #2808, #2806 → #2809 → #2810 and #2811 → #2812).

  • Each branch merges cleanly into master. Between the branches, conflicts are limited to adjacent additions (README/index rows, usage sections, imports, visitor and feature lists, one enum line and one alias guard).
  • The integrated build passes Java 17 offline Gradle spotlessApply check: 11,494 tests, 11,469 passed, 25 skipped, zero failures/errors. The grammar choice conflict check passes.
  • On a corpus of 635 MySQL 8.4 and PostgreSQL 18 DDL/DCL statements, each accepted by the server, the integrated build parses 265 of 271 MySQL statements (master: 206) and 363 of 364 PostgreSQL statements (master: 328). Every MySQL 8.4 non-reserved word and PostgreSQL 18 unreserved or column-name keyword parses as a column and table name.
  • On paired MySQL 8.4 and PostgreSQL 18.3 servers, all 263 MySQL and 362 PostgreSQL statements rendered by the integrated build give the same results as the originals.

Add CreateTablespace and AlterTablespace. MySQL options reuse the
TableOption models (plus FILE_BLOCK_SIZE) and PostgreSQL parameters reuse
the storage-parameter lists. CREATE UNDO requires ADD DATAFILE, undo
tablespaces accept only ENGINE, and ALTER rejects FILE_BLOCK_SIZE.

ALTER TABLESPACE forms outside this grammar, such as Oracle or NDB data
file clauses, still parse as UnsupportedStatement. ALTER TABLE ALL IN
TABLESPACE remains AlterTablespaceMove.

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