@@ -11,9 +11,9 @@ public final class PreparedStatement: DatabaseHandle {
1111 /// Find the database handle of a prepared statement.
1212 var db : OpaquePointer ! { sqlite3_db_handle ( stmt) }
1313
14- private( set) lazy var columnIndexByName = [ String: Int32 ] (
14+ private( set) lazy var columnIndexByName = [ String: Int ] (
1515 uniqueKeysWithValues: ( 0 ..< columnCount) . compactMap { index in
16- column ( at: index) . name . map { name in ( name, index) }
16+ columnName ( at: index) . map { name in ( name, index) }
1717 }
1818 )
1919
@@ -34,20 +34,6 @@ public final class PreparedStatement: DatabaseHandle {
3434 try check ( sqlite3_step ( stmt) , SQLITE_DONE)
3535 }
3636
37- /// The new row of data is ready for processing.
38- ///
39- /// - Throws: ``DatabaseError``
40- public func step( ) throws -> Bool {
41- switch sqlite3_step ( stmt) {
42- case SQLITE_DONE:
43- return false
44- case SQLITE_ROW:
45- return true
46- case let code:
47- throw DatabaseError ( code: code, db: db)
48- }
49- }
50-
5137 /// Reset the prepared statement.
5238 ///
5339 /// The ``PreparedStatement/reset()`` function is called to reset a prepared statement object back to its initial state, ready to be re-executed.
@@ -59,32 +45,6 @@ public final class PreparedStatement: DatabaseHandle {
5945 public func reset( ) throws -> PreparedStatement {
6046 try check ( sqlite3_reset ( stmt) )
6147 }
62-
63- /// Reset all bindings on a prepared statement.
64- ///
65- /// Contrary to the intuition of many, ``PreparedStatement/reset()`` does not reset the bindings on a prepared statement.
66- /// Use this routine to reset all host parameters to NULL.
67- ///
68- /// - Throws: ``DatabaseError``
69- @discardableResult
70- public func clearBindings( ) throws -> PreparedStatement {
71- try check ( sqlite3_clear_bindings ( stmt) )
72- }
73-
74- // MARK: - Decodable
75-
76- public func array< T> ( decoding type: T . Type ) throws -> [ T ] where T: Decodable {
77- var array : [ T ] = [ ]
78- while try step ( ) {
79- let value = try decode ( type)
80- array. append ( value)
81- }
82- return array
83- }
84-
85- public func decode< T> ( _ type: T . Type ) throws -> T where T: Decodable {
86- try StatementDecoder ( ) . decode ( type, from: self )
87- }
8848}
8949
9050// MARK: - Retrieving Statement SQL
@@ -112,16 +72,16 @@ extension PreparedStatement {
11272
11373extension PreparedStatement {
11474 /// Number of SQL parameters.
115- public var parameterCount : Int32 { sqlite3_bind_parameter_count ( stmt) }
75+ public var parameterCount : Int { Int ( sqlite3_bind_parameter_count ( stmt) ) }
11676
11777 /// Name of a SQL parameter.
118- public func parameterName( at index: Int32 ) -> String ? {
119- sqlite3_bind_parameter_name ( stmt, index) . map { String ( cString: $0) }
78+ public func parameterName( at index: Int ) -> String ? {
79+ sqlite3_bind_parameter_name ( stmt, Int32 ( index) ) . map { String ( cString: $0) }
12080 }
12181
12282 /// Index of a parameter with a given name.
123- public func parameterIndex( for name: String ) -> Int32 {
124- sqlite3_bind_parameter_index ( stmt, name)
83+ public func parameterIndex( for name: String ) -> Int {
84+ Int ( sqlite3_bind_parameter_index ( stmt, name) )
12585 }
12686}
12787
@@ -138,13 +98,14 @@ extension PreparedStatement {
13898 @discardableResult
13999 public func bind( parameters: SQLParameter ... ) throws -> PreparedStatement {
140100 for (index, parameter) in parameters. enumerated ( ) {
141- try bind ( index: Int32 ( index + 1 ) , parameter: parameter)
101+ try bind ( index: index + 1 , parameter: parameter)
142102 }
143103 return self
144104 }
145105
146106 @discardableResult
147- public func bind( index: Int32 , parameter: SQLParameter ) throws -> PreparedStatement {
107+ public func bind( index: Int , parameter: SQLParameter ) throws -> PreparedStatement {
108+ let index = Int32 ( index)
148109 let code =
149110 switch parameter {
150111 case . null:
@@ -162,52 +123,118 @@ extension PreparedStatement {
162123 }
163124 return try check ( code)
164125 }
126+
127+ /// Reset all bindings on a prepared statement.
128+ ///
129+ /// Contrary to the intuition of many, ``PreparedStatement/reset()`` does not reset the bindings on a prepared statement.
130+ /// Use this routine to reset all host parameters to NULL.
131+ ///
132+ /// - Throws: ``DatabaseError``
133+ @discardableResult
134+ public func clearBindings( ) throws -> PreparedStatement {
135+ try check ( sqlite3_clear_bindings ( stmt) )
136+ }
165137}
166138
167- // MARK: - Result values from a Query
139+ // MARK: - Columns
168140
169141extension PreparedStatement {
170142 /// Return the number of columns in the result set.
171- public var columnCount : Int32 { sqlite3_column_count ( stmt) }
143+ public var columnCount : Int { Int ( sqlite3_column_count ( stmt) ) }
172144
173- public func column( at index: Int32 ) -> Column {
174- Column ( index: index, statement: self )
145+ /// Returns the name assigned to a specific column in the result set of the SELECT statement.
146+ ///
147+ /// The name of a result column is the value of the "AS" clause for that column, if there is an AS clause.
148+ /// If there is no AS clause then the name of the column is unspecified and may change from one release of SQLite to the next.
149+ public func columnName( at index: Int ) -> String ? {
150+ sqlite3_column_name ( stmt, Int32 ( index) ) . string
175151 }
152+ }
176153
177- public func column( for name: String ) -> Column ? {
178- columnIndexByName [ name] . map { Column ( index: $0, statement: self ) }
154+ // MARK: - Result values from a Query
155+
156+ extension PreparedStatement {
157+ /// The new row of data is ready for processing.
158+ ///
159+ /// - Throws: ``DatabaseError``
160+ public func row( ) throws -> Row ? {
161+ switch sqlite3_step ( stmt) {
162+ case SQLITE_DONE: nil
163+ case SQLITE_ROW: Row ( statement: self )
164+ case let code: throw DatabaseError ( code: code, db: db)
165+ }
179166 }
180167
181- /// Information about a single column of the current result row of a query.
182- public struct Column {
183- let index : Int32
168+ public func array< T> ( _ type: T . Type ) throws -> [ T ] where T: Decodable {
169+ try array ( type, using: RowDecoder . default)
170+ }
171+
172+ public func array< T> ( _ type: T . Type , using decoder: RowDecoder ) throws -> [ T ] where T: Decodable {
173+ var array : [ T ] = [ ]
174+ while let row = try row ( ) {
175+ let value = try row. decode ( type, using: decoder)
176+ array. append ( value)
177+ }
178+ return array
179+ }
180+
181+ @dynamicMemberLookup
182+ public struct Row {
184183 let statement : PreparedStatement
185- private var stmt : OpaquePointer { statement. stmt }
186184
187- /// Returns the name assigned to a specific column in the result set of the SELECT statement.
188- ///
189- /// The name of a result column is the value of the "AS" clause for that column, if there is an AS clause.
190- /// If there is no AS clause then the name of the column is unspecified and may change from one release of SQLite to the next.
191- public var name : String ? { sqlite3_column_name ( stmt, index) . string }
185+ public subscript( dynamicMember name: String ) -> Value ? {
186+ self [ name]
187+ }
188+
189+ public subscript( name: String ) -> Value ? {
190+ statement. columnIndexByName [ name] . flatMap { self [ $0] }
191+ }
192+
193+ public subscript( index: Int ) -> Value ? {
194+ if sqlite3_column_type ( statement. stmt, Int32 ( index) ) == SQLITE_NULL {
195+ return nil
196+ }
197+ return Value ( index: Int32 ( index) , statement: statement)
198+ }
192199
193- public var isNull : Bool { sqlite3_column_type ( stmt, index) == SQLITE_NULL }
200+ public func decode< T> ( _ type: T . Type ) throws -> T where T: Decodable {
201+ try decode ( type, using: RowDecoder . default)
202+ }
203+
204+ public func decode< T> ( _ type: T . Type , using decoder: RowDecoder ) throws -> T where T: Decodable {
205+ try decoder. decode ( type, from: self )
206+ }
207+ }
208+
209+ /// Result value from a query.
210+ public struct Value {
211+ let index : Int32
212+ let statement : PreparedStatement
213+ private var stmt : OpaquePointer { statement. stmt }
194214
195215 /// 64-bit INTEGER result.
196216 public var int64 : Int64 { sqlite3_column_int64 ( stmt, index) }
197217
218+ /// 32-bit INTEGER result.
219+ public var int32 : Int32 { sqlite3_column_int ( stmt, index) }
220+
221+ /// A platform-specific integer.
222+ public var int : Int { Int ( int64) }
223+
198224 /// 64-bit IEEE floating point number.
199225 public var double : Double { sqlite3_column_double ( stmt, index) }
200226
227+ /// Size of a BLOB or a UTF-8 TEXT result in bytes.
228+ public var count : Int { Int ( sqlite3_column_bytes ( stmt, index) ) }
229+
201230 /// UTF-8 TEXT result.
202231 public var string : String ? {
203232 sqlite3_column_text ( stmt, index) . flatMap { String ( cString: $0) }
204233 }
205234
206235 /// BLOB result.
207236 public var blob : Data ? {
208- sqlite3_column_blob ( stmt, index) . map { bytes in
209- Data ( bytes: bytes, count: Int ( sqlite3_column_bytes ( stmt, index) ) )
210- }
237+ sqlite3_column_blob ( stmt, index) . map { Data ( bytes: $0, count: count) }
211238 }
212239 }
213240}
0 commit comments