Skip to content

feat: parse MySQL spatial reference system statements and ALTER INSTANCE - #2911

Open
minleejae wants to merge 1 commit into
JSQLParser:masterfrom
minleejae:feat/mysql-srs-alter-instance-20261111
Open

minleejae wants to merge 1 commit into
JSQLParser:masterfrom
minleejae:feat/mysql-srs-alter-instance-20261111

Conversation

@minleejae

@minleejae minleejae commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

Purpose

Parse the MySQL statements for spatial reference systems and for the server instance into structured statements, following the MySQL 8.4 grammar:

CREATE SPATIAL REFERENCE SYSTEM 4120 NAME 'Greek' ORGANIZATION 'EPSG' IDENTIFIED BY 4120
    DEFINITION 'GEOGCS["Greek"]' DESCRIPTION 'd';
CREATE OR REPLACE SPATIAL REFERENCE SYSTEM 4120 NAME 'Greek' DEFINITION 'x';
CREATE SPATIAL REFERENCE SYSTEM IF NOT EXISTS 0x1018 DEFINITION 'x' NAME 'Greek';
DROP SPATIAL REFERENCE SYSTEM IF EXISTS 4120;
ALTER INSTANCE ROTATE INNODB MASTER KEY;
ALTER INSTANCE ROTATE BINLOG MASTER KEY;
ALTER INSTANCE RELOAD TLS FOR CHANNEL mysql_admin NO ROLLBACK ON ERROR;
ALTER INSTANCE RELOAD KEYRING;
ALTER INSTANCE DISABLE INNODB REDO_LOG;

Current design (As-is)

  • CREATE SPATIAL REFERENCE SYSTEM … and ALTER INSTANCE … reach the fallbacks of Create() and Alter() and come back as UnsupportedStatement, whatever follows the first words.
  • DROP SPATIAL REFERENCE SYSTEM 4120 fails: Drop() has no object type that starts with SPATIAL, and a DROP target is a name, not a number.

Target design (To-be)

Spatial reference systems

  • CreateSpatialReferenceSystem keeps isOrReplace(), isIfNotExists() (they exclude each other, as in the grammar), the SRID and the attributes in source order.
    • The SRID and the number after IDENTIFIED BY are the literals as written: a LongValue, or a HexValue for 0x… and X'…' (MySQL's real_ulonglong_num).
    • Each attribute is a SpatialReferenceSystemAttribute with a Kind (NAME, DEFINITION, ORGANIZATION, DESCRIPTION), its StringValue and, for an organization, the identifier. getName(), getDefinition(), getOrganization(), getOrganizationId() and getDescription() derive from that list.
    • The parser accepts what the grammar accepts: attributes in any order and any number, plain strings in single or double quotes. A repeated attribute, a missing NAME or DEFINITION and an SRID above 4294967295 are errors the server reports when it runs the statement (errors 3709, 3708, 1690), not syntax errors, so they parse.
  • DROP SPATIAL REFERENCE SYSTEM [IF EXISTS] srid builds on the DROP object types of several words: Drop gets the object type SPATIAL_REFERENCE_SYSTEM, and its name is the SRID as written. Nothing may follow the SRID.

ALTER INSTANCE

  • AlterInstance has an Action (ENABLE_INNODB_REDO_LOG, DISABLE_INNODB_REDO_LOG, ROTATE_INNODB_MASTER_KEY, ROTATE_BINLOG_MASTER_KEY, RELOAD_TLS, RELOAD_KEYRING) and, for RELOAD TLS, getChannel() and isNoRollbackOnError().
  • MySQL reads INNODB, BINLOG and REDO_LOG as identifiers that it compares with these names (the engine of ROTATE also as a string), so ROTATE `innodb` MASTER KEY and ROTATE 'BINLOG' MASTER KEY parse; the statement prints the plain words. The channel is any identifier, kept as written: the grammar does not restrict it to mysql_main and mysql_admin.
  • Alter() dispatches the statement before the other ALTER forms, which are unchanged.

Dialects and wiring

  • No new token and no reserved word: REFERENCE, INSTANCE, ROTATE, RELOAD, TLS, CHANNEL, KEYRING, MASTER, INNODB, BINLOG, REDO_LOG, DEFINITION, ORGANIZATION and DESCRIPTION stay identifiers.
  • The statements are read with Dialect.MYSQL and without a dialect; MariaDB does not have them.
    • With Dialect.MYSQL a CREATE SPATIAL … statement that is neither this one nor CREATE SPATIAL INDEX, and ALTER INSTANCE with an unknown action, are errors, as on the server.
    • Without a dialect only SPATIAL REFERENCE SYSTEM and a known ALTER INSTANCE action select the new statements; other text keeps producing UnsupportedStatement.
    • MariaDB, PostgreSQL and the other dialects are unchanged.
  • Wired into StatementVisitor (default methods), StatementVisitorAdapter, StatementDeParser, TablesNamesFinder, StatementFeatureVisitor (MODIFIES_SCHEMA for the SRS statements, MODIFIES_SESSION for ALTER INSTANCE, a server operation like ALTER SYSTEM) and StatementValidator with the new features createSpatialReferenceSystem and alterInstance, which the MySQL capabilities enable. README, index.rst and usage.rst describe the statements.

Validation

  • New tests: SpatialReferenceSystemTest (102 cases), AlterInstanceTest (77 cases) and MySqlInstanceStatementsValidatorTest (3 cases), plus entries in ASTNodeCoverageTest and StatementValidatorTest. They cover each form with and without the dialect, toString, the deparser, reparse, AST fields and node spans, rejected forms, readings kept in other dialects, statement boundaries in scripts, visitors, TablesNamesFinder and validation features.

  • ./gradlew spotlessApply cleanTest check jar on Java 17: 13,521 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): the three statements move from UnsupportedStatement (CREATE, ALTER INSTANCE) and a parse failure (DROP) to the new models, with the MySQL dialect and without; no regression and no other changed result.

  • MySQL 8.4.11 accepts the syntax of all 66 statements the tests accept for the MySQL dialect; master rejects the 8 DROP SPATIAL REFERENCE SYSTEM forms and returns the others as UnsupportedStatement. Some fail only when run, for example a repeated or missing attribute (3709, 3708), an SRID above 4294967295 or an unknown TLS channel. MySQL reports a syntax error (1064) for all 108 server-checked statements the tests reject, including OR REPLACE with IF NOT EXISTS, a quoted, signed or decimal SRID, 0X… and X'1', an N'…' or introducer string, ORGANIZATION without IDENTIFIED BY, a list of SRIDs, CASCADE after DROP, a quoted TLS channel and any action outside the grammar. Two further statements that MySQL rejects are not rejected here: CREATE TEMPORARY SPATIAL REFERENCE SYSTEM … and ALTER INSTANCES RELOAD TLS still come back as UnsupportedStatement through the generic CREATE/ALTER fallback, as on master.

AI assistance: prepared with Claude Code.

CREATE SPATIAL REFERENCE SYSTEM and ALTER INSTANCE came back as
UnsupportedStatement, and DROP SPATIAL REFERENCE SYSTEM failed to parse.

CREATE [OR REPLACE] SPATIAL REFERENCE SYSTEM [IF NOT EXISTS] is the new
CreateSpatialReferenceSystem: the SRID as written and the NAME,
DEFINITION, ORGANIZATION ... IDENTIFIED BY and DESCRIPTION attributes
in source order, with typed getters derived from that list. As in
MySQL's grammar the attributes come in any order and number; the server
reports a repeated or missing attribute when it runs the statement.
DROP SPATIAL REFERENCE SYSTEM [IF EXISTS] srid is a Drop with the new
object type SPATIAL_REFERENCE_SYSTEM, named by its SRID.

ALTER INSTANCE is the new AlterInstance with an Action for the redo
log, master key, TLS and keyring forms, and the channel and NO ROLLBACK
ON ERROR of RELOAD TLS.

The statements are read with the MySQL dialect and without a dialect,
add no token, and are wired into the deparser, visitors, table finder,
feature analysis and validation, with the new features
createSpatialReferenceSystem and alterInstance.

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