Skip to content

fix: reset stale query bindings to prevent type conversion errors#164

Merged
usernane merged 2 commits into
mainfrom
dev
Jun 8, 2026
Merged

fix: reset stale query bindings to prevent type conversion errors#164
usernane merged 2 commits into
mainfrom
dev

Conversation

@usernane

@usernane usernane commented Jun 8, 2026

Copy link
Copy Markdown
Member

Summary

Fix stale query parameter bindings leaking between queries, causing MSSQL error 245 (varchar to int conversion) when migrations fail before calling execute().

Motivation

In MSSQL environments, calling SchemaRunner::apply() multiple times would crash with "Conversion failed when converting the varchar value ... to data type int" when a prior migration threw an exception before completing query execution, leaving dirty bindings on the shared query generator.

Changes

  • Added resetBinding() in SchemaRunner::apply() and applyOne() catch blocks to clean up after failed migrations
  • Added defensive resetBinding() in SchemaChangeRepository::count() before building queries
  • Added resetBinding() at the start of update() in MySQLQuery and MSSQLQuery
  • Added observability improvements over exceptions in schema runner
  • Added SchemaRunnerApplyMultipleTest (16 tests) covering repeated apply() calls and the dirty-bindings scenario
  • Added StaleBindingsTest (4 tests) covering update/delete resilience against abandoned query bindings

How to Test / Verify

Unit tests covering SQLite, MySQL, and MSSQL:

php vendor/bin/phpunit --filter "SchemaRunnerApplyMultipleTest|StaleBindingsTest"

Full suite passes (882 tests, 2535 assertions).

Breaking Changes and Migration Steps

None

Checklist

  • I reviewed my own diff before requesting review
  • My commits follow Conventional Commits
  • The title of the pull request follows Conventional Commits
  • I added/updated tests (or explained why not)
  • I updated docs (if needed)
  • I ran lint/cs-fixer (if applicable)
  • I considered backward compatibility
  • I considered security

Related issues

Not Applicable

Ibrahim BinAlshikh and others added 2 commits June 8, 2026 22:03
When a migration throws before calling execute(), its bindings remain
on the shared query generator. Subsequent calls to
SchemaChangeRepository::count() then inherit these stale bindings,
causing MSSQL to fail with error 245 (varchar to int conversion)
when the extra binding is passed to a mismatched placeholder.

Changes:
- Add resetBinding() in SchemaRunner::apply() and applyOne() catch
  blocks to clean up after failed migrations
- Add defensive resetBinding() in SchemaChangeRepository::count()
  before building the query
- Add resetBinding() at the start of update() in MySQLQuery and
  MSSQLQuery to prevent stale bindings from prior abandoned queries
  from corrupting update parameter binding

Tests:
- Add SchemaRunnerApplyMultipleTest covering apply() called multiple
  times, including the specific scenario of a failed migration leaving
  dirty bindings
- Add StaleBindingsTest covering update and delete resilience against
  abandoned query bindings
@sonarqubecloud

sonarqubecloud Bot commented Jun 8, 2026

Copy link
Copy Markdown

@usernane usernane merged commit cda6bc9 into main Jun 8, 2026
9 of 13 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.

1 participant