The REPL particularly hates this. This does mean, however, that `step()`
needs to live on the statement itself, not the cursor.

In fact, cursor may be better accessed as `row`, so let's do just that:

    while stmt.step() {
        let id = stmt.row[0] as Int
        // ...
    }

Signed-off-by: Stephen Celis <stephen@stephencelis.com>
This commit is contained in:
Stephen Celis 2015-03-03 12:01:20 -08:00
Родитель 76ad0d8733
Коммит 3df3ed734b
2 изменённых файлов: 26 добавлений и 23 удалений

Просмотреть файл

@ -172,13 +172,13 @@ class StatementTests: XCTestCase {
XCTAssertEqual(6, count)
}
func test_cursor_returnsValues() {
func test_row_returnsValues() {
InsertUser(db, "alice")
let stmt = db.prepare("SELECT id, email FROM users")
stmt.cursor.step()
stmt.step()
XCTAssertEqual(Int64(1), stmt.cursor[0] as Int64)
XCTAssertEqual("alice@example.com", stmt.cursor[1] as String)
XCTAssertEqual(Int64(1), stmt.row[0] as Int64)
XCTAssertEqual("alice@example.com", stmt.row[1] as String)
}
}

Просмотреть файл

@ -32,7 +32,7 @@ public final class Statement {
private let database: Database
public lazy var cursor: Cursor = { Cursor(self) }()
public lazy var row: Cursor = { Cursor(self) }()
internal init(_ database: Database, _ SQL: String) {
self.database = database
@ -115,7 +115,7 @@ public final class Statement {
public func run(bindings: Binding?...) -> Statement {
if !bindings.isEmpty { return run(bindings) }
reset(clearBindings: false)
while cursor.step() {}
while step() {}
return self
}
@ -142,8 +142,8 @@ public final class Statement {
public func scalar(bindings: Binding?...) -> Binding? {
if !bindings.isEmpty { return scalar(bindings) }
reset(clearBindings: false)
cursor.step()
return cursor[0]
step()
return row[0]
}
/// :param: bindings A list of parameters to bind to the statement.
@ -163,6 +163,11 @@ public final class Statement {
// MARK: -
public func step() -> Bool {
try(sqlite3_step(handle))
return status == SQLITE_ROW
}
private func reset(clearBindings: Bool = true) {
(status, reason) = (SQLITE_OK, nil)
sqlite3_reset(handle)
@ -209,7 +214,7 @@ extension Statement: GeneratorType {
/// :returns: The next row from the result set (or nil).
public func next() -> [Binding?]? {
return cursor.step() ? Array(cursor) : nil
return step() ? Array(row) : nil
}
}
@ -236,33 +241,31 @@ public func || (lhs: Statement, rhs: @autoclosure () -> Statement) -> Statement
/// Cursors provide direct access to a statement's current row.
public struct Cursor {
private unowned let statement: Statement
private let handle: COpaquePointer
private let columnCount: Int
private init(_ statement: Statement) {
self.statement = statement
}
public func step() -> Bool {
statement.try(sqlite3_step(statement.handle))
return statement.status == SQLITE_ROW
handle = statement.handle
columnCount = statement.columnCount
}
public subscript(idx: Int) -> Blob {
let bytes = sqlite3_column_blob(statement.handle, Int32(idx))
let length = sqlite3_column_bytes(statement.handle, Int32(idx))
let bytes = sqlite3_column_blob(handle, Int32(idx))
let length = sqlite3_column_bytes(handle, Int32(idx))
return Blob(bytes: bytes, length: Int(length))
}
public subscript(idx: Int) -> Double {
return sqlite3_column_double(statement.handle, Int32(idx))
return sqlite3_column_double(handle, Int32(idx))
}
public subscript(idx: Int) -> Int64 {
return sqlite3_column_int64(statement.handle, Int32(idx))
return sqlite3_column_int64(handle, Int32(idx))
}
public subscript(idx: Int) -> String {
return String.fromCString(UnsafePointer(sqlite3_column_text(statement.handle, Int32(idx)))) ?? ""
return String.fromCString(UnsafePointer(sqlite3_column_text(handle, Int32(idx)))) ?? ""
}
public subscript(idx: Int) -> Bool {
@ -279,7 +282,7 @@ public struct Cursor {
extension Cursor: SequenceType {
public subscript(idx: Int) -> Binding? {
switch sqlite3_column_type(statement.handle, Int32(idx)) {
switch sqlite3_column_type(handle, Int32(idx)) {
case SQLITE_BLOB:
return self[idx] as Blob
case SQLITE_FLOAT:
@ -298,7 +301,7 @@ extension Cursor: SequenceType {
public func generate() -> GeneratorOf<Binding?> {
var idx = 0
return GeneratorOf<Binding?> {
idx >= self.statement.columnCount ? Optional<Binding?>.None : self[idx++]
idx >= self.columnCount ? Optional<Binding?>.None : self[idx++]
}
}