You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit d60cbbd
Browse filesBrowse the repository at this point in the historyBrowse files
test: close tracked MySQL corpus gaps with native DDL checks
Promote the five tracked JSON_TABLE, CREATE TABLE, ALTER TABLE, CREATE
PROCEDURE and optimizer-hint witnesses to strict complete-AST, exact
emission and stable-reparse checks. Add 45 positive and malformed witnesses
with hand-reduced syntax and exact grammar provenance in the pinned official
MySQL 8.4.8 and 9.7.2 sources. The curated baseline is now 385 cases:
192 CHECKED, 193 REJECTED and zero remaining known_gap records. This is a
corpus result rather than a dialect-wide grammar coverage percentage.
Extend the optional isolated native oracle with an explicit DDL action.
Create a unique owned schema for each DDL/procedure witness, install only
its specified fixture, send procedure bodies using a collision-free mysql
client delimiter and clean up on both success and failure. Never drop a
schema whose creation failed. Retain exact client input and cleanup evidence
and test schema isolation, rejection, fixture failure and ownership handling.
Document the structured AST additions and their bounded grammar, hint
metadata contract, execution restrictions and unsupported routine batch
limitations. Preserve explicit distinctions between native syntax rejection,
server semantic errors and unverified behavior.
Validation: 14 Python harness tests pass; all 385 parser expectations and
465 source anchors per pinned release match. Native 8.4.8 observes 170
accepted, 198 syntax-rejected and 17 semantic/server errors; native 9.7.2
observes 175 accepted, 188 syntax-rejected and 22 server errors. Neither
run has intended-validity mismatches or skipped cases, and all owned schemas
are removed. Separate runs of all 192 emitted positives retain their original
native state/error code on both versions. This observation is not an
execution-equivalence guarantee. Native reports and benchmarks stay outside
the committed files.
Copy file name to clipboardExpand all lines: docs/mysql-compatibility.md
+17-7Lines changed: 17 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,6 +2,16 @@
2
2
3
3
This harness tracks a small, deliberately selected set of MySQL syntax witnesses and known ParserSQL gaps. It does not measure the percentage of the MySQL dialect supported, implement mysqltest/MTR extraction, or establish query-engine execution support.
4
4
5
+
The five previously tracked witnesses—`JSON_TABLE`, `CREATE TABLE`, `ALTER TABLE`, `CREATE PROCEDURE`, and optimizer hints—now require `CHECKED` outcomes. This closes those particular parse/emission/reparse gaps; it does not establish full support for any of those MySQL feature families.
6
+
7
+
`JSON_TABLE` retains separate document, path, column-list, column, nested-path, and response nodes. Supported columns include `FOR ORDINALITY`, typed `PATH`, `EXISTS PATH`, and recursive `NESTED PATH ... COLUMNS` with a limit of 128 column-list levels. Both pinned grammars require `PATH` after `NESTED`. Paths use native text literals, including national/charset prefixes and adjacent quoted fragments. `NULL`, `ERROR`, and `DEFAULT` responses preserve `ON EMPTY` and `ON ERROR` in either native order; the reversed order is deprecated by MySQL. DEFAULT uses the native signed-literal production, including numeric, text, temporal, hex, and bit literals. A table alias is required, and an alias-column list is not accepted. The [8.4.8 JSON_TABLE productions](https://github.com/mysql/mysql-server/blob/0896fcd61dec11a0904166911a0126f59daaa1bf/sql/sql_yacc.yy#L12023) and [9.7.2 JSON_TABLE productions](https://github.com/mysql/mysql-server/blob/008e09c2834b98143a8c067d4d225c90953050cf/sql/sql_yacc.yy#L12447) define this bounded grammar coverage. JSON path validity and conversion semantics remain native semantic checks.
8
+
9
+
MySQL table DDL preserves structured definitions, constraints, options, and ALTER actions. The supported subset includes column types and attributes, generated/default expressions, common keys, CHECK and foreign-key constraints, common table options, and ADD/DROP/MODIFY/CHANGE/RENAME actions. TEMPORARY and IF NOT EXISTS are supported for CREATE TABLE. Shared native type parsing also serves JSON_TABLE columns and procedure parameters; VECTOR is a 9.7 type and is not part of the 8.4 grammar. CREATE TABLE LIKE, query-derived table definitions, partitioning, and specialized index/table options remain outside this bounded implementation. Unknown or incomplete clauses are rejected rather than retained as unvalidated tails. The corpus anchors [8.4.8 CREATE TABLE](https://github.com/mysql/mysql-server/blob/0896fcd61dec11a0904166911a0126f59daaa1bf/sql/sql_yacc.yy#L3217) and [9.7.2 CREATE TABLE](https://github.com/mysql/mysql-server/blob/008e09c2834b98143a8c067d4d225c90953050cf/sql/sql_yacc.yy#L3317), plus the ALTER and definition productions used by each witness.
10
+
11
+
`CREATE PROCEDURE` preserves typed IN/OUT/INOUT parameters, SQL-language routine characteristics, a single supported query/DML/SET statement or a BEGIN/END body, and nested blocks up to 64 levels. Statement separators inside supported bodies remain part of the procedure AST, including when parsing a batch. This grouping guarantee does not extend to unsupported or malformed routine bodies: the batch parser can stop at an inner semicolon and reports a failed batch. Local and user-variable SET assignments are supported. CREATE DEFINER, procedure IF NOT EXISTS, non-SQL languages, DECLARE, labels, conditionals, loops, cursors, handlers, and scoped/session-configuration SET forms remain unsupported. These broader native constructs are not labeled malformed merely because ParserSQL rejects them. The corpus records [8.4.8 procedure productions](https://github.com/mysql/mysql-server/blob/0896fcd61dec11a0904166911a0126f59daaa1bf/sql/sql_yacc.yy#L17938) and [9.7.2 procedure productions](https://github.com/mysql/mysql-server/blob/008e09c2834b98143a8c067d4d225c90953050cf/sql/sql_yacc.yy#L18697), including parameter, characteristic, and block productions.
12
+
13
+
Optimizer hints immediately following their supported statement keyword are retained losslessly in a dedicated comment node. This preserves their contents and position during emission; ParserSQL does not interpret or validate the hint language or promise that a native optimizer applies a hint. Unknown hint names can be accepted by MySQL with warnings. Ordinary comments are still outside this hint-preservation guarantee. These additions provide syntax/AST support: local execution and conservative parameterization reject unsupported JSON_TABLE, table DDL, procedure, and hinted-statement semantics.
14
+
5
15
ParserSQL now preserves MySQL JSON arrows, named/inherited windows, `GROUP_CONCAT` modifiers and separators, and grouping alternatives including `GROUP BY ... WITH ROLLUP` as structured ASTs. Database-qualified column names are retained. The local engine rejects these unsupported semantics rather than executing a simplified interpretation; parameterization remains conservative for JSON arrows and `GROUP_CONCAT`. Empty MySQL SELECT target lists are rejected.
6
16
7
17
MySQL JSON aggregates use structured ASTs with native argument counts: `JSON_ARRAYAGG` takes one expression and `JSON_OBJECTAGG` takes two. Each argument accepts an explicit `ALL`; `DISTINCT`, a bare star, in-call ordering, and wrong arities are rejected. Both functions preserve optional window clauses. With `IGNORE_SPACE` off, these built-in forms require an adjacent opening parenthesis; spaced or quoted names remain ordinary function calls. The 9.7.2 `JSON_ARRAYAGG` extension preserves `NULL ON NULL` and `ABSENT ON NULL`; neither clause belongs to `JSON_OBJECTAGG`. These clauses are absent from the 8.4.8 production. Native 9.7.2 accepts `NULL ON NULL` but returns unsupported-feature error 1235 for the curated `ABSENT ON NULL` witnesses outside JSON duality views. The [8.4.8 JSON aggregate productions](https://github.com/mysql/mysql-server/blob/0896fcd61dec11a0904166911a0126f59daaa1bf/sql/sql_yacc.yy#L10988) and [9.7.2 JSON aggregate productions](https://github.com/mysql/mysql-server/blob/008e09c2834b98143a8c067d4d225c90953050cf/sql/sql_yacc.yy#L11397) define this bounded coverage. These are syntax/AST guarantees; the local engine rejects the new aggregate nodes, and parameterization remains conservative.
@@ -56,13 +66,13 @@ To also verify the source provenance, add `--source84 /path/to/mysql-8.4.8` and
56
66
57
67
The strict parse gate requires status `OK`, `full_input=true`, and a non-null AST. Failure categories are `ERROR`, `PARTIAL`, `NO_AST`, and `TRAILING_INPUT`. `NO_AST` takes precedence over trailing input; the report retains the raw flags and remaining SQL so neither fact is lost. In particular, classification-only DDL must not count as structured parsing.
58
68
59
-
Complete parses have their emitted SQL reparsed through the same strict gate. The emitted text must stabilize after that reparse. Positive controls also specify exact expected SQL, including JSON `->` and `->>` operators. These checks can expose dropped or changed syntax even when the altered SQL still parses. They are bounded emission checks, not a proof of AST or execution equivalence. `CHECKED` means only that these checks passed. The optimizer-hint witness records a known `EMISSION_MISMATCH`, because dropping a hint is not faithful preservation.
69
+
Complete parses have their emitted SQL reparsed through the same strict gate. The emitted text must stabilize after that reparse. Positive controls also specify exact expected SQL, including JSON `->` and `->>` operators. These checks can expose dropped or changed syntax even when the altered SQL still parses. They are bounded emission checks, not a proof of AST or execution equivalence. `CHECKED` means only that these checks passed. Optimizer-hint witnesses require their comment text to survive emission exactly.
60
70
61
71
Malformed controls are handled separately: a complete AST is `MALFORMED_ACCEPTED`, even when emission changes. The `SELECT FROM` and malformed JSON-arrow controls require rejection. A rejection is `REJECTED`; the original record still identifies whether it was an error, incomplete input, or a missing AST.
62
72
63
73
Every fixture freezes one exact expected outcome. Known gaps do not make arbitrary failures acceptable. Both regression and unexpected improvement cause exit status 1, so a fixed gap must be reviewed and explicitly promoted in the corpus. When promoting, add an independently derived `expected_sql`, set `known_gap=false`, and require `CHECKED`. Harness/transport/source errors return 2. Exit status 0 means the expected baseline matched, including its documented known gaps.
64
74
65
-
The 340-case baseline has 166`CHECKED` witnesses and 169`REJECTED`negative controls. Its five remaining known gaps are one `TRAILING_INPUT`, three `NO_AST`, and one `EMISSION_MISMATCH`: JSON_TABLE, CREATE TABLE, ALTER TABLE, CREATE PROCEDURE, and optimizer-hint preservation. JSON aggregates, grouping alternatives, and EXPLAIN INTO now join the previously supported witnesses in passing complete parse, exact emission, and stable reparse checks. Source verification checks 363 exact source anchors per pinned release. These counts describe this corpus only.
75
+
The 385-case curated baseline has 192`CHECKED` witnesses and 193`REJECTED`malformed controls, with no remaining `known_gap` records. All five previously tracked gaps are promoted. Source verification checks 465 exact grammar anchors per pinned release. These counts describe this selected corpus only, not overall dialect coverage.
66
76
67
77
The JSON report includes all original and reparsed records, source verification counts, pinned revisions, SQL-mode metadata, and SHA-256 hashes of the corpus and probe. Counts apply only to these witnesses. The probe uses hex-line input and hex fields in its TSV response, preserving tabs, newlines and embedded NUL bytes. It emits while both the input string and parser arena are alive; Python reparses owned copies in a second probe invocation.
The client uses `--no-defaults`, the supplied socket, and `root` unless `--native-user` is specified. There is no host discovery or automatic connection. Use an isolated test server: this option explicitly creates a uniquely named `parsersql_compat_<uuid>` database, installs the small fixture in [native.py](../scripts/mysql_compat/native.py), and drops only that owned database in cleanup. The partition witnesses use a separate `pt` table with populated `p0` and `p1` range partitions; `t` retains its fulltext index for the existing search witness. The supplied user needs permission to create/drop that database and its tables. The helper requires server version 8.4.8 or 9.7.2, records the exact reported version and session SQL mode, and reapplies that mode for each query. It does not assert that the native mode equals the corpus's empty intended mode.
88
+
The client uses `--no-defaults`, the supplied socket, and `root` unless `--native-user` is specified. There is no host discovery or automatic connection. Use an isolated test server: this option explicitly creates a uniquely named `parsersql_compat_<uuid>` database, installs the small fixture in [native.py](../scripts/mysql_compat/native.py), and drops only that owned database in cleanup. Each DDL/procedure case additionally creates its own uniquely named schema, installs only its explicitly recorded `native_fixture_sql` when needed, and drops that schema after the observation. An ALTER witness therefore gets a clean table without conflicting with the shared query fixture. Cleanup also runs after statement rejection or fixture failure; a failed CREATE DATABASE never grants ownership for DROP. The partition witnesses use a separate `pt` table with populated `p0` and `p1` range partitions; `t` retains its fulltext index for the existing search witness. The supplied user needs permission to create/drop that database and its tables. The helper requires server version 8.4.8 or 9.7.2, records the exact reported version and session SQL mode, and reapplies that mode for each query. It does not assert that the native mode equals the corpus's empty intended mode.
79
89
80
-
Each curated case explicitly chooses direct query execution, `EXPLAIN` for DML (including CTE-prefixed DML), or no native action. DDL and procedures remain **NOT VERIFIED**. These are query-execution or EXPLAIN observations, not access to MySQL's raw parser. Returned row values are evidence only; they are not compared with ParserSQL execution. The helper neither executes emitted SQL nor claims semantic round-trip validation.
90
+
Each curated case explicitly chooses direct query execution, `EXPLAIN` for DML (including CTE-prefixed DML), isolated DDL/procedure creation, or no native action. The `ddl` action uses the mysql client's DELIMITER command with a marker absent from the witness, so internal procedure semicolons are sent in one statement. Per-case reports retain the schema, fixture SQL, exact client input, and cleanup result. Procedure creation is observed; procedure bodies are not called or executed by this action. These are query-execution or EXPLAIN observations, not access to MySQL's raw parser. Returned row values are evidence only; they are not compared with ParserSQL execution. The standard corpus run submits original SQL only and does not claim semantic round-trip validation.
81
91
82
-
Native results are stored separately in `native_oracle`: `ACCEPTED`, `SYNTAX_REJECTED` (1064/1149), `SERVER_ERROR`, `CLIENT_ERROR`, or **NOT VERIFIED**. For example, a derived table missing its required alias returns error 1248; this remains a server error, even though the corpus requires ParserSQL to reject that input. Accepted invalid controls and syntax-rejected valid controls count as expectation mismatches, using per-version validity when specified. Server errors remain explicitly unresolved; client errors return status 2. Thus exit status 0 still does not mean all native cases were verified. The default corpus metadata remains **NOT VERIFIED**, while the optional report describes the actual native observations.
92
+
Native results are stored separately in `native_oracle`: `ACCEPTED`, `SYNTAX_REJECTED` (1064/1149), `SERVER_ERROR`, `CLIENT_ERROR`, or **NOT VERIFIED**. For example, a derived table missing its required alias returns error 1248, and the corresponding JSON_TABLE witness returns 3667; these remain server errors, even though the corpus requires ParserSQL to reject those inputs. Accepted invalid controls and syntax-rejected valid controls count as expectation mismatches, using per-version validity when specified. Server errors remain explicitly unresolved; client errors return status 2. Thus exit status 0 still does not mean all native cases were verified. The default corpus metadata remains **NOT VERIFIED**, while the optional report describes the actual native observations.
83
93
84
-
A native check of all 340 witnesses under `ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION` found no native expectation mismatches. MySQL 8.4.8 accepted 147, syntax-rejected 175, and returned fifteen server errors; MySQL 9.7.2 accepted 152, syntax-rejected 165, and returned twenty server errors. Both runs skipped the three DDL/procedure witnesses and cleaned up their owned schemas. Server errors retain the existing missing-alias, empty/default VALUES, and repeated-lock observations, plus the documented unsupported JSON null behavior, secondary-engine requirements, row-valued grouping operand, quoted grouping-function names, missing FORMAT tables/databases, and EXPLAIN format restrictions. Two malformed EXPLAIN controls fail at semantic checks before native parsing reaches the later error: misplaced FORMAT returns 6006, and a missing destination name returns 3061. These remain unresolved server errors, not syntax rejections. Re-run the command on each isolated socket to reproduce current observations; reports are intentionally not committed.
94
+
Native checks of all 385 witnesses under `ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION` found no intended-validity mismatches. MySQL 8.4.8 accepted 170, syntax-rejected 198, and returned 17 server errors; MySQL 9.7.2 accepted 175, syntax-rejected 188, and returned 22 server errors. Every case had a native action, including DDL and procedure creation; no cases were skipped, and all owned schemas were cleaned up. Semantic errors remain unresolved observations, including missing aliases, unsupported runtime features, engine prerequisites, and error 1235 for the grammar-valid procedure parameter `COLLATE BINARY` witness in both releases. These must not be relabeled as syntax rejection. Reports are intentionally kept outside the repository; rerun each isolated socket to reproduce current observations. Separate native runs also submitted all 192 valid emitted witnesses to each pinned server. Every emitted statement retained the original observation state and error code. This is a bounded additional emission check, not proof of AST, optimizer, result-value, or execution equivalence.
85
95
86
-
The corpus is deliberately selected and is not a representative workload. It contains 330 shared witnesses and ten version-specific query witnesses; this does not imply identical dialects in 8.4.8 and 9.7.2. The version-specific entries record `applicability`, source productions for both versions, `native_validity` per version, and observed native outcomes. Their generic `validity=valid` denotes the 9.7.2 grammar target. The native helper selects the intended validity using the actual server version, so an expected 8.4.8 syntax rejection is not treated as a corpus error. Stored native observations are context, not substitutes for a current run. These version-specific query additions now pass ParserSQL parse/emission/reparse checks; native runtime restrictions remain separately reported. The following differences include the original four query witnesses and two separate DDL spot checks:
96
+
The corpus is deliberately selected and is not a representative workload. It includes shared and explicitly version-specific witnesses; this does not imply identical dialects in 8.4.8 and 9.7.2. The version-specific entries record `applicability`, source productions for both versions, `native_validity` per version, and observed native outcomes. Their generic `validity=valid` denotes the 9.7.2 grammar target. The native helper selects the intended validity using the actual server version, so an expected 8.4.8 syntax rejection is not treated as a corpus error. Stored native observations are context, not substitutes for a current run. These version-specific query additions now pass ParserSQL parse/emission/reparse checks; native runtime restrictions remain separately reported. The following differences include the original four query witnesses and two separate DDL spot checks:
87
97
88
98
| Reduced feature | MySQL 8.4.8 observation | MySQL 9.7.2 observation |
0 commit comments