Accept non-reserved keyword and quoted CTE names (#662) - #667
Open
youdie006 wants to merge 1 commit into
Open
Conversation
The WITH parser only accepted a CTE name tokenized as TokenType::None, so a non-reserved keyword (e.g. data) or a backtick-quoted identifier (e.g. my_cte) was rejected with "The name of the CTE was expected." even though MySQL accepts both, making valid CTE queries fail to parse. Accept, in addition to a plain identifier, a non-reserved keyword and a backtick-quoted symbol as the CTE name; Token::value already yields the correct name (backticks stripped) in every case. Also removed the now-obsolete negated-boolean phpstan baseline entry that covered the replaced "! preg_match(...)" expression. Fixes phpmyadmin#662
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #662.
Problem
The
WITH(CTE) parser rejects valid CTE names. MySQL accepts a non-reserved keyword (e.g.data,text) as an unquoted identifier, and any identifier when backtick-quoted, but the parser reportsThe name of the CTE was expected.for:The same happens for a backtick-quoted name such as
WITH \my_cte` AS (...)`.Root cause
In
WithStatement::parse()the CTE-name state only accepts a token of typeTokenType::None. A non-reserved keyword is lexed asTokenType::Keyword(withoutFLAG_KEYWORD_RESERVED), and a backtick-quoted identifier asTokenType::Symbol(withFLAG_SYMBOL_BACKTICK), so both fail the guard and are reported as errors.Fix
Also accept a non-reserved keyword and a backtick-quoted symbol as the CTE name.
Token::$valuealready carries the correct name (backticks stripped for the symbol case, the keyword text for the keyword case), so the rest of the method is unchanged. Reserved keywords (e.g.SELECT) are still rejected.The old condition negated
preg_match()(int|false), suppressed by a PHPStan baseline entry; the new condition compares explicitly (=== 1), so I removed the now-obsolete baseline entry.Test
Added
testWithNonReservedOrQuotedName(data provider) totests/Parser/WithStatementTest.php, covering a non-reserved keyword name, a backtick-quoted keyword name, and a backtick-quoted identifier with a space. Red-green verified: before the fix all three produceThe name of the CTE was expected.; after, each parses with zero errors and the expected wither name.Verified locally under PHP 8.4: full
phpunit(1023 tests),phpcsandpsalmclean.phpstanreports only one pre-existing error inCreateStatement.phpthat is also present on the unmodified tree (a baseline/PHP-version artifact unrelated to this change).Disclosure: prepared with AI assistance (Claude); I reviewed it and verified the red-green test and the project test/analysis gates.