Skip to content

fix(parser): support CAST to an array type for MySQL multi-valued indexes - #2506

Merged
manticore-projects merged 1 commit into
JSQLParser:masterfrom
minleejae:fix/issue-2490-multi-valued-index-cast-array
Aug 25, 2026
Merged

fix(parser): support CAST to an array type for MySQL multi-valued indexes#2506
manticore-projects merged 1 commit into
JSQLParser:masterfrom
minleejae:fix/issue-2490-multi-valued-index-cast-array

Conversation

@minleejae

Copy link
Copy Markdown
Contributor

Refs #2490

Description

Fixes the last open group of #2490, group 6, multi-valued (functional) indexes:

CREATE INDEX i20 ON t ((CAST(data->'$.zips' AS UNSIGNED ARRAY)));
ALTER TABLE t ADD INDEX i31 ((CAST(data->'$.zips' AS UNSIGNED ARRAY)));

Both failed at the ARRAY keyword inside the cast target type, because that keyword was not reachable from the type of a CAST.

Approach

ARRAY is accepted as a further word of the cast target type, exactly the way INT UNSIGNED is already assembled by DataType(). The type therefore reads UNSIGNED ARRAY, so:

  • no change to the public ColDataType model is needed, and
  • both output paths, CastExpression#toString() and ExpressionDeParser, render it through the same ColDataType#toString(), so the statement round trips.

It is added to the CastExpression() production only, which is where MySQL permits it. The ARRAY<type> constructor form and the [] array suffix are untouched, and no other statement gains a trailing ARRAY.

If you would rather have this exposed as an explicit flag on ColDataType for programmatic access, say the word and I will change it.

Testing

  • ./gradlew check passes: checkstyle, PMD, spotless, spotbugs, JaCoCo.
  • 4927 tests, 0 failures, 0 errors.
  • JavaCC reports 0 errors and 13 warnings, unchanged from master, verified by regenerating the parser on both states.
  • Three new tests: the CREATE INDEX form, the ALTER TABLE form, and the cast itself, including CAST(x AS CHAR(10) ARRAY) to cover a type that carries a precision, plus an assertion that the parsed type is UNSIGNED ARRAY.
  • Verified that CAST(x AS UNSIGNED) and ARRAY<INT>[1, 2] still parse unchanged.

All statements were verified against MySQL 8.4.11 while writing #2490.

PR Checklist

  • I have read the contribution guidelines and the governance document on PR expectations.

…exes

MySQL defines a multi-valued index key part by casting to an array, e.g.
CAST(data->'$.zips' AS UNSIGNED ARRAY). The trailing ARRAY keyword was not
reachable, so both the CREATE INDEX and the ALTER TABLE form failed to parse.

ARRAY is accepted as a further word of the cast target type, the way INT
UNSIGNED already is, so no model change is needed and the deparsed statement
round trips. It is added to the CAST production only, where MySQL allows it,
which leaves the ARRAY<type> constructor form untouched.

Closes the last open group of JSQLParser#2490.
@manticore-projects

Copy link
Copy Markdown
Contributor
CREATE INDEX i20 ON t ((CAST(data->'$.zips' AS UNSIGNED ARRAY)));
ALTER TABLE t ADD INDEX i31 ((CAST(data->'$.zips' AS UNSIGNED ARRAY)));

They should have killed this when it was little still.
But since it seems to be useful to someone, so be it.

@manticore-projects
manticore-projects merged commit e781b3f into JSQLParser:master Aug 25, 2026
7 checks passed
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.

2 participants