Skip to content

v2.5.0

Choose a tag to compare

@tommyknocker tommyknocker released this 20 Oct 03:58
· 470 commits to master since this release

✨ Major Feature Release

New Features

Connection Pooling

  • Support for initialization without default connection via new PdoDb()
  • Better error messages for uninitialized connections
  • Perfect for microservices and multi-tenant applications

17 New SQL Helper Functions

  • NULL handling: Db::ifNull(), Db::coalesce(), Db::nullIf()
  • Math operations: Db::abs(), Db::round(), Db::mod(), Db::greatest(), Db::least()
  • String operations: Db::upper(), Db::lower(), Db::trim(), Db::length(), Db::substring(), Db::replace()
  • Date/Time extraction: Db::curDate(), Db::curTime(), Db::date(), Db::time(), Db::year(), Db::month(), Db::day(), Db::hour(), Db::minute(), Db::second()

Complete JSON Operations API

  • Db::jsonGet(), Db::jsonLength(), Db::jsonKeys(), Db::jsonType()
  • Unified API across MySQL, PostgreSQL, and SQLite
  • Comprehensive edge-case testing

📚 21 Runnable Examples (NEW!)
Complete, tested examples organized by complexity:

  • Basic: Connection, CRUD, WHERE conditions, INSERT/UPDATE
  • Intermediate: JOINs, aggregations, pagination, transactions
  • Advanced: Connection pooling, bulk operations, UPSERT
  • JSON: Complete JSON operations guide
  • Helpers: String, math, date/time, NULL handling
  • Real-World:
    • Blog system with posts, comments, tags, and analytics
    • User authentication with sessions, RBAC, password hashing
    • Advanced search & filters with facets and pagination
    • Multi-tenant SaaS with resource tracking and quotas

Comprehensive Test Coverage

  • 334 tests, 1499 assertions - ALL PASSING ✅
  • 90%+ code coverage with dialect-specific testing
  • 68 tests in SharedCoverageTest for dialect-independent code
  • 8 new edge-case tests for Db::concat() bug fixes
  • Improved test organization with automatic setUp() cleanup

Utility Scripts

  • scripts/release.sh - Release automation with validation
  • scripts/test-examples.sh - Example verification

Documentation

  • Professional README (1400+ lines)
  • Table of contents, error handling, performance tips
  • Debugging guide and troubleshooting section
  • Complete CHANGELOG from v1.0.3

🐛 Critical Bug Fixes

  • CRITICAL: insertMulti() bulk UPSERT bug: Fixed automatic conflict target determination for PostgreSQL/SQLite ON CONFLICT

    • buildInsertMultiSql() now correctly uses first column when id not present (matches insert() behavior)
    • Enables proper bulk UPSERT operations across all dialects
    • Without this fix, bulk inserts with onDuplicate parameter would fail on PostgreSQL/SQLite
  • CRITICAL: Db::concat() helper bugs (2 major issues fixed):

    • Bug #1: ConcatValue not initializing parent class → "Typed property not initialized" error
      • Fixed with parent::__construct('') and protective getValue() override
    • Bug #2: String literals (spaces, special chars) treated as column names
      • Enhanced auto-detection and quoting for spaces, :, |, -, emoji, unicode
      • Now works: Db::concat('first_name', ' ', 'last_name')
    • Added 8 comprehensive edge-case tests covering all scenarios
  • Restored RawValue support in rawQuery methods

  • Fixed method calls in lock/unlock/loadData/loadXml

  • MySQL EXPLAIN compatibility (table format preservation)

  • PostgreSQL formatSelectOptions (FOR UPDATE/FOR SHARE)

  • SQLite JSON edge cases

🔧 Improvements

  • Enhanced examples: Replaced 30+ raw SQL expressions with Db:: helpers for better readability
    • Db::inc()/Db::dec() for balance transfers and counters
    • Db::count(), Db::sum(), Db::case() for aggregations
    • Db::concat() with automatic string literal handling
  • Better test isolation: Added setUp() method for automatic cleanup
    • Removed 26+ redundant cleanup statements
    • Improved reliability and maintainability
  • Optimized QueryBuilder: Refactored with helper methods
  • Clearer error messages: Better guidance for common issues

🗑️ Removed (Non-Breaking)

Deprecated helper methods from PdoDb (~130 lines):

  • inc(), dec(), not() → Use Db:: equivalents
  • escape() → Use prepared statements
  • tableExists() → Use QueryBuilder::tableExists()
  • now() → Use Db::now()
  • loadData(), loadXml() → Use QueryBuilder::loadCsv(), QueryBuilder::loadXml()

📝 Technical Details

  • Backward compatible: Zero breaking changes
  • PHP 8.4+ required (property hooks, union types, match expressions)
  • 90%+ test coverage with comprehensive edge-case testing
  • All 21 examples tested and verified on PHP 8.4.13
  • Full CHANGELOG: See CHANGELOG.md

🚀 Quick Start

composer require tommyknocker/pdo-database-class

# Try examples
cd vendor/tommyknocker/pdo-database-class/examples
cp config.example.php config.php
php 01-basic/01-connection.php
php 06-real-world/02-user-auth.php
php 06-real-world/03-search-filters.php

📖 Resources