Fix LIMIT/OFFSET and FOR UPDATE guards firing on keywords inside identifiers, comments and subqueries. - #13
Open
itoolsTim wants to merge 1 commit into
Open
Fix LIMIT/OFFSET and FOR UPDATE guards firing on keywords inside identifiers, comments and subqueries.#13itoolsTim wants to merge 1 commit into
itoolsTim wants to merge 1 commit into
Conversation
…tifiers, comments and subqueries.
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.
Fix LIMIT/OFFSET and FOR UPDATE guards firing on keywords below the top level
selectOne(),queryOne()andcount()append their ownLIMIT, so they reject templates that already contain one. The check waspreg_match('/\b(LIMIT|OFFSET)\b/i', $where), and\bmatches inside backticks, comments and parentheses. So all of these threwThis method doesn't support LIMIT or OFFSETon valid SQL:The
FOR UPDATE/LOCK IN SHARE MODEcheck inrejectPreLimitConflicts()had the same problem.Fix (
src/ConnectionInternals.php): new private helpertopLevelSql()blanks out quoted text, backtick identifiers, comments and parenthesised groups (nested, in one recursive pass). Both guards now match against that, so only a real top-level clause fires them. The raw regex still runs first, so templates with no keyword at all cost nothing extra. Error messages are unchanged. The trailing-comment and trailing-;checks deliberately still see the raw template.Side effect: a quoted keyword like
name = 'no limit'now reports the accurateQuotes not allowed in templateerror instead of the misleading LIMIT/OFFSET one (quotes were always rejected byassertSafeTemplate(); the guard just fired first).Tests:
tests/DB/LimitOffsetGuardTest.php(16 tests) - keyword allowed inside identifiers, comments, derived tables and nested subqueries; top-levelLIMIT/OFFSET/FOR UPDATEstill rejected, including after a subquery; quotes error takes precedence. Existing rejection tests inSelectTest,CountTest,QueryTest,DocsExamplesTestare unaffected.Feel free to take whatever from this and test it out. I ran this specifically against 3.84 and based on the repo after including SmartArrayHtml and related classes.