feat: ListQuery filter operators and multi-column ordering - #71
Open
KapplerJulien wants to merge 1 commit into
Open
feat: ListQuery filter operators and multi-column ordering#71KapplerJulien wants to merge 1 commit into
KapplerJulien wants to merge 1 commit into
Conversation
Plural DataViews over DatabaseModuleStorage could only express equality filters and a single ORDER BY column, so downstream plugins kept hand-written SQL read models next to the DataView. - New Tangible\DataObject\Filter: equals, not_equals, in, is_null, is_not_null, less_than, at_most, greater_than, at_least. matches() defines the reference semantics; compare() is the shared ordering rule. - ListQuery filters accept a scalar (equality, unchanged), an array (IN) or a Filter; constraints() returns the normalized map. $filters is left as given so existing readers keep working. - ListQuery orderby accepts an array of field => direction pairs (or a list sharing $order), exposed as $ordering; $orderby/$order stay the first key. - DatabaseModuleStorage translates each operator into prepared SQL and emits one ORDER BY term per key, keeping NULL rows where the in-memory rule keeps them. A bare null filter value still means loose equality with '', not IS NULL. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
KapplerJulien
marked this pull request as ready for review
September 10, 2026 14:15
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Plural DataViews backed by
DatabaseModuleStoragecan only express equality filters and a singleORDER BYcolumn throughListQuery. Real listings need a little more: "current rows only" (superseded_by IS NULL), a stable secondary sort,INlists, and range comparisons. Without them, downstream plugins keep hand-written SQL read models next to the DataView instead of aPluralObjectover the TDB table.What
Tangible\DataObject\Filter(new): a constraint value object withequals,not_equals,in,is_null,is_not_null,less_than,at_most,greater_than,at_least.Filter::matches()defines the reference semantics;Filter::compare()is the shared numeric-or-case-insensitive comparison rule that ordering already used.ListQuery::$filtersaccepts a scalar (equality, unchanged), an array (shorthand forIN) or aFilter.constraints()returns the normalizedFiltermap for storages.$filtersitself is left exactly as given, so existing readers such as(string) $query->filters['type']keep working.ListQueryordering:orderbyaccepts a string (unchanged) or an array, eitherfield => 'asc'|'desc'pairs or a list of fields sharing$order. The full ordering is exposed as$ordering;$orderby/$orderstay as the first key for single-column consumers.DatabaseModuleStoragetranslates every operator into prepared SQL and emits oneORDER BYterm per ordering key. NULL handling follows the in-memory rule:<>against a non-empty value and</<=keep NULL rows, since a stored null stringifies to''and sorts before every value there.Compatibility
No behaviour change for existing queries: a bare
nullfilter value still means loose equality with'', notIS NULL.RequestRouter,PluralHandlerandPluralObjectare untouched; the in-memory fallback and the SQL path agree on every new scenario (see the extended parity test).Tests
ListQuery_TestCasegains 13 tests: shorthand normalization, each operator's null and loose-equality edge cases,ANDcombination, multi-column ordering (array and list forms, blank/duplicate keys, unknown keys falling through) and 14 new SQL-vs-in-memory parity scenarios on a TDB table with a nullable column.Ran locally against wordpress-develop with database-module loaded: the full suite shows the same 17 errors / 1 failure as
main(Tangible Fields framework not loaded in this environment); every ListQuery and DatabaseModuleStorage test passes.🤖 Generated with Claude Code