@@ -9,6 +9,75 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99
1010---
1111
12+ ## [ 2.5.1] - 2025-10-22
13+
14+ ### Added
15+ - ** Db::inc() and Db::dec() support in onDuplicate()** : Now you can use convenient helpers for UPSERT increments
16+ - Works across all dialects: MySQL, PostgreSQL, SQLite
17+ - Example: ` ->onDuplicate(['counter' => Db::inc(5)]) `
18+ - Automatically generates dialect-specific SQL (e.g., ` counter = counter + 5 ` )
19+ - ** CI testing for examples** : All 21 examples now tested in GitHub Actions
20+ - SQLite: 21/21 examples verified
21+ - MySQL: 20/20 examples verified (if database available)
22+ - PostgreSQL: 20/20 examples verified (if database available)
23+ - ** New tests** for UPSERT functionality:
24+ - ` testUpsertWithRawIncrement() ` - tests ` Db::raw('age + 5') ` in onDuplicate
25+ - ` testUpsertWithIncHelper() ` - tests ` Db::inc(5) ` in onDuplicate
26+ - ` testGroupByWithQualifiedNames() ` - verifies qualified column names in GROUP BY
27+
28+ ### Changed
29+ - ** All examples migrated to QueryBuilder API** :
30+ - Replaced 15+ ` rawQuery() ` calls with fluent QueryBuilder methods
31+ - ` rawQuery() ` now used ONLY for DDL (CREATE/ALTER/DROP TABLE)
32+ - Examples demonstrate best practices with ` Db:: ` helpers
33+ - ** Enhanced buildUpsertClause() signature** (backwards compatible):
34+ - Added optional ` $tableName ` parameter for PostgreSQL ambiguous column resolution
35+ - Enables proper ` Db::inc() ` and ` Db::raw() ` support in UPSERT operations
36+ - ** Improved test-examples.sh script** :
37+ - Fixed PostgreSQL port detection in connection checks
38+ - Now correctly detects all 3 database dialects when available
39+ - ** JSON column handling** : Examples automatically use JSONB for PostgreSQL, TEXT for MySQL/SQLite
40+
41+ ### Fixed
42+ - ** CRITICAL: groupBy() and orderBy() with qualified column names** (` u.id ` , ` t.name ` ):
43+ - ** Bug** : Qualified names quoted as single identifier `` `u.id` `` instead of `` `u`.`id` ``
44+ - ** Impact** : Broke on MySQL/PostgreSQL with "Unknown column 'u.id'" error
45+ - ** Fix** : Changed to use ` quoteQualifiedIdentifier() ` instead of ` quoteIdentifier() `
46+ - ** Tests** : Added ` testGroupByWithQualifiedNames() ` for all 3 dialects
47+ - ** CRITICAL: Db::inc()/Db::dec() ignored in onDuplicate()** :
48+ - ** Bug** : Dialects didn't handle ` ['__op' => 'inc'] ` array format in UPSERT
49+ - ** Impact** : UPSERT replaced value instead of incrementing
50+ - ** Fix** : Added ` is_array($expr) && isset($expr['__op']) ` handling in all dialects
51+ - ** PostgreSQL UPSERT "ambiguous column" errors** :
52+ - ** Bug** : ` Db::raw('age + 5') ` in onDuplicate caused "column reference ambiguous"
53+ - ** Impact** : PostgreSQL couldn't distinguish old vs new column values
54+ - ** Fix** : Auto-qualify column references with table name (` user_stats."age" + 5 ` )
55+ - ** PostgreSQL lastInsertId() exception for non-SERIAL tables** :
56+ - ** Bug** : Crash when inserting into tables without auto-increment
57+ - ** Fix** : Added try-catch in ` executeInsert() ` to gracefully handle missing sequence
58+ - ** String literal quoting in SQL expressions** :
59+ - Fixed PostgreSQL compatibility (uses ` 'string' ` not ` "string" ` )
60+ - Fixed CASE WHEN conditions to use single quotes for string literals
61+ - Examples now properly escape string values in Db::raw() expressions
62+ - ** Examples multi-dialect compatibility** :
63+ - JSON columns: Use JSONB for PostgreSQL, TEXT for MySQL/SQLite
64+ - String concatenation: Dialect-aware (` || ` vs ` CONCAT() ` )
65+ - Date/time functions: Dialect-specific interval syntax
66+ - All 21 examples verified on all 3 dialects
67+
68+ ### Technical Details
69+ - ** All tests passing** : 343 tests, 1544 assertions (up from 334 tests)
70+ - Added 9 new tests across MySQL, PostgreSQL, SQLite
71+ - Zero failures, zero errors, zero warnings
72+ - ** All examples passing** : 61/61 total runs (21 examples × ~ 3 dialects each)
73+ - SQLite: 21/21 ✅
74+ - MySQL: 20/20 ✅ (01-connection.php uses SQLite only)
75+ - PostgreSQL: 20/20 ✅
76+ - ** PHPStan Level 8** : Zero errors across entire codebase
77+ - ** Full backwards compatibility** : Optional parameter with default value
78+
79+ ---
80+
1281## [ 2.5.0] - 2025-10-19
1382
1483### Added
@@ -308,7 +377,8 @@ Initial tagged release with basic PDO database abstraction functionality.
308377
309378---
310379
311- [ Unreleased ] : https://github.com/tommyknocker/pdo-database-class/compare/v2.5.0...HEAD
380+ [ Unreleased ] : https://github.com/tommyknocker/pdo-database-class/compare/v2.5.1...HEAD
381+ [ 2.5.1 ] : https://github.com/tommyknocker/pdo-database-class/compare/v2.5.0...v2.5.1
312382[ 2.5.0 ] : https://github.com/tommyknocker/pdo-database-class/compare/v2.4.3...v2.5.0
313383[ 2.4.3 ] : https://github.com/tommyknocker/pdo-database-class/compare/v2.4.2...v2.4.3
314384[ 2.4.2 ] : https://github.com/tommyknocker/pdo-database-class/compare/v2.4.1...v2.4.2
0 commit comments