分析表SQL语句构建过程
分析动态构建表
需要实现两个功能:
提供绑定数据方法
提供一个类,封装整个SQL的管理:绑定、转换,包括swift到数据库及其方向的操作。
public final class Statement {
fileprivate var handle: OpaquePointer? = nil
fileprivate let connection: Connection
init(_ connection: Connection, _ SQL: String) throws {
self.connection = connection
try connection.check(sqlite3_prepare_v2(connection.handle, SQL, -1, &handle, nil))
}
deinit {
sqlite3_finalize(handle)
}
第二步:绑定数据 =>提供原始绑定方法
fileprivate func bind(_ value: Binding?, atIndex idx: Int) {
if value == nil {
sqlite3_bind_null(handle, Int32(idx))
} else if let value = value as? String {
sqlite3_bind_text(handle, Int32(idx), value, -1, SQLITE_TRANSIENT)
} else if let value = value {
fatalError("tried to bind unexpected value \(value)")
}
}
绑定方法重载=>循环遍历
fileprivate func reset(clearBindings shouldClear: Bool = true) {
sqlite3_reset(handle)
if (shouldClear) {
sqlite3_clear_bindings(handle)
}
}
public func bind(_ values: [String: Binding?]) -> Statement {
reset()
for (name, value) in values {
let idx = sqlite3_bind_parameter_index(handle, name)
guard idx > 0 else {
fatalError("parameter not found: \(name)")
}
bind(value, atIndex: Int(idx))
}
return self
}
绑定方法重载->提供默认方法(抽象公共功能)
public func bind(_ values: [Binding?]) -> Statement {
if values.isEmpty {
return self
}
reset()
guard values.count == Int(sqlite3_bind_parameter_count(handle)) else {
fatalError("\(sqlite3_bind_parameter_count(handle)) values expected, \(values.count) passed")
}
for idx in 1...values.count {
bind(values[idx - 1], atIndex: idx)
}
return self
}
public func bind(_ values: Binding?...) -> Statement {
return bind(values)
}
执行SQL语句
public func step() throws -> Bool {
return try connection.sync {
try self.connection.check(sqlite3_step(self.handle)) == SQLITE_ROW
}
}
@discardableResult public func run(_ bindings: [Binding?]) throws -> Statement {
return try bind(bindings).run()
}
@discardableResult public func run(_ bindings: [String: Binding?]) throws -> Statement {
return try bind(bindings).run()
}
@discardableResult public func run(_ bindings: Binding?...) throws -> Statement {
guard bindings.isEmpty else {
return try run(bindings)
}
reset(clearBindings: false)
repeat {} while
try step()
return self
}
为Connection提供接口
为了方便客户端调用,对已有的一些接口集中到Connection重载:
prepare重载
public func prepare(_ statement: String, _ bindings: Binding?...) throws -> Statement {
if !bindings.isEmpty {
return try prepare(statement, bindings)
}
return try Statement(self, statement)
}
public func prepare(_ statement: String, _ bindings: [Binding?]) throws -> Statement {
return try prepare(statement).bind(bindings)
}
public func prepare(_ statement: String, _ bindings: [String: Binding?]) throws -> Statement {
return try prepare(statement).bind(bindings)
}
run重载
@discardableResult public func run(_ statement: String, _ bindings: Binding?...) throws -> Statement {
return try run(statement, bindings)
}
@discardableResult public func run(_ statement: String, _ bindings: [Binding?]) throws -> Statement {
return try prepare(statement).run(bindings)
}
@discardableResult public func run(_ statement: String, _ bindings: [String: Binding?]) throws -> Statement {
return try prepare(statement).run(bindings)
}
|