@@ -28,19 +28,40 @@ public extension SQLStatement {
28
28
}
29
29
return objects
30
30
}
31
+
32
+ /// Fetches the next row as `SQLRow`.
33
+ func row( ) throws -> SQLRow ? {
34
+ guard try step ( ) else {
35
+ return nil
36
+ }
37
+ return SQLRow ( statement: self )
38
+ }
39
+
40
+ /// Fetches the first `count` rows as `SQLRow`s returned by the statement. By default,
41
+ /// fetches all rows.
42
+ func rows( count: Int ? = nil ) throws -> [ SQLRow ] {
43
+ var objects = [ SQLRow] ( )
44
+ let limit = count ?? Int . max
45
+ if let count = count {
46
+ objects. reserveCapacity ( count)
47
+ }
48
+ while let object = try row ( ) , objects. count < limit {
49
+ objects. append ( object)
50
+ }
51
+ return objects
52
+ }
31
53
}
32
54
33
55
/// Represents a single row returned by the SQL statement.
34
- ///
35
- /// - warning: This is a leaky abstraction. This is not a real value type, it
36
- /// just wraps the underlying statement. If the statement moves to the next
37
- /// row by calling `step()`, the row is also going to point to the new row.
38
56
public struct SQLRow {
39
- /// The underlying statement.
40
- public let statement : SQLStatement // Storing as strong reference doesn't seem to affect performance
41
57
42
58
public init ( statement: SQLStatement ) {
43
- self . statement = statement
59
+ values = ( 0 ..< statement. columnCount) . map { index in
60
+ statement. column ( at: index)
61
+ }
62
+ columnIndicesByNames = Dictionary ( uniqueKeysWithValues: ( 0 ..< statement. columnCount) . map { index in
63
+ ( statement. columnName ( at: index) , index)
64
+ } )
44
65
}
45
66
46
67
/// Returns a single column of the current result row of a query.
@@ -50,7 +71,7 @@ public struct SQLRow {
50
71
///
51
72
/// - parameter index: The leftmost column of the result set has the index 0.
52
73
public subscript< T: SQLDataType > ( index: Int ) -> T {
53
- statement . column ( at : index)
74
+ T . convert ( from : values [ index] ! ) !
54
75
}
55
76
56
77
/// Returns a single column of the current result row of a query. If the
@@ -61,7 +82,8 @@ public struct SQLRow {
61
82
///
62
83
/// - parameter index: The leftmost column of the result set has the index 0.
63
84
public subscript< T: SQLDataType > ( index: Int ) -> T ? {
64
- statement. column ( at: index)
85
+ guard let value = values [ index] else { return nil }
86
+ return T . convert ( from: value)
65
87
}
66
88
67
89
/// Returns a single column (by its name) of the current result row of a query.
@@ -71,10 +93,10 @@ public struct SQLRow {
71
93
///
72
94
/// - parameter columnName: The name of the column.
73
95
public subscript< T: SQLDataType > ( columnName: String ) -> T {
74
- guard let columnIndex = statement . columnIndex ( forName : columnName) else {
96
+ guard let columnIndex = columnIndicesByNames [ columnName] else {
75
97
fatalError ( " No such column \( columnName) " )
76
98
}
77
- return statement . column ( at : columnIndex)
99
+ return self [ columnIndex]
78
100
}
79
101
80
102
/// Returns a single column (by its name) of the current result row of a query.
@@ -84,11 +106,14 @@ public struct SQLRow {
84
106
///
85
107
/// - parameter columnName: The name of the column.
86
108
public subscript< T: SQLDataType > ( columnName: String ) -> T ? {
87
- guard let columnIndex = statement . columnIndex ( forName : columnName) else {
109
+ guard let columnIndex = columnIndicesByNames [ columnName] else {
88
110
return nil
89
111
}
90
- return statement . column ( at : columnIndex)
112
+ return self [ columnIndex]
91
113
}
114
+
115
+ private let values : [ Any ? ]
116
+ private let columnIndicesByNames : [ String : Int ]
92
117
}
93
118
94
119
public protocol SQLRowDecodable {
0 commit comments