CodeSampleX

Sample

doctrine/dbal 4.4.4: Query an in-memory SQLite through Doctrine DBAL 4 without the parameter binding, empty result and schema introspection traps

Verified sample for composer doctrine/dbal 4.4.4: Query an in-memory SQLite through Doctrine DBAL 4 without the parameter binding, empty result and schema…

sha256:090b8a4df8ed4282fa66e190d2a7e4a2c1611b82a538304c73a2585e29fa9c7a

This network offers one thing: a sample that builds. It ran the sample in a sandbox and kept the signed receipt. It grades nothing and warrants nothing — whether the same code builds where you are is not something it measured. How many distinct signing keys filed a passing contract receipt. One is the author alone; more than one means somebody else built it too. A key is self-generated with nothing registered behind it, so it counts keys, not people. MIT-0

Execution evidence

The declared environment and the signed runs are kept apart, so you can see exactly what this sample ran and where.

Evidence basis
Signed contract pass
Verification receipts
1
Signing keys that built it
1
Declared environment php 8 linux x64 php 8 php composer

Verification-run environments

Environment Contract Stages Run
php 8 · linux alpine/x64 · docker ed25519:a2ec939a4c60e243 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · composer@1
2026-08-14

Case

HOW
Goal
Query an in-memory SQLite through Doctrine DBAL 4 without the parameter binding, empty result and schema introspection traps
Packages
Symbols
  • Doctrine.DBAL.DriverManager
  • Connection::executeQuery
  • Result::fetchAssociative
  • Doctrine.DBAL.ParameterType
  • Doctrine.DBAL.ArrayParameterType
  • QueryBuilder::createNamedParameter
  • QueryBuilder::setParameter
  • AbstractSchemaManager::introspectTable
  • Type::lookupName
Environment
php 8
Created
2026-08-14T20:22:50Z

Contract

  1. assert positional parameters are bound in the order the array was built and never by its keys, so two arrays that are == with the same keys give different answers and ksort alone changes the result
  2. assert named parameters are resolved by name so the order they were set in cannot matter, and that a 1-based or nonsense-keyed positional array still works because no key is ever read
  3. assert named and positional placeholders can be mixed in one statement despite the manual saying they cannot, and that whether the SQL parser runs at all is decided by is_string on the first key of the params array
  4. assert that same switch decides whether a bad parameter list raises MissingNamedParameter or MissingPositionalParameter or instead reaches the driver as SQLSTATE column index out of range, and that a surplus named value is silently unused
  5. assert fetchAssociative returns false rather than null when the result is exhausted so the ?? guard never fires, and that fetchOne returns false for no row but int 0 for a stored zero, which are == but not ===
  6. assert fetchAllAssociative spells the same emptiness as an empty array instead, and that rowCount reports 0 for a SELECT on pdo_sqlite so counting has to happen in SQL
  7. assert a wrong ParameterType rewrites the value instead of failing: '0012' bound as INTEGER is stored as '12', 'abc' becomes 0, 2.9 truncates to 2, and false bound as STRING becomes the empty string rather than '0'
  8. assert that mistake still matches on an INTEGER column because SQLite applies column affinity to the comparison, and matches nothing against a text column, which is why it survives the read path and only corrupts writes
  9. assert an IN clause needs createNamedParameter with an ArrayParameterType, that the single placeholder is expanded into one ? per element inside executeQuery rather than by the builder, and that an empty list becomes the literal NULL
  10. assert expr()->in with a raw array interpolates the values into the SQL and dies on 'no such column' for strings, that setParameter with an array and the default type only raises a PHP 'Array to string conversion' warning and matches nothing, and that a scalar ParameterType casts the array to 1 with no diagnostic at all
  11. assert setParameter binds a value without adding a placeholder, so a parameter whose placeholder is missing from the SQL is discarded without complaint
  12. assert schema introspection returns datetime for datetime_immutable, text for json and simple_array, and a fixed string(36) for guid, while length, precision, scale and autoincrement do survive the round trip
  13. assert the Comparator still calls the two schemas identical and emits no ALTER because it compares the generated DDL rather than the Doctrine type, so the loss surfaces only in convertToPHPValue handing back a mutable DateTime and an undecoded JSON string
  14. assert introspecting a declared type with no mapping raises InvalidArgumentException instead of falling back to string, and that Type::getName is gone in DBAL 4 in favour of the static Type::lookupName

Files

  • composer.json
  • composer.lock
  • csx.json
  • phpunit.xml
  • src/Ledger.php
  • test/LedgerTest.php

Download the source artifact (tar.gz)

Origin Seeder

anonymous