Add custom function support to predicates and sort descriptors#22
Merged
Conversation
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.
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.
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.propertyor a.functionresult. A compatibilityinit(property:ascending:)and a.propertyaccessor keep all existing call sites source-compatible.DatabaseFunction— a value type carryingname,argumentCount,deterministic, and a backend-agnosticevaluate: ([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.functiontoNSExpression(forFunction:).CoreData's actual in-memory evaluation of
.functionpredicates/sorts is deferred to a follow-up; this PR establishes the abstract API and wiring.Testing
DatabaseFunctionTestscoveringCodableround-trips of the new expression/sort cases, theevaluateclosure, and the compatibility initializer.