如何在SQLite.swift中创建Type-Safe自定义函数?

时间:2015-10-06 23:15:45

标签: ios sqlite swift2 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)
}

但是我想在不使用查询字符串的情况下使用Type-Safe SQL Expression。 如何添加一个能够使它像这样工作的函数(这里lat和lon值是表示表中行和centerLat的位置的表达式值,centerLon值表示I'的中心点。 m计算物体的距离):

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

2 个答案:

答案 0 :(得分:0)

目前还没有好办法(许多表达式构建帮助程序现在都是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
    )
}

答案 1 :(得分:0)

当前文档为此问题提供了希望。但是,我无法使用多个参数来编译示例代码(上下文闭包类型'([Binding?]) - &gt; 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