Skip to content

[TMP] IBX-12043: Upgraded to Doctrine DBAL 4 - #39

Open
ViniTou wants to merge 2 commits into
6.0from
dbal-4-upgrade
Open

[TMP] IBX-12043: Upgraded to Doctrine DBAL 4#39
ViniTou wants to merge 2 commits into
6.0from
dbal-4-upgrade

Conversation

@ViniTou

@ViniTou ViniTou commented Aug 6, 2026

Copy link
Copy Markdown
Contributor
🎫 Issue IBX-12043

Related PRs:

Important

composer.json carries [TMP] pointers for ibexa/core, ibexa/doctrine-schema and ibexa/test-core (dev-dbal-4-upgrade as 6.0.x-dev). All must be reverted to ~6.0.x-dev once those PRs merge, before this PR is mergeable.

Description:

Binding types became enums, and QueryBuilder::getQueryPart() was removed. Both ripple into public signatures.

Parameter types:

  • Connection::ARRAY_PARAM_OFFSET is gone, so the ParameterType + offset arithmetic that turned a scalar binding type into an array one is replaced by an explicit mapping — DoctrineSchemaMetadata::getArrayBindingTypeForColumn(), next to the existing lookup
  • getBindingTypeForColumn() returns ParameterType instead of int — signature change on DoctrineSchemaMetadataInterface
  • Parameter widens its type to match

getQueryPart() removal — both answers now come from the query builder itself, since in both cases the builder may have been set up by the calling gateway rather than by this code:

  • "is this table already joined?" — the join is added to a clone and the clone asked to build itself; DBAL reports a taken alias as NonUniqueAlias. A gateway is free to join a relationship's table before handing the query over — ibexa/shipping does exactly that for ibexa_shipping_method_region, which the ShippingMethodRegion criterion then joins again — so tracking only what this strategy joined gives the wrong answer and the query becomes unbuildable.
  • "has this sub-select been given a SELECT?" — derived from getSQL(), which throws QueryException when no SELECT expressions have been provided.

Insert identifiers — the change worth the most review:

  • DBAL 3's lastInsertId() returned "0" for a table that generates no identity and callers discarded it. DBAL 4's MySQL driver throws NoIdentityValue; PostgreSQL instead falls back to LASTVAL() and returns whichever sequence the session last touched, so the value was wrong there too — silently.
  • doInsert() now returns the identifier the caller supplied in $data when the table has a single identifier column and that column is present, and only reads lastInsertId() otherwise. Callers need no change, and a table whose id comes from its parent stops being a landmine.
  • doInsertWithoutIdentity() remains for tables with no single identifier to return — composite-keyed assignment tables. Four call sites org-wide, all in ibexa/order-management.
  • DoctrineSchemaMetadataInterface::getIdentifierColumns() added; getIdentifierColumn() throws on composite keys, so it could not answer this.

This shape was chosen over two sibling methods because whether a table generates an identity is a fixed property of the table, not of the call, and making each author pick was demonstrably error-prone: eleven sites were found and fixed by hand across four packages and a twelfth — ibexa/share, ibexa_collaboration_content — was still missed. It needs no change under this behaviour.

For QA:

  • filtering and sorting through the persistence layer's Doctrine gateways, in particular criteria filtering on a related entity (sub-select and joined relationship types) and IN comparisons, which are the array-binding path
  • creating records in packages with joined-inheritance tables — order, discount code usage, collaboration participants, product attributes — on MySQL or MariaDB; PostgreSQL passes either way

Documentation:

N/A

@ViniTou ViniTou changed the title IBX-12043: Upgrade to Doctrine DBAL 4 [TMP] IBX-12043: Upgraded to Doctrine DBAL 4 Aug 7, 2026
@ViniTou
ViniTou force-pushed the dbal-4-upgrade branch 3 times, most recently from d919a11 to 1f91bb5 Compare August 7, 2026 10:17
@ViniTou
ViniTou force-pushed the dbal-4-upgrade branch 2 times, most recently from eaf558e to efa4dc7 Compare August 21, 2026 10:32
Binding types became enums, so Connection::ARRAY_PARAM_OFFSET arithmetic is replaced by a mapping onto ArrayParameterType and getBindingTypeForColumn() returns ParameterType. QueryBuilder::getQueryPart() is gone, so already-joined tables are tracked per QueryBuilder via core's JoinedTablesTracker and an uninitialised sub-select is recognised from the builder itself.

The PostgreSQL CI job passed the server version as "server_version", which DoctrineBundle never reads; it hands DBAL 4 an empty string instead and the PostgreSQL driver rejects it. The query parameter is "serverVersion", and its value now matches the postgres service image.

DBAL 4 makes lastInsertId() throw NoIdentityValue instead of returning "0" when the statement generated none, which breaks doInsert() for tables that have no auto-increment column, such as the child table of a joined inheritance hierarchy where the caller supplies the identifier. Those call sites now use doInsertWithoutIdentity() and never ask for a value the database was never going to produce.
Points ibexa/core, ibexa/doctrine-schema, ibexa/test-core at their dbal-4-upgrade branches so this one can resolve before they are merged. Revert this commit once they are.
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.

3 participants