如何在 SQLite.swift 中创建类型安全的自定义函数?
How to create a Type-Safe custom function in SQLite.swift?
我想创建一个简单的距离函数来对从 Swift2 中的 SQLite 数据库中获取的对象进行排序。
我正在使用很棒的 SQLite.swift 框架。
通过以下我可以获取最近的对象:
db.createFunction("distance") { (args) -> Binding? in
assert(args.count == 4)
if let lat1 = args[0] as? Double, let lon1 = args[1] as? Double, let lat2 = args[2] as? Double, let lon2 = args[3] as? Double {
let deltaLat = lat1 - lat2
let deltaLon = lon1 - lon2
return deltaLat * deltaLat + deltaLon * deltaLon * 0.46512281898705
}
return nil
}
let queryString = "SELECT * FROM objects where lat != \"\" and lng != \"\" ORDER BY distance(lat, lng, \(lat), \(lng)) ASC LIMIT \(fetchLimit)"
let stmt = db.prepare(queryString)
for row in stmt {
print(row)
}
但我想在不使用查询字符串的情况下使用类型安全 SQL 表达式。
我怎样才能添加一个函数才能让它像这样工作(这里的lat和lon值是表示行在table和centerLat中的位置的表达式值,centerLon值表示中心点来自哪里我正在计算物体的距离):
for row in db.order(distance(lat, lon, centerLat, centerLon).limit(fetchLimit) {
print(row)
}
目前还没有好的方法(许多表达式构建助手现在是 SQLite.swift 内部的)。我鼓励您将问题作为功能请求打开。
同时,因为这些是不需要引用的值,您可以执行以下操作:
func distance(
lat1: Expression<Double>, lng1: Expression<Double>,
lat2: Double, lng2: Double
) -> Expression<Double> {
return Expression(
literal: "distance(\(lat1.asSQL()), \(lng1.asSQL()), ?, ?)",
lat2, lng2
)
}
当前的文档为这个问题带来了希望。但是,我无法使用多个参数编译示例代码(上下文闭包类型'([Binding?])-> Binding?'需要1个参数,但闭包主体中使用了2个), 应该可以:
import MobileCoreServices
let typeConformsTo: (Expression<String>, String) -> Expression<Bool> = (
try db.createFunction("typeConformsTo", deterministic: true) { UTI, conformsToUTI in
return UTTypeConformsTo(UTI, conformsToUTI)
}
)
https://github.com/stephencelis/SQLite.swift/blob/master/Documentation/Index.md#custom-sql-functions
我想创建一个简单的距离函数来对从 Swift2 中的 SQLite 数据库中获取的对象进行排序。 我正在使用很棒的 SQLite.swift 框架。
通过以下我可以获取最近的对象:
db.createFunction("distance") { (args) -> Binding? in
assert(args.count == 4)
if let lat1 = args[0] as? Double, let lon1 = args[1] as? Double, let lat2 = args[2] as? Double, let lon2 = args[3] as? Double {
let deltaLat = lat1 - lat2
let deltaLon = lon1 - lon2
return deltaLat * deltaLat + deltaLon * deltaLon * 0.46512281898705
}
return nil
}
let queryString = "SELECT * FROM objects where lat != \"\" and lng != \"\" ORDER BY distance(lat, lng, \(lat), \(lng)) ASC LIMIT \(fetchLimit)"
let stmt = db.prepare(queryString)
for row in stmt {
print(row)
}
但我想在不使用查询字符串的情况下使用类型安全 SQL 表达式。 我怎样才能添加一个函数才能让它像这样工作(这里的lat和lon值是表示行在table和centerLat中的位置的表达式值,centerLon值表示中心点来自哪里我正在计算物体的距离):
for row in db.order(distance(lat, lon, centerLat, centerLon).limit(fetchLimit) {
print(row)
}
目前还没有好的方法(许多表达式构建助手现在是 SQLite.swift 内部的)。我鼓励您将问题作为功能请求打开。
同时,因为这些是不需要引用的值,您可以执行以下操作:
func distance(
lat1: Expression<Double>, lng1: Expression<Double>,
lat2: Double, lng2: Double
) -> Expression<Double> {
return Expression(
literal: "distance(\(lat1.asSQL()), \(lng1.asSQL()), ?, ?)",
lat2, lng2
)
}
当前的文档为这个问题带来了希望。但是,我无法使用多个参数编译示例代码(上下文闭包类型'([Binding?])-> Binding?'需要1个参数,但闭包主体中使用了2个), 应该可以:
import MobileCoreServices
let typeConformsTo: (Expression<String>, String) -> Expression<Bool> = (
try db.createFunction("typeConformsTo", deterministic: true) { UTI, conformsToUTI in
return UTTypeConformsTo(UTI, conformsToUTI)
}
)
https://github.com/stephencelis/SQLite.swift/blob/master/Documentation/Index.md#custom-sql-functions