Add custom SQL function support#7
Merged
Merged
Conversation
Register custom scalar functions with a SQLite store and invoke them from predicates and sort descriptors, plus a raw-SQL escape hatch for app-managed virtual tables (e.g. R*Tree). - SQLiteDatabase/SQLiteViewContext.register(function:) bridges a DatabaseFunction to Connection.createFunction, converting between AttributeValue and SQLite Binding at the boundary. - SQLiteDatabase.execute(_:_:) runs raw SQL so apps can create and maintain their own virtual tables; the library never creates or syncs them itself. - Predicate.swift compiles .function expressions to SQL function calls in WHERE clauses; Database.swift emits them in ORDER BY.
The custom function API landed in CoreModel 2.8.0, so depend on the release instead of the local path override.
- matchesInMemorySwiftFilterAndSort: verifies the SQL distance function produces the same filtered set and sort order as filtering/sorting the same 200-point dataset in Swift. - appManagedRTreePrefilter: demonstrates the app-managed R*Tree pattern — the app creates an rtree virtual table + sync triggers via execute(), uses it as a bounding-box prefilter, then applies the exact distance function; result matches a brute-force oracle and the prefilter is sound. Gate the custom-function tests to Apple platforms and document the limit: SQLite.swift's createFunction is unreliable on non-Apple platforms and segfaults on Linux (upstream stephencelis/SQLite.swift#1071).
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 support for registering custom scalar SQL functions with a SQLite-backed store and invoking them from predicates and sort descriptors, plus a raw-SQL escape hatch for app-managed virtual tables (e.g. RTree). The motivating use case is efficient GPS distance filtering/sorting — an app registers a
distancefunction and, if it wants spatial indexing, sets up its own RTree table viaexecute— but nothing here is geo-specific.Changes
register(function:)onSQLiteDatabaseandSQLiteViewContext— bridges aDatabaseFunction(from CoreModel) toConnection.createFunction, converting betweenAttributeValueand SQLiteBindingat the boundary and invoking the registered closure inside the SQLite callback. Registration is per-connection, so the same function must be registered on both a database and its paired view context.SQLiteDatabase.execute(_:_:)— runs raw SQL against the underlying connection so apps canCREATE VIRTUAL TABLE ... USING rtree(...)and keep it in sync themselves (e.g. via triggers). The library never creates, syncs, or knows about any virtual table itself.Predicate.swift— compiles.functionexpressions to real SQL function calls (name(args...)) inWHEREclauses, with arguments compiled recursively (columns, constants, or nested calls).Database.swift— the ORDER BY builder emits.functionsort terms the same way, appending bindings in positional order.Testing
New
CustomFunctionTestsregister a Haversinedistancefunction (defined in the test, not the library) and verify:.functionpredicate against an independently computed brute-force oracle,.functionsort term,fetchLimit,SQLiteViewContext,Full suite passes locally (56 tests).
Dependency note
This depends on the new
DatabaseFunction/Expression.function/SortDescriptor.termAPI in CoreModel PR #22 (feature/functionsbranch), which is not yet in a released tag. CI will not pass until that PR merges and a new CoreModel release is tagged, at which pointPackage.swiftshould be bumped to that version.