Skip to content

Commit 5a9b583

Browse files
committed
Introduce FailableIterator
1 parent 28e2cfa commit 5a9b583

File tree

3 files changed

+48
-40
lines changed

3 files changed

+48
-40
lines changed

Sources/SQLite/Core/Statement.swift

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -191,14 +191,6 @@ public final class Statement {
191191

192192
}
193193

194-
extension Statement {
195-
196-
func rowCursorNext() throws -> [Binding?]? {
197-
return try step() ? Array(row) : nil
198-
}
199-
200-
}
201-
202194
extension Statement : Sequence {
203195

204196
public func makeIterator() -> Statement {
@@ -208,12 +200,38 @@ extension Statement : Sequence {
208200

209201
}
210202

211-
extension Statement : IteratorProtocol {
203+
public protocol FailableIterator : IteratorProtocol {
204+
func failableNext() throws -> Self.Element?
205+
}
212206

213-
public func next() -> [Binding?]? {
214-
return try! step() ? Array(row) : nil
207+
extension FailableIterator {
208+
public func next() -> Element? {
209+
return try! failableNext()
215210
}
216211

212+
public func map<T>(_ transform: (Element) throws -> T) throws -> [T] {
213+
var elements = [T]()
214+
while let row = try failableNext() {
215+
elements.append(try transform(row))
216+
}
217+
return elements
218+
}
219+
}
220+
221+
extension Array {
222+
public init<I: FailableIterator>(_ failableIterator: I) throws where I.Element == Element {
223+
self.init()
224+
while let row = try failableIterator.failableNext() {
225+
append(row)
226+
}
227+
}
228+
}
229+
230+
extension Statement : FailableIterator {
231+
public typealias Element = [Binding?]
232+
public func failableNext() throws -> [Binding?]? {
233+
return try step() ? Array(row) : nil
234+
}
217235
}
218236

219237
extension Statement : CustomStringConvertible {

Sources/SQLite/Typed/Query.swift

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -894,35 +894,19 @@ public struct Delete : ExpressionType {
894894

895895
}
896896

897-
public struct RowCursor {
897+
898+
public struct RowCursor: FailableIterator {
899+
public typealias Element = Row
898900
let statement: Statement
899901
let columnNames: [String: Int]
900-
901-
public func next() throws -> Row? {
902-
return try statement.rowCursorNext().flatMap { Row(columnNames, $0) }
903-
}
904-
905-
public func map<T>(_ transform: (Row) throws -> T) throws -> [T] {
906-
var elements = [T]()
907-
while true {
908-
if let row = try next() {
909-
elements.append(try transform(row))
910-
} else {
911-
break
912-
}
913-
}
914-
915-
return elements
902+
903+
public func failableNext() throws -> Row? {
904+
return try statement.failableNext().flatMap { Row(columnNames, $0) }
916905
}
917906
}
918907

908+
919909
extension Connection {
920-
921-
public func prepareCursor(_ query: QueryType) throws -> RowCursor {
922-
let expression = query.expression
923-
let statement = try prepare(expression.template, expression.bindings)
924-
return RowCursor(statement: statement, columnNames: try columnNamesForQuery(query))
925-
}
926910

927911
public func prepare(_ query: QueryType) throws -> AnySequence<Row> {
928912
let expression = query.expression
@@ -935,6 +919,12 @@ extension Connection {
935919
}
936920
}
937921

922+
public func prepareRowCursor(_ query: QueryType) throws -> RowCursor {
923+
let expression = query.expression
924+
let statement = try prepare(expression.template, expression.bindings)
925+
return RowCursor(statement: statement, columnNames: try columnNamesForQuery(query))
926+
}
927+
938928
private func columnNamesForQuery(_ query: QueryType) throws -> [String: Int] {
939929
var (columnNames, idx) = ([String: Int](), 0)
940930
column: for each in query.clauses.select.columns {
@@ -1002,7 +992,7 @@ extension Connection {
1002992
}
1003993

1004994
public func pluck(_ query: QueryType) throws -> Row? {
1005-
return try prepareCursor(query.limit(1, query.clauses.limit?.offset)).next()
995+
return try prepareRowCursor(query.limit(1, query.clauses.limit?.offset)).failableNext()
1006996
}
1007997

1008998
/// Runs an `Insert` query.

Tests/SQLiteTests/QueryTests.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -343,14 +343,14 @@ class QueryIntegrationTests : SQLiteTestCase {
343343
_ = user[users[managerId]]
344344
}
345345
}
346-
347-
func test_prepareCursor() {
346+
347+
func test_prepareRowCursor() {
348348
let names = ["a", "b", "c"]
349349
try! InsertUsers(names)
350-
350+
351351
let emailColumn = Expression<String>("email")
352-
let emails = try! db.prepareCursor(users).map { $0[emailColumn] }
353-
352+
let emails = try! db.prepareRowCursor(users).map { $0[emailColumn] }
353+
354354
XCTAssertEqual(names.map({ "\($0)@example.com" }), emails.sorted())
355355
}
356356

0 commit comments

Comments
 (0)