Changes for version 0.63 - 2026-02-27

  • BUG FIXES
    • delete() on a ResultSet with group_by and/or having would cause DBIx::Class to generate a DELETE subquery with GROUP BY silently stripped, producing invalid SQL that most databases reject. Fixed by detecting group_by/having, building a clean copy of the attrs with those keys removed, and re-fetching matching PKs via a plain WHERE search before issuing delete_all().
    • Fixed delete() attribute routing: the previous guard triggered the two-query delete_all() path whenever the ResultSet had any attribute at all, including harmless ones such as result_class, order_by, and prefetch, causing unnecessary extra queries. The check is now restricted to the six attributes that genuinely make a direct DELETE unsafe: rows, offset, and page (LIMIT/OFFSET), join (multi-table DELETE), and group_by/having (see above). ResultSets carrying only ordering or prefetch attributes now issue a direct single-query DELETE.
  • ENHANCEMENTS
    • SelectNormaliser is now applied automatically inside search() after attribute merging and before the new ResultSet is constructed. Any { -ident => $col, -as => $alias } items in the select list are rewritten to bare column strings at this point, so every downstream operation flowing through search() -- all, count, count_total, update, and so on -- receives clean attributes without requiring individual normalisation calls at each call site.
  • TESTS
    • Added t/154-grouped-delete.t covering delete() on ResultSets with group_by, having, rows (LIMIT), and join, plus a regression guard for plain ungrouped delete. Tests use a live SQLite database via the standard TestSchema fixture.
    • Added t/155-select-normaliser.t covering _is_ident_hashref classification, all normalise() input forms (bare strings, -ident with and without -as, function hashrefs, literal SQL refs, mixed lists, scalar and hashref non-array inputs), as/select length mismatches, normalise_attrs() key preservation and no-mutation guarantee, and a structural proof that the normalised output contains no -ident hashrefs. No live database required.

Modules

Non-blocking, multi-worker asynchronous wrapper for DBIx::Class
Base class for DBIx::Class::Async exceptions
Exception for column names that are ambiguous across joined tables
Translate raw DBIx::Class errors into typed exception objects
Exception for absent required columns on insert
Exception for undeclared relationship names used in queries
Exception for operations on un-inserted row objects
Exception for relationship name passed where a column was expected
Non-blocking resultset proxy with Future-based execution
Asynchronous pagination handling for Async ResultSets
Asynchronous operations on a single ResultSource column
Asynchronous Row object representing a single database record.
Non-blocking, worker-pool based Proxy for DBIx::Class::Schema
Normalise -ident clauses in ResultSet select attributes
Storage Layer for DBIx::Class::Async
DBI-based async storage backend for DBIx::Class::Async
Asynchronous cursor for DBIx::Class ResultSets using Futures