Repository navigation
Render the same parameter names every time a statement is rendered - #236
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
Parameter naming state (instanceParameterIndex, processInfo subselect count and the function-static exprNParam counter) carried over between renders, so a second prepare of the same Select/Update/Insert/Delete/ Combine produced where3, subselect2where1, expr1Param1 and so on. getSqlString() and prepareStatement() now reset that state before building, a platform decorator resets its subject too, and processSubSelect starts each sub-select with a clean index. The exprNParam counter moves into processInfo and is carried through sub-selects like the subselect count, so first-render names are unchanged and no longer depend on process history.
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
Rendering the same Sql object more than once gives different SQL and parameter names each time. With a named-parameter driver and a fresh
ParameterContainerper call::n1:n2:where1,:where2:where3,:where4:subselect1where1:subselect2where1:expr0Param1:expr1Param1This affects anything that renders a statement more than once: calling
prepareStatementForSqlObject()twice,getSqlString()followed by a prepare, retries, and statement caches keyed on SQL text. The same drift happens with Update, Insert, Delete, Combine and through platform decorators.exprNParamnames also depended on everything else rendered earlier in the PHP process, so the first render of a new object was not predictable either.Cause
AbstractSqlkeeps its naming state on the object, and none of it was reset between renders:$instanceParameterIndexkept counting per prefix (where,n, ...).$processInfo['subselectCount']kept growing, so sub-selects were numbered from where the last render stopped.$instanceParameterIndexandprocessInfofrom earlier renders. A Select that had been used as a sub-select also kept itssubselectNprefix when it was later rendered on its own.processExpression()numbered unnamed expressions with a function-static counter shared by the whole process.Fix
AbstractSql::resetRenderState()setsprocessInfoback to its defaults and emptiesinstanceParameterIndex. A platform decorator also resets its subject, because it copies the subject's state at the start of each render.getSqlString()andAbstractPreparableSql::prepareStatement()call it before building. Nested renders callbuildSqlString()directly, so they are not reset part way through.processSubSelect()gives each sub-select a freshprocessInfoandinstanceParameterIndexfor this render.processInfo['expressionCount']. It is passed into sub-selects and read back afterwards, the same waysubselectCountis, so parent and sub-select expressions stay uniquely named and keep today's order.For a new object in a new process, every name is the same as the current first render. Combine and TableGateway need no changes because they render through these entry points. The phpdb-mysql and phpdb-sqlite decorators only read
processInfo['paramPrefix'], which is unchanged.Tests
test/unit/Sql/RenderStateTest.php(#[Group('unit')]). All 10 cases fail before the fix:getNamedArray(), both equal to today's first-render output.getSqlString()between two prepares does not change the names.subselectNprefix when prepared on its own.phpunit --testsuite "unit test"passes (2192 tests).mago format --check,mago lintandmago analyzeall exit 0. Every changed line is covered.