IdStrategy::INT and IdStrategy::STRING from src/Enum/IdStrategy.php. Migration path: INT → AUTO_INCREMENT or UUID; STRING → UUID or UID. See ADR-0002.IdStrategy::UID remains in 2.0 (already [@deprecated](https://github.com/deprecated) since 1.0.x per AR-034). The deprecation is a 1.x lifecycle marker (the 18-char IdGenerator::generateUniqueId output is collision-prone under concurrent writers); the case is not removed in 2.0. Migration target for consumers who want collision-safe generation: IdStrategy::UUID (UUID v7, time-ordered). See ADR-0002 § Decision 3 and AR-034. Consumers on IdStrategy::INT or IdStrategy::STRING (the two cases removed in 2.0) should switch to IdStrategy::migrateFromV1() (added in 1.2.0 per AR-052) before upgrading to ^2.0.Full direction-setting rationale:
docs/adr/0002-wave-2.0-breaking-change-direction.md.
elrise/dbal-bundle → elriseio/dbal-bundle. composer.json name field updated. PSR-4 namespace (Elrise\Bundle\DbalBundle\), GitHub repository (elriseio/dbal-bundle), and source code are unchanged — this is a manifest-level rename only, aligned with the GitHub organisation. No source-code or behaviour change. No PHPUnit tests added or modified. Drop-in upgrade from ^1.2.0 for consumers who already depend on the elriseio/dbal-bundle URL on Packagist.README.md: four header badges (Latest Stable Version, Total Downloads, License) and the composer require install command updated to reference elriseio/dbal-bundle. CI badge and GitHub URLs were already correct.composer validate --strict passes after the rename.vendor/bin/phpunit reports the same 320/320 tests pass that v1.2.0 reported (no test file was touched by this commit).git diff v1.2.0 v1.2.1 --stat shows exactly three files changed: composer.json, README.md, and CHANGELOG.md. No src/, tests/, or itests/ file is touched.https://packagist.org/packages/elriseio/dbal-bundle (replaces https://packagist.org/packages/elrise/dbal-bundle).require.php bumped from ~8.2 to ~8.3, config.platform.php from 8.2.0 to 8.3.0. CI matrix updated from [8.2, 8.3, 8.4] to [8.3, 8.4, 8.5]. README compatibility line bumped. This is a breaking change for consumers on PHP 8.2; the typed class constants already in use (public const string NAME = ..., private const int LIMIT = ...) are PHP 8.3+ syntax and were silently failing CI on 8.2 — the bump aligns the declared minimum with the code that actually ships.php-cs-fixer 3.95 violations: ordered_class_elements (getFieldValue() moved before collectFields() in src/Utils/DtoFieldExtractor.php so public methods precede private ones) and no_useless_return (redundant trailing return; removed from the reapNext closure in itests/runner/parallel.php). CI on php-cs-fixer 3.95.15 now exits 0 across the new matrix.IdStrategy::migrateFromV1(IdStrategy $old, ?IdStrategy $explicitTarget = null): IdStrategy static helper on src/Enum/IdStrategy.php. Maps the v1 cases (INT, STRING) to their v2 replacements per ADR-0002 § Decision 3: INT → AUTO_INCREMENT (default) or UUID; STRING → UID (default) or UUID. Cases that survive into 2.0 (AUTO_INCREMENT, UUID, UID, DEFAULT) pass through unchanged. Available in 1.x as a developer-experience aid for consumers planning their 2.0 upgrade; the helper is backward-compatible (no existing call site breaks). 14 new PHPUnit cases in tests/Enum/IdStrategyTest.php exercise the migration table and the InvalidArgumentException path.Verification:
php-cs-fixer 3.95.15 fix --dry-runclean (0 of 120 files) on PHP 8.3 / 8.4 / 8.5;phpunit --no-coverage320/320 pass on the same matrix;composer validate --strictpasses.php -lon all 115 PHP files undersrc/,tests/,itests/clean on all three PHP versions.
304 tests pass. 18 sub-tasks closed from AR-017 through AR-034, on top of Wave 1.1 (AR-010, AR-011, AR-012) and Wave 1.2 (AR-013, AR-014, AR-015) closed earlier in the release window. One deprecation marker flags
IdStrategy::UIDfor removal at 2.0. No DBAL-internal breaking changes from 1.0.8; new public surfaces are additive (ConnectionAwareInterface, advisory-lock helpers,BulkUpserter::upsertManyReturningIds,LockModeenum). The H-stream boundaries are not strict — the unifying theme is hardening.
Elrise\Bundle\DbalBundle\Manager\ConnectionAwareInterface rollout: each of the 8 manager-layer classes (BulkInserter, BulkUpdater, BulkUpserter, BulkDeleter, DbalFinder, DbalMutator, CursorIterator, OffsetIterator) now exposes getConnection(): Connection. Non-breaking addition; callers can ask a finder / mutator / bulk executor for its underlying connection without reflection. Commits bcd5430 (rollout) and b2fbb8b (regression test).DbalBundleConfig::$strictFieldValidation flag and doctrine_dbal.strict_field_validation bundle-config node. When enabled, inserts reject unknown fields with a typed exception instead of silently dropping them. Commit 17be65d.docs/adr/0003-symmetric-bulk-builder-decision.md. No portable single-fragment UPSERT syntax exists across MySQL 8 / MariaDB 10.x / PostgreSQL 16+. The per-platform SqlBuilder dispatch (MysqlSqlBuilder, PostgresSqlBuilder, SqlBuilderFactory) is the permanent architecture. No SymmetricBulkSqlBuilder is implemented. Commit 0a41afa.Psr\Log\LoggerInterface dependency on AbstractDbalWriteExecutor and its descendants. When no logger is injected, the executor uses NullLogger and behaviour is unchanged. When a logger is injected, every bulk operation emits INFO start / INFO end (with operation, table, chunk_size, total_rows, rows_affected, duration_ms, peak_memory_mb), WARNING on a unique-constraint violation (dbal.bulk.constraint_violation), and ERROR before re-throwing a generic DBAL connection error (dbal.bulk.connection_error). composer.json adds psr/log: ^3.0 to require. Commit a325b55.bench/ using phpbench/phpbench (added to require-dev). Subjects: bench/InsertBench.php (100-row and 1000-row chunks), bench/UpdateBench.php (narrow and wide row shapes), bench/UpsertBench.php (insert-path and update-path), bench/CursorBench.php (10k-row fixture scan). Each subject is #[BeforeMethods('setUp')] + #[AfterMethods('tearDown')] + #[Revs] + #[Iterations] per the phpbench attribute API. New composer bench script invokes phpbench run --report=aggregate. bench/README.md documents fixture setup, BENCH_DATABASE_URL env var, expected output, and how to add a new subject. phpunit.xml.dist excludes bench/*Bench.php from coverage so the bench classes do not pollute coverage reports. Commit 18f6790.DbalBundleConfig::$sqlCommentEnabled (default false, backward-compatible opt-in) and corresponding doctrine_dbal.sql_comment_enabled bundle-config node. When enabled, every DbalConnection::executeQuery / executeStatement / prepare call prepends a JSON caller-trace comment carrying applicationCaller (first non-framework class in the backtrace) and entryPointController (Symfony controller or console command, if any). Wiring is automatic via AddSqlCommentEnablePass compiler pass. Commits 8e579ed (toggle) and 91afc73 (closure docs).QuestionMarkPlaceholderStrategy::prepareBulkParameterLists rewritten to an append-only form, replacing the per-call array_merge that rebuilt the result array for each input row on every bulk insert call. Allocations drop from O(n²) to O(n) over the parameter-list runtime. Commit 96a8fa7.SymfonyDtoDeserializer keeps a ReflectionClass lookup table keyed by DTO class, eliminating repeated reflection on hot deserialization paths. Commit 40b23af.DtoFieldExtractor::getFields memoizes the resolved field list per DTO class across calls; the array of fields is built once per class and reused on every subsequent extraction. Commit f700c8f.BacktraceHelper::getApplicationCaller keeps a static resolved caller per PHP process, so each cold caller resolution is paid at most once per worker. Commit 43d5d24.TransactionService uses a per-instance atomic counter for SAVEPOINT names, replacing the global uniqid() call that broke parallel transactions in long-running workers. Each TransactionService instance now owns its own savepoint-name counter; nested transactions no longer collide across workers. Commit 2cac12d.README.md and docs/architecture/STATUS.md synced with the actual support matrix: MySQL 8 (incl. 8.4 LTS), MariaDB 10.5+ / 11, PostgreSQL 12+ verified through 16. Removed the obsolete "MySQL 5.7" line, added a "Known compatibility gaps" subsection documenting the MySQL VALUES(col) deprecation (tracked for Wave H2) and the PG 17 / MariaDB 12 / MySQL 9 fixture gap. Symfony minimum bumped from "7.0+" to "7.2+" to match composer.json. Commit 28fb52b.PgUpsertBench exercise so the upsert update-path is actually covered by a benchmark on PG. Commit db25ca2.DbalConnection real streaming via unbuffered PDO query, replacing the buffered-then-replayed path. For SELECT result sets larger than the row-buffer threshold, the executor now uses PDO::MYSQL_ATTR_USE_BUFFERED_QUERY = false on MySQL / MariaDB and the equivalent PG path so rows stream to the consumer without being materialised in PHP memory first. Commit ba1382d.MysqlSqlBuilder now emits the row-alias form INSERT INTO ... (cols) AS new VALUES (...) ON DUPLICATE KEY UPDATE col = new.col (MySQL 8.0.20+), replacing the deprecated VALUES(col) function which MySQL 9.0 removes. INSERT [IGNORE] INTO ... (cols) AS new VALUES (...) is now the canonical prefix for all MySQL bulk inserts generated by the bundle (the alias is unused on plain insert but keeps a single canonical shape). getUpsertBulkSql cache key extended with the literal marker AS_NEW so cached SQL from before this migration is invalidated. MariaDB 10.x does not accept the row-alias form in ON DUPLICATE KEY UPDATE (only MariaDB 11+); MariaDB users must be on 11+ to use this version. Commit 306582a.CursorIterator supports composite-keyset pagination (multi-column keyset cursors, not just single-column). The cursor pair can now be a tuple (col1, col2, ..., colN) and the cursor query handles the lexicographic ordering of the composite key. Commit 6a5c6ef.JsonbType and JsonbObjectType (as jsonb and jsonb_object type names) for native PostgreSQL JSONB column support. Bundle-managed; consumers can now declare #[Column(type: 'jsonb')] and get binary-storage semantics (de-duplication, hash indexing) on PostgreSQL 12+ without hand-rolling a Type registration. On MySQL / MariaDB, the same Type name falls back to JSON text storage, matching Doctrine DBAL's standard cross-platform behaviour. DbalParameterType::JSONB_OBJECT enum case added (mapped to ParameterType::STRING in DbalTypeGuesser::toDoctrine); the existing JSONB case was already present but missing from the test data provider, so the mapping test now covers both. Commit a4f5353.int_array (INT[]), text_array (TEXT[]), and numeric_array (NUMERIC[]). Mirrors the existing float_array / float4_array pattern (final classes extending Doctrine\DBAL\Types\Type, with getSQLDeclaration, convertToPHPValue, convertToDatabaseValue, getName). Internal DbalParameterType enum gains INT_ARRAY, TEXT_ARRAY, NUMERIC_ARRAY cases (mapped to ParameterType::STRING in DbalTypeGuesser::toDoctrine). Text-array converter replicates the private escapePostgresString shape from ArraySerializer inline (the public surface of ArraySerializer is unchanged). Commit c4bc9e6.PgUpsertBench::benchUpsertUpdatePath now actually exercises the ON CONFLICT update-path SQL generated by PostgresSqlBuilder::getUpsertBulkSql. Previously the bench always hit the insert path because the seed fixture didn't create a row collision; the seed now includes a pre-existing row that the bench update arm matches against, so the update-path latency is now reflected in the benchmark aggregate. Commit 4c61fe7.max_allowed_packet. The executor probes @[@max_allowed_packet](https://github.com/max_allowed_packet) once per connection lifetime (cached), then bounds the bulk-insert chunk size to a fraction of that limit. Avoids truncation errors on large bulk inserts without the operator having to tune the chunk size manually. Commit b57282c.sqlCache on SqlBuilderFactory. Cached SQL fragments are keyed by (platform class, builder method, mutation-relevant inputs) so that repeated calls within the same PHP process avoid re-running the SQL string assembly. Cache invalidation is correct under the row-alias migration (AR-025 cache key bump). Commit 5b9acaa.BulkUpserter::upsertManyReturningIds on the PostgreSQL path. Appends RETURNING <id column> to the upsert SQL and returns the per-row IDs in one round-trip. MySQL / MariaDB are not supported and throw LogicException (the RETURNING clause is PG-specific). PostgresSqlBuilder::getUpsertBulkSqlReturningIds is the underlying SQL builder; BulkUpserterInterface declares the contract method. Commit 51e6df3.TransactionService: acquireAdvisoryLock(int), tryAdvisoryLock(int): bool, releaseAdvisoryLock(int) (PostgreSQL-only, throw LogicException on other platforms), and lockRows(string, array, LockMode): int (cross-platform row-level FOR UPDATE / FOR SHARE / LOCK IN SHARE MODE mapping via the new Elrise\Bundle\DbalBundle\Manager\Contract\LockMode enum with cases FOR_UPDATE, FOR_NO_KEY_UPDATE, FOR_SHARE, FOR_KEY_SHARE). lockRows accepts a single-value criteria array and emits SELECT * FROM <table> WHERE ... <fragment> LIMIT 1. PG-only modes (FOR_NO_KEY_UPDATE, FOR_KEY_SHARE) throw LogicException on MySQL/MariaDB. TransactionServiceInterface declares the four new methods. Commit 97ebed2.IdStrategy::UID is marked [@deprecated](https://github.com/deprecated) since 1.0.x; it will be removed in 2.0.0. The 18-char generated ID relies on getmypid() + uniqid() + md5 and is collision-prone under concurrent PHP-FPM / long-running-worker workloads. Migration target: IdStrategy::UUID (UUID v7, time-ordered, collision-safe). A WARNING-level log line dbal.id_strategy.uid_deprecated is emitted on each use. The [@deprecated](https://github.com/deprecated) marker is a 1.x lifecycle signal; the case remains in 2.0 per ADR-0002 § Decision 3 (only INT and STRING are removed). Consumers who prefer collision-safe generation should migrate to IdStrategy::UUID at their convenience. The other cases (AUTO_INCREMENT, UUID, INT, STRING, DEFAULT) are unchanged. IdGenerator::generateUniqueId stays in place for 1.x but is the deprecated implementation path. Commit b1a5ec0.README.md "Compatibility" section reflects the actual support matrix (MySQL 8 incl. 8.4 LTS, MariaDB 10.5+ / 11, PostgreSQL 12+ verified through 16, plus the 8.4 / 11 / 17 fixtures added in AR-023).docs/architecture/STATUS.md synced with platform coverage.composer.json's public-facing README to match the actual composer.json constraint.vendor/bin/phpunit reports 304/304 tests passing, 644 assertions, 1 deprecation warning (the IdStrategy::UID deprecation marker introduced by AR-034 — expected and not a test failure).vendor/bin/php-cs-fixer fix --dry-run exits 0 with 0 style violations after the AR-034 auto-fix pass.composer validate --strict exits 0 with no warnings.strictFieldValidation to reject unknown insert fields (AR-011, opt-in via doctrine_dbal.strict_field_validation).sqlCommentEnabled to attach a caller-trace comment to every SQL invocation (AR-015, opt-in via doctrine_dbal.sql_comment_enabled).IdStrategy::UID consumers to IdStrategy::UUID at your convenience; the deprecation marker is non-blocking in 1.x. IdStrategy::UID remains available in 2.0 per ADR-0002 § Decision 3 (only INT and STRING are removed); the migration is a recommendation for collision-safety, not a forced upgrade. See [2.0.0]() above for the actual 2.0 surface.docs/adr/0002-wave-2.0-breaking-change-direction.md) — 2.0 direction-setting decision; informs the AR-034 deprecation.docs/adr/0003-symmetric-bulk-builder-decision.md) — Symmetric Bulk Builder no-go decision; informs the Wave 1.1 / AR-012 closure.docs/ROADMAP.md — full roadmap and wave closures.Issues/done/developer/AR-*.md — individual sub-task manifests with commit-SHA trails.Elrise\Bundle\DbalBundle\Enum\*Interface (non-existent namespace). All imports now correctly reference Elrise\Bundle\DbalBundle\Manager\Contract\*Interface. The bundle could not autoload before this fix.manifest.json referenced non-existent class ItechDbalBundle. Corrected to ElriseDbalBundle.DtoFieldExtractorTest::testNoDuplicatesWithMixedAccess now uses assertEqualsCanonicalizing; QuestionMarkPlaceholderStrategyTest::testPrepareBulkParameterListsWithEmptyInput uses a single-platform data provider compatible with the method signature.composer.json license: proprietary → MIT (LICENSE file was already MIT).keywords, homepage, and support fields to composer.json for Packagist discovery.elrise/dbal-bundle, Doctrine DBAL 4.2+, PostgreSQL 16 in supported list.No changes
v1.0.0 from the develop branchHow can I help you explore Laravel packages today?