Repository navigation
Quote ORDER BY names as identifiers where fragment quoting breaks them - #243
Open
simon-mundy wants to merge 1 commit into
Open
simon-mundy wants to merge 1 commit into
simon-mundy wants to merge 1 commit into
Conversation
Select::processOrder() fragment-quoted each order name, so names such as x-y, my col, a"b or café rendered as several quoted pieces. Such names are now quoted whole as an identifier chain split only on '.'. Names whose parts between '*' and '.' already render as one identifier each, such as t.col and price*qty, render byte-for-byte as before.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
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.
Problem
Select::order()renders some order names as broken SQL. On the SQL-92 platform:'x-y DESC'"x""-""y" DESC"x-y" DESC't-1.x-y DESC'"t""-""1"."x""-""y" DESC"t-1"."x-y" DESC['my col' => 'DESC']"my" "col" DESC"my col" DESC'a"b DESC'"a""'""b" DESC"a'b" DESC'café DESC'"café" DESCThe same happens in comma lists (
'x-y DESC, b') and in list arrays (['x-y DESC', 'b']).Cause
processOrder()passes each parsed order name toAbstractPlatform::quoteIdentifierInFragment(). That regex-splits on every non-word character and quotes each piece, leaving only the safe words (*, space,.,as) bare. Select columns, join columns andGROUP BYhave the same cause (#241), as do Update SET columns (#238). #241 lists ORDER BY as a follow-up.Rule
processOrder()now calls a new privateSelect::quoteOrderIdentifier():*and., and spaces around each segment are trimmed.quoteIdentifierInFragment()either as one quoted identifier (the same asquoteIdentifier()) or unchanged (empty, a bare safe word, or identifier quoting off), the name keeps fragment quoting as before.., each part goes throughquoteIdentifier(), a*part stays bare, and the parts are joined withgetIdentifierSeparator().The check uses the platform's own
quoteIdentifierInFragment(), so platform fragment patterns are respected. phpdb-mysql treats-as a word character, sox-yandprice*x-yalready rendered as valid SQL there and still render the same.The order-string parsing is unchanged: comma splitting, the first-space split into name and direction, ASC/DESC detection and
Expressionentries work as before.What stays the same
Any order whose fragment output was valid renders byte-for-byte as before. The tests pin these forms:
a,t.col DESCa DESC, bprice*qty DESC,['price * qty' => 'DESC'],['t.price*t.qty' => 'DESC']'my col DESC', which still parses as the namemywith an unknown direction ("my" ASC)t.as, and unknown directionsExpressionentries, alone and in arraysOnly output that was already broken changes. The maintainer's long-term direction (D18) is that identifier slots take identifiers only and SQL goes through
Expression. On 0.6.x, this PR changes only broken output.Tests
test/unit/Sql/SelectOrderNameTest.php(#[Group('unit')]) has three data-provider tests:*, andx-y.*, across the string, comma-list, array-key and list-array forms, with ASC and DESCHyphenWordSql92Platformtest asset uses phpdb-mysql's fragment pattern, andTestSql92Platformcovers identifier quoting offBefore the fix, all 14 broken-form cases and the
x+ycase on the hyphen-word platform failed, and every unchanged case passed. The changed lines inSelect.phpare fully covered../vendor/bin/phpunit --testsuite "unit test": OK (2217 tests)mago format --check,mago lint,mago analyze: all exit 0