仅在Swift中创建自定义sqlite函数

时间:2015-06-14 02:43:54

标签: ios sqlite swift

如何在Swift中添加自定义sqlite函数?

以下SO问题解决了在涉及坐标的sqlite查询中使用acos和cos等函数的问题: iOS sqlite no such function: ACOS error

建议添加自定义功能。但是这个例子在Objective-C中给出。除了桥接到Objective-C之外,有一个原生的Swift函数或库可以创建自定义函数吗?

2 个答案:

答案 0 :(得分:3)

SQLite.swiftcreating custom SQL functions 提供了一个类型安全的Swift接口(免责声明:我编写并维护了SQLite.swift)。当前版本在内部桥接到Objective-C,尽管这是您可以忽略的实现细节。未来的版本可能会使用Swift 2的函数指针API。虽然可以使用Swift 1.x中的C函数指针与@objc_blockunsafeBitCast一起使用,但读取和维护的情况要差得多。

创建cos函数的最基本方法:

import SQLite
import Darwin

// opens a database connection
let db = Database()

// defines a "cos" function on the connection 
db.create(function: "cos", argc: 1, deterministic: true) { args in
    if let x = args[0] as? Double {
        return Darwin.cos(x)
    }
    return nil
}

println(db.scalar("SELECT cos(1.0)"))
// Optional(0.54030230586813977)

一个更复杂,更安全的示例,其中SQLite.swift在给定合同的情况下为您的数据库生成类型安全的接口:

import SQLite
import Darwin

// opens a database connection
let db = Database()

// defines a "cos" function on the connection 
let cos: Expression<Double> -> Expression<Double> = (
    db.create(function: "cos", deterministic: true, Darwin.cos)
)

// builds a SQL expression for the column, "x"
let x = Expression<Double>("x")

// creates a query reference for the table, "table"
let table = db["table"]

// creates the table
db.create(table: table) { t in
    t.column(x)
}
// CREATE TABLE "table" ("x" REAL)

// inserts a row where "x" is 1.0
table.insert(x <- 1.0)
// INSERT INTO "table" ("x") VALUES (1.0)

// executes the query
for row in db.select(cos(x)) {
    println(row[cos(x)])
}
// SELECT "cos"("x") FROM "table"

答案 1 :(得分:2)

这是Swift 4示例如何将闭包绑定到SQLite函数中,其中1个参数返回大写字符串:

sqlite3_create_function(db, "utf8_upper".cString(using: .utf8), 1, SQLITE_UTF8, nil, { context, argc, arguments in
    let SQLITE_TRANSIENT = unsafeBitCast(-1, to: sqlite3_destructor_type.self)
    let argv = Array(UnsafeBufferPointer(start: arguments, count: Int(argc)))
    let param = String(cString: UnsafePointer(sqlite3_value_text(argv[0])))
    let result = param.uppercased()
    return sqlite3_result_text(context, result, -1, SQLITE_TRANSIENT)
}, nil, nil)