v2.7.1
🚀 Release v2.7.1 - Major Query Builder Enhancements
Overview
v2.7.1 introduces five major query builder features with full cross-database support, comprehensive testing, and extensive documentation. This release significantly expands the library's capabilities for complex SQL queries and advanced analytics.
✨ New Features
📊 Window Functions Support
Advanced analytics with SQL window functions - perfect for rankings, leaderboards, and time-series analysis.
Ranking Functions:
Db::rowNumber()- Sequential row numberingDb::rank()- Rank with gaps for tiesDb::denseRank()- Rank without gapsDb::ntile()- Divide rows into buckets
Value Access Functions:
Db::lag()- Access previous row valuesDb::lead()- Access next row valuesDb::firstValue()- First value in windowDb::lastValue()- Last value in windowDb::nthValue()- Nth value in window
Window Aggregates:
Db::windowAggregate()- Running totals, moving averages
Features:
- Support for
PARTITION BY,ORDER BY, and frame clauses (ROWS BETWEEN) - Cross-database support (MySQL 8.0+, PostgreSQL 9.4+, SQLite 3.25+)
- 11 helper methods in
WindowHelpersTrait - Complete documentation (900+ lines)
- 10 comprehensive use cases in examples
Documentation: documentation/03-query-builder/window-functions.md
Examples: examples/16-window-functions/
🔗 Common Table Expressions (CTEs)
WITH clauses for complex queries and recursive data processing.
Features:
QueryBuilder::with()- Basic CTEsQueryBuilder::withRecursive()- Recursive CTEs for hierarchical data- Support for
Closure,QueryBuilder, or raw SQL - Multiple CTEs with unique parameter scoping
- Explicit column lists for recursive CTEs
- Cross-database support (MySQL 8.0+, PostgreSQL 8.4+, SQLite 3.8.3+)
Use Cases:
- Tree structures (categories, comments, file systems)
- Organizational charts
- Recursive calculations
- Query organization and readability
Documentation: documentation/03-query-builder/cte.md
Examples: examples/17-cte/
🔀 Set Operations
UNION, INTERSECT, and EXCEPT operations for combining query results.
Features:
QueryBuilder::union()- Combine results (removes duplicates)QueryBuilder::unionAll()- Combine results (keeps duplicates)QueryBuilder::intersect()- Common rows in both queriesQueryBuilder::except()- Rows in first but not in second- Support for
ClosureandQueryBuilderinstances - Proper
ORDER BY/LIMIT/OFFSETplacement (SQL standard compliance) - Cross-database: MySQL 8.0+, PostgreSQL, SQLite 3.8.3+
Documentation: documentation/03-query-builder/set-operations.md
Examples: examples/18-set-operations/
🔍 DISTINCT and DISTINCT ON
Remove duplicates from result sets with advanced control.
Features:
QueryBuilder::distinct()- Remove duplicates (all databases)QueryBuilder::distinctOn()- PostgreSQL-specific distinct on columns- Runtime dialect validation with clear exceptions
DialectInterface::supportsDistinctOn()for feature detection
Documentation: documentation/03-query-builder/distinct.md
Examples: Extended examples/01-basic/05-ordering.php
🎯 FILTER Clause for Conditional Aggregates
SQL:2003 standard compliance with automatic dialect translation.
Features:
filter()method chainable after all aggregate functionsDb::count()->filter(...),Db::sum()->filter(...), etc.- Native
FILTER (WHERE ...)clause for PostgreSQL and SQLite 3.30+ - Automatic
CASE WHENfallback for MySQL DialectInterface::supportsFilterClause()for feature detection
Example:
$db->find()
->from('orders')
->select([
'total_orders' => Db::count('*'),
'paid_orders' => Db::count('*')->filter('status', 'paid'),
'pending_amount' => Db::sum('amount')->filter('status', 'pending'),
])
->groupBy('user_id')
->get();Documentation: documentation/03-query-builder/filter-clause.md
Examples: Extended examples/02-intermediate/02-aggregations.php
🧪 Testing
20 new edge-case tests covering critical scenarios:
- Empty result sets
- NULL value handling
- Boundary conditions
- Unsupported feature detection
Total Coverage:
- ✅ 574 tests with 2526 assertions
- ✅ All tests passing on MySQL, PostgreSQL, SQLite
- ✅ 108 examples (36 files × 3 dialects)
📚 Documentation
Added 6 new comprehensive documentation files (2,305+ lines):
- Window Functions (923 lines)
- CTEs (409 lines)
- Set Operations (204 lines)
- DISTINCT (320 lines)
- FILTER Clause (349 lines)
- Window Helpers Reference (550 lines)
🔧 Changes & Fixes
Changed
- Aggregate helpers now return
FilterValueinstead ofRawValueto supportfilter()chaining SelectQueryBuilderInterfaceextended withsetUnions(),setDistinct(),setDistinctOn()- Enhanced parameter management for UNION subqueries
Fixed
- MySQL recursive CTE string concatenation: Fixed test failure using
CONCAT()instead of||operator - All examples now work correctly on all three database dialects
📊 Statistics
- 39 files changed
- 6,507 insertions, 80 deletions
- PHPStan Level 9 (upgraded from Level 8)
- 100% backward compatible - no breaking changes
🔗 Links
- Full Changelog: CHANGELOG.md
- Documentation:
documentation/ - Examples:
examples/ - Comparison: v2.7.0...v2.7.1
📦 Installation
composer require tommyknocker/pdo-database-class:^2.7.1Enjoy building powerful database queries! 🎉