Skip to content

Add custom function support to predicates and sort descriptors#22

Merged
colemancda merged 3 commits into
masterfrom
feature/functions
Jul 16, 2026
Merged

Add custom function support to predicates and sort descriptors#22
colemancda merged 3 commits into
masterfrom
feature/functions

Conversation

@colemancda

@colemancda colemancda commented Jul 16, 2026

Copy link
Copy Markdown
Member

Summary

Adds a generic function-call mechanism to the abstract query model so predicates and sort descriptors can invoke named functions registered with a store.

Fixes #21.

Changes

  • Expression.function(FunctionExpression) — a new generic { name: String, arguments: [Expression] } call expression (Expression.swift, FunctionExpression.swift). Any comparison against a function's result uses the existing operators, e.g. myFn(a, b) <= x.
  • SortDescriptor.term: SortTerm — sort descriptors can now sort by either a plain .property or a .function result. A compatibility init(property:ascending:) and a .property accessor keep all existing call sites source-compatible.
  • DatabaseFunction — a value type carrying name, argumentCount, deterministic, and a backend-agnostic evaluate: ([AttributeValue?]) -> AttributeValue? closure.
  • ModelStorage.register(function:) — a new protocol requirement, implemented by all existing conformers. A SQL-backed store can execute the function natively; CoreData records it for in-memory evaluation and maps .function to NSExpression(forFunction:).

CoreData's actual in-memory evaluation of .function predicates/sorts is deferred to a follow-up; this PR establishes the abstract API and wiring.

Testing

  • New DatabaseFunctionTests covering Codable round-trips of the new expression/sort cases, the evaluate closure, and the compatibility initializer.
  • Full suite passes (21 tests).

Introduce a generic function-call expression so predicates and sort
descriptors can invoke named functions registered with a store, and add
a cross-backend registration API for those functions.

- Add FetchRequest.Predicate.Expression.function(FunctionExpression),
  a generic {name, arguments} call expression.
- Add FetchRequest.SortDescriptor.term (SortTerm: .property/.function)
  so results can be sorted by a function result, keeping a compatibility
  init(property:ascending:) and .property accessor for existing callers.
- Add DatabaseFunction (name, argumentCount, deterministic, evaluate)
  and a ModelStorage.register(function:) requirement, implemented by all
  existing conformers. CoreData records functions for later in-memory
  evaluation and maps .function to NSExpression(forFunction:).
Use NSManagedObjectContext.userInfo, the dictionary CoreData provides for
associating custom data with a context, instead of objc associated objects.
CoreData can't run custom functions in a native fetch, so a fetch whose
predicate or sort references a .function expression is split: a superset is
fetched natively (function comparisons replaced with TRUE, function sorts and
limit/offset dropped), then filtered, sorted, and paginated in memory using
the registered functions.

Adds a test registering a function on the CoreData backend and using it to
filter and sort a collection of people by name.
@colemancda colemancda merged commit a10fece into master Jul 16, 2026
31 checks passed
@colemancda colemancda deleted the feature/functions branch July 16, 2026 17:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for SQLite functions

1 participant