Skip to content

Commit 03724bf

Browse files
author
Elfred Pagán
committed
make fromDatatypeValue throw
When using custom types, sometimes decoding can fail, say due to changes in the type structure. In this case decoding would fail and the only way to handle it is forcing a crash. This change allows you to use `try row.get()` instead. Givng you the chance to handle the mismatch.
1 parent 3d25271 commit 03724bf

File tree

4 files changed

+39
-9
lines changed

4 files changed

+39
-9
lines changed

Sources/SQLite/Core/Value.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public protocol Value: Expressible { // extensions cannot have inheritance claus
3939

4040
static var declaredDatatype: String { get }
4141

42-
static func fromDatatypeValue(_ datatypeValue: Datatype) -> ValueType
42+
static func fromDatatypeValue(_ datatypeValue: Datatype) throws -> ValueType
4343

4444
var datatypeValue: Datatype { get }
4545

Sources/SQLite/Helpers.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,9 @@ func transcode(_ literal: Binding?) -> String {
121121
}
122122
}
123123

124-
// swiftlint:disable force_cast
124+
// swiftlint:disable force_cast force_try
125125
func value<A: Value>(_ binding: Binding) -> A {
126-
A.fromDatatypeValue(binding as! A.Datatype) as! A
126+
try! A.fromDatatypeValue(binding as! A.Datatype) as! A
127127
}
128128

129129
func value<A: Value>(_ binding: Binding?) -> A {

Sources/SQLite/Typed/Query.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,7 +1097,7 @@ extension Connection {
10971097
public func scalar<V: Value>(_ query: ScalarQuery<V?>) throws -> V.ValueType? {
10981098
let expression = query.expression
10991099
guard let value = try scalar(expression.template, expression.bindings) as? V.Datatype else { return nil }
1100-
return V.fromDatatypeValue(value)
1100+
return try V.fromDatatypeValue(value)
11011101
}
11021102

11031103
public func scalar<V: Value>(_ query: Select<V>) throws -> V {
@@ -1108,7 +1108,7 @@ extension Connection {
11081108
public func scalar<V: Value>(_ query: Select<V?>) throws -> V.ValueType? {
11091109
let expression = query.expression
11101110
guard let value = try scalar(expression.template, expression.bindings) as? V.Datatype else { return nil }
1111-
return V.fromDatatypeValue(value)
1111+
return try V.fromDatatypeValue(value)
11121112
}
11131113

11141114
public func pluck(_ query: QueryType) throws -> Row? {
@@ -1200,9 +1200,9 @@ public struct Row {
12001200
}
12011201

12021202
public func get<V: Value>(_ column: Expression<V?>) throws -> V? {
1203-
func valueAtIndex(_ idx: Int) -> V? {
1203+
func valueAtIndex(_ idx: Int) throws -> V? {
12041204
guard let value = values[idx] as? V.Datatype else { return nil }
1205-
return V.fromDatatypeValue(value) as? V
1205+
return try V.fromDatatypeValue(value) as? V
12061206
}
12071207

12081208
guard let idx = columnNames[column.template] else {
@@ -1224,10 +1224,10 @@ public struct Row {
12241224
similar: columnNames.keys.filter(similar).sorted()
12251225
)
12261226
}
1227-
return valueAtIndex(columnNames[firstIndex].value)
1227+
return try valueAtIndex(columnNames[firstIndex].value)
12281228
}
12291229

1230-
return valueAtIndex(idx)
1230+
return try valueAtIndex(idx)
12311231
}
12321232

12331233
public subscript<T: Value>(column: Expression<T>) -> T {

Tests/SQLiteTests/Typed/RowTests.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,34 @@ class RowTests: XCTestCase {
8585
}
8686
}
8787
}
88+
89+
public func test_get_datatype_throws() {
90+
// swiftlint:disable nesting
91+
struct MyType: Value {
92+
enum MyError: Error {
93+
case failed
94+
}
95+
96+
public static var declaredDatatype: String {
97+
Blob.declaredDatatype
98+
}
99+
100+
public static func fromDatatypeValue(_ dataValue: Blob) throws -> Data {
101+
throw MyError.failed
102+
}
103+
104+
public var datatypeValue: Blob {
105+
return Blob(bytes: [])
106+
}
107+
}
108+
109+
let row = Row(["\"foo\"": 0], [Blob(bytes: [])])
110+
XCTAssertThrowsError(try row.get(Expression<MyType>("foo"))) { error in
111+
if case MyType.MyError.failed = error {
112+
XCTAssertTrue(true)
113+
} else {
114+
XCTFail("unexpected error: \(error)")
115+
}
116+
}
117+
}
88118
}

0 commit comments

Comments
 (0)