1

我想创建一个简单的距离函数来排序对象,同时从 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 值是 Expression 值,表示表中行的位置和 centerLat,centerLon 值表示我正在计算的中心点物体的距离):

for row in db.order(distance(lat, lon, centerLat, centerLon).limit(fetchLimit) {
    print(row)
}
4

2 回答 2

1

目前还没有很好的方法来做到这一点(许多表达式构建助手现在是 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
    )
}
于 2015-10-14T00:47:52.393 回答
0

当前的文档为这个问题带来了希望。但是,我无法使用多个参数编译示例代码(上下文闭包类型 '([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/stephenencelis/SQLite.swift/blob/master/Documentation/Index.md#custom-sql-functions

于 2017-01-09T19:00:17.037 回答