如何在 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