Skip to content

Commit 24e0f5d

Browse files
committed
Make throwing row accessors public
1 parent 2b1b56e commit 24e0f5d

File tree

3 files changed

+72
-34
lines changed

3 files changed

+72
-34
lines changed

GRDB/Core/Row.swift

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ extension Row {
452452
/// ```
453453
@inlinable
454454
public subscript<Value: DatabaseValueConvertible>(_ columnName: String) -> Value {
455-
try! decode(Value.self, forKey: columnName)
455+
try! decode(Value.self, forColumn: columnName)
456456
}
457457

458458
/// Returns the value at given column, converted to the requested type.
@@ -489,7 +489,7 @@ extension Row {
489489
/// ```
490490
@inlinable
491491
public subscript<Value: DatabaseValueConvertible & StatementColumnConvertible>(_ columnName: String) -> Value {
492-
try! decode(Value.self, forKey: columnName)
492+
try! decode(Value.self, forColumn: columnName)
493493
}
494494

495495
/// Returns `Int64`, `Double`, `String`, `Data` or nil, depending on the
@@ -533,7 +533,7 @@ extension Row {
533533
/// ```
534534
@inlinable
535535
public subscript<Value: DatabaseValueConvertible>(_ column: some ColumnExpression) -> Value {
536-
try! decode(Value.self, forKey: column.name)
536+
try! decode(Value.self, forColumn: column)
537537
}
538538

539539
/// Returns the value at given column, converted to the requested type.
@@ -573,7 +573,7 @@ extension Row {
573573
-> Value
574574
where Value: DatabaseValueConvertible & StatementColumnConvertible
575575
{
576-
try! decode(Value.self, forKey: column.name)
576+
try! decode(Value.self, forColumn: column)
577577
}
578578

579579
/// Calls the given closure with the `Data` at given index.
@@ -1068,7 +1068,7 @@ extension Row {
10681068
/// If the SQLite value is NULL, or if the conversion fails, a
10691069
/// `RowDecodingError` is thrown.
10701070
@inlinable
1071-
func decode<Value: DatabaseValueConvertible>(
1071+
public func decode<Value: DatabaseValueConvertible>(
10721072
_ type: Value.Type = Value.self,
10731073
atIndex index: Int)
10741074
throws -> Value
@@ -1086,9 +1086,9 @@ extension Row {
10861086
/// or if the SQLite value can not be converted to `Value`, a
10871087
/// `RowDecodingError` is thrown.
10881088
@inlinable
1089-
func decode<Value: DatabaseValueConvertible>(
1089+
public func decode<Value: DatabaseValueConvertible>(
10901090
_ type: Value.Type = Value.self,
1091-
forKey columnName: String)
1091+
forColumn columnName: String)
10921092
throws -> Value
10931093
{
10941094
guard let index = index(forColumn: columnName) else {
@@ -1100,6 +1100,23 @@ extension Row {
11001100
}
11011101
return try Value.decode(fromRow: self, atUncheckedIndex: index)
11021102
}
1103+
1104+
/// Returns the value at given column, converted to the requested type.
1105+
///
1106+
/// Column name lookup is case-insensitive. When several columns exist with
1107+
/// the same name, the leftmost column is considered.
1108+
///
1109+
/// If the row does not contain the column, or if the SQLite value is NULL,
1110+
/// or if the SQLite value can not be converted to `Value`, a
1111+
/// `RowDecodingError` is thrown.
1112+
@inlinable
1113+
public func decode<Value: DatabaseValueConvertible>(
1114+
_ type: Value.Type = Value.self,
1115+
forColumn column: some ColumnExpression)
1116+
throws -> Value
1117+
{
1118+
try decode(type, forColumn: column.name)
1119+
}
11031120
}
11041121

11051122
// MARK: - Throwing DatabaseValueConvertible & StatementColumnConvertible Decoding Methods
@@ -1118,7 +1135,7 @@ extension Row {
11181135
/// `RowDecodingError` is thrown.
11191136
@inline(__always)
11201137
@inlinable
1121-
func decode<Value: DatabaseValueConvertible & StatementColumnConvertible>(
1138+
public func decode<Value: DatabaseValueConvertible & StatementColumnConvertible>(
11221139
_ type: Value.Type = Value.self,
11231140
atIndex index: Int)
11241141
throws -> Value
@@ -1140,9 +1157,9 @@ extension Row {
11401157
/// or if the SQLite value can not be converted to `Value`, a
11411158
/// `RowDecodingError` is thrown.
11421159
@inlinable
1143-
func decode<Value: DatabaseValueConvertible & StatementColumnConvertible>(
1160+
public func decode<Value: DatabaseValueConvertible & StatementColumnConvertible>(
11441161
_ type: Value.Type = Value.self,
1145-
forKey columnName: String)
1162+
forColumn columnName: String)
11461163
throws -> Value
11471164
{
11481165
guard let index = index(forColumn: columnName) else {
@@ -1155,6 +1172,27 @@ extension Row {
11551172
return try Value.fastDecode(fromRow: self, atUncheckedIndex: index)
11561173
}
11571174

1175+
/// Returns the value at given column, converted to the requested type.
1176+
///
1177+
/// This method exists as an optimization opportunity for types that adopt
1178+
/// ``StatementColumnConvertible``. It can trigger [SQLite built-in
1179+
/// conversions](https://www.sqlite.org/datatype3.html).
1180+
///
1181+
/// Column name lookup is case-insensitive. When several columns exist with
1182+
/// the same name, the leftmost column is considered.
1183+
///
1184+
/// If the row does not contain the column, or if the SQLite value is NULL,
1185+
/// or if the SQLite value can not be converted to `Value`, a
1186+
/// `RowDecodingError` is thrown.
1187+
@inlinable
1188+
public func decode<Value: DatabaseValueConvertible & StatementColumnConvertible>(
1189+
_ type: Value.Type = Value.self,
1190+
forColumn column: some ColumnExpression)
1191+
throws -> Value
1192+
{
1193+
try decode(type, forColumn: column.name)
1194+
}
1195+
11581196
// Support for fast decoding in scoped rows
11591197
@usableFromInline
11601198
func fastDecode<Value: DatabaseValueConvertible & StatementColumnConvertible>(
@@ -1217,7 +1255,7 @@ extension Row {
12171255
/// null values.
12181256
///
12191257
/// See ``splittingRowAdapters(columnCounts:)`` for a sample code.
1220-
func decodeIfPresent<Record: FetchableRecord>(
1258+
public func decodeIfPresent<Record: FetchableRecord>(
12211259
_ type: Record.Type = Record.self,
12221260
forKey scope: String)
12231261
throws -> Record?
@@ -1258,7 +1296,7 @@ extension Row {
12581296
/// null values.
12591297
///
12601298
/// See ``splittingRowAdapters(columnCounts:)`` for a sample code.
1261-
func decode<Record: FetchableRecord>(
1299+
public func decode<Record: FetchableRecord>(
12621300
_ type: Record.Type = Record.self,
12631301
forKey scope: String)
12641302
throws -> Record
@@ -1313,7 +1351,7 @@ extension Row {
13131351
/// let books: [Book] = row["books"]
13141352
/// print(books[0].title)
13151353
/// // Prints "Moby-Dick"
1316-
func decode<Collection>(
1354+
public func decode<Collection>(
13171355
_ type: Collection.Type = Collection.self,
13181356
forKey key: String)
13191357
throws -> Collection
@@ -1364,7 +1402,7 @@ extension Row {
13641402
/// let books: Set<Book> = row["books"]
13651403
/// print(books.first!.title)
13661404
/// // Prints "Moby-Dick"
1367-
func decode<Record: FetchableRecord & Hashable>(
1405+
public func decode<Record: FetchableRecord & Hashable>(
13681406
_ type: Set<Record>.Type = Set<Record>.self,
13691407
forKey key: String)
13701408
throws -> Set<Record>

GRDB/Record/FetchableRecord+Decodable.swift

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -212,20 +212,20 @@ private struct _RowDecoder<R: FetchableRecord>: Decoder {
212212

213213
// swiftlint:disable comma
214214
// swiftlint:disable line_length
215-
func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool { try decoder.row.decode(forKey: decodeColumn(forKey: key)) }
216-
func decode(_ type: Int.Type, forKey key: Key) throws -> Int { try decoder.row.decode(forKey: decodeColumn(forKey: key)) }
217-
func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 { try decoder.row.decode(forKey: decodeColumn(forKey: key)) }
218-
func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 { try decoder.row.decode(forKey: decodeColumn(forKey: key)) }
219-
func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 { try decoder.row.decode(forKey: decodeColumn(forKey: key)) }
220-
func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 { try decoder.row.decode(forKey: decodeColumn(forKey: key)) }
221-
func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt { try decoder.row.decode(forKey: decodeColumn(forKey: key)) }
222-
func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 { try decoder.row.decode(forKey: decodeColumn(forKey: key)) }
223-
func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 { try decoder.row.decode(forKey: decodeColumn(forKey: key)) }
224-
func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 { try decoder.row.decode(forKey: decodeColumn(forKey: key)) }
225-
func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 { try decoder.row.decode(forKey: decodeColumn(forKey: key)) }
226-
func decode(_ type: Float.Type, forKey key: Key) throws -> Float { try decoder.row.decode(forKey: decodeColumn(forKey: key)) }
227-
func decode(_ type: Double.Type, forKey key: Key) throws -> Double { try decoder.row.decode(forKey: decodeColumn(forKey: key)) }
228-
func decode(_ type: String.Type, forKey key: Key) throws -> String { try decoder.row.decode(forKey: decodeColumn(forKey: key)) }
215+
func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool { try decoder.row.decode(forColumn: decodeColumn(forKey: key)) }
216+
func decode(_ type: Int.Type, forKey key: Key) throws -> Int { try decoder.row.decode(forColumn: decodeColumn(forKey: key)) }
217+
func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 { try decoder.row.decode(forColumn: decodeColumn(forKey: key)) }
218+
func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 { try decoder.row.decode(forColumn: decodeColumn(forKey: key)) }
219+
func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 { try decoder.row.decode(forColumn: decodeColumn(forKey: key)) }
220+
func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 { try decoder.row.decode(forColumn: decodeColumn(forKey: key)) }
221+
func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt { try decoder.row.decode(forColumn: decodeColumn(forKey: key)) }
222+
func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 { try decoder.row.decode(forColumn: decodeColumn(forKey: key)) }
223+
func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 { try decoder.row.decode(forColumn: decodeColumn(forKey: key)) }
224+
func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 { try decoder.row.decode(forColumn: decodeColumn(forKey: key)) }
225+
func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 { try decoder.row.decode(forColumn: decodeColumn(forKey: key)) }
226+
func decode(_ type: Float.Type, forKey key: Key) throws -> Float { try decoder.row.decode(forColumn: decodeColumn(forKey: key)) }
227+
func decode(_ type: Double.Type, forKey key: Key) throws -> Double { try decoder.row.decode(forColumn: decodeColumn(forKey: key)) }
228+
func decode(_ type: String.Type, forKey key: Key) throws -> String { try decoder.row.decode(forColumn: decodeColumn(forKey: key)) }
229229
// swiftlint:enable line_length
230230
// swiftlint:enable comma
231231

Tests/GRDBTests/DatabaseValueConversionErrorTests.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class DatabaseValueConversionErrorTests: GRDBTestCase {
77
var name: String
88

99
init(row: Row) throws {
10-
name = try row.decode(forKey: "name")
10+
name = try row.decode(forColumn: "name")
1111
}
1212
}
1313

@@ -123,7 +123,7 @@ class DatabaseValueConversionErrorTests: GRDBTestCase {
123123
var value: Value
124124

125125
init(row: Row) throws {
126-
value = try row.decode(forKey: "value")
126+
value = try row.decode(forColumn: "value")
127127
}
128128
}
129129

@@ -592,7 +592,7 @@ class DatabaseValueConversionErrorTests: GRDBTestCase {
592592

593593
do {
594594
let row = try Row.fetchOne(statement)!
595-
_ = try row.decode(String.self, forKey: "name")
595+
_ = try row.decode(String.self, forColumn: "name")
596596
XCTFail("Expected error")
597597
} catch let error as RowDecodingError {
598598
switch error.impl {
@@ -644,7 +644,7 @@ class DatabaseValueConversionErrorTests: GRDBTestCase {
644644

645645
do {
646646
_ = try Row.fetchCursor(statement)
647-
.map { try $0.decode(Int8.self, forKey: "missing") }
647+
.map { try $0.decode(Int8.self, forColumn: "missing") }
648648
.next()
649649
XCTFail("Expected error")
650650
} catch let error as RowDecodingError {
@@ -691,7 +691,7 @@ class DatabaseValueConversionErrorTests: GRDBTestCase {
691691

692692
do {
693693
let row = try Row.fetchOne(statement)!
694-
_ = try row.decode(Int8.self, forKey: "foo")
694+
_ = try row.decode(Int8.self, forColumn: "foo")
695695
XCTFail("Expected error")
696696
} catch let error as RowDecodingError {
697697
switch error.impl {
@@ -793,7 +793,7 @@ class DatabaseValueConversionErrorTests: GRDBTestCase {
793793

794794
do {
795795
let row = try Row.fetchOne(statement)!
796-
_ = try row.decode(Value.self, forKey: "name")
796+
_ = try row.decode(Value.self, forColumn: "name")
797797
XCTFail("Expected error")
798798
} catch let error as RowDecodingError {
799799
switch error.impl {

0 commit comments

Comments
 (0)