Parsing Swift Predicates into Database Statements with PredicateExpressions - Stack Overflow
Context
I am attempting to take a Swift Predicate created with the #Predicate
macro and parse it into a database query statement. (SwiftData does this under the hood to query the underlying SQLite database that powers Core Data).
Example:
class Foo
{
var title: String = ""
}
let p = #Predicate<Foo> { $0.title == "test" }
Given that predicate, p
, I want to turn it into this string-ified query statement:
SELECT * FROM `Foo` WHERE `title` = "test"
Question
The process for doing this is very sparsely documented. I'm following that example by declaring a custom protocol and then having each type of PredicateExpression
that I support adopt that protocol. (This code is very proof-of-concept at the moment; it ignores errors and handles only this very simple Predicate for now):
protocol DBPredicateExpression {
func dbQuery() -> String
}
// Handle the "==" operator
extension PredicateExpressions.Equal: DBPredicateExpression where LHS: DBPredicateExpression, RHS: DBPredicateExpression
{
func dbQuery() -> String {
return lhs.dbQuery() + " = " + rhs.dbQuery()
}
}
// Handle constant values
extension PredicateExpressions.Value: DBPredicateExpression
{
func dbQuery() -> String {
if let v = value as? String {
return "\"\(v)\""
}
return "" // TODO: handle other value types; throw for unsupported ones.
}
}
// Handle KeyPaths
extension PredicateExpressions.Keypath: DBPredicateExpression
{
func dbQuery() -> String
{
let rootType: Any.Type = type(of: root) // String(describing:) --> Variable<Foo>
let kpType: Any.Type = type(of: keyPath) // String(describing:) --> ReferenceWritableKeyPath<Foo, String>
// THIS IS WHERE I NEED HELP.
// How do I introspect `root` and `keyPath` to get string versions of them?
// This should return: "FROM `Foo` WHERE `title`"
// But getting "Foo" and "title" from `root` and `keyPath` is the tricky bit.
}
}
As stated in the comment: how do I transform the KeyPath
and Root
types into their String
equivalents (title
and Foo
)? Using string(describing:)
seems very fragile and non-performant. How does SwiftData take one of these KeyPath Predicates and transform it into the SQL statements that ultimately get run in Core Data?
- 微软为何仍在打造硬件 听纳德拉怎么说
- 谷歌加入硬件战场:正面对抗亚马逊和苹果
- reactjs - The difference between @Vite4 and @Vite5 - Stack Overflow
- python - How to solve this TensorflowTensorboard compatibility problem? - Stack Overflow
- typescript - Not able to make firstValueFromasync work with Angular - Stack Overflow
- powershell - Questionable output while iterating over an array of arrays - Stack Overflow
- pytorch - Why can't my DDPG solve MountainCarContinuous-v0 - Stack Overflow
- macos - Can't access UI "section" in AppleScript - Stack Overflow
- python - hydra submitit launcher plugin fails to import modules that can be imported normally when omitting the plugin - Stack O
- flutter - Error handshake exception: handshake error in client(os error: certificate _verify_failed: unable to get local issuer
- x86 - how does internal functions of kernel resolve after paging? - Stack Overflow
- python - Can't run pytest with a `FileNotFoundError: [Errno 2] No such file or directory: 'tmppip-build-env-3fag
- python - CERT_PATH points to the wrong directory even though I set it correctly in my Django project - Stack Overflow
- python - Could NOT find Python3 during cmake - Stack Overflow
- arrays - Visual Studio 2022 - Fortran - Debugging Issue - Stack Overflow
- using Okta principal groups and metadata in Spring Boot with Okta Spring Boot - Stack Overflow
- spring boot - Hibernate search backend elastic search with multiple data bases - Stack Overflow