From 9a76550144ccf33592cae99f0ad4ff3686230936 Mon Sep 17 00:00:00 2001 From: Nick Shelley Date: Mon, 8 May 2017 13:29:13 -0600 Subject: [PATCH] Make Row.get throw instead of crash. --- Sources/SQLite/Foundation.swift | 8 ++--- Sources/SQLite/Typed/Query.swift | 52 +++++++++++++++++++++----------- 2 files changed, 38 insertions(+), 22 deletions(-) diff --git a/Sources/SQLite/Foundation.swift b/Sources/SQLite/Foundation.swift index 5e102297..1634f954 100644 --- a/Sources/SQLite/Foundation.swift +++ b/Sources/SQLite/Foundation.swift @@ -92,17 +92,17 @@ extension QueryType { extension Row { public subscript(column: Expression) -> Data { - return get(column) + return try! get(column) } public subscript(column: Expression) -> Data? { - return get(column) + return try! get(column) } public subscript(column: Expression) -> Date { - return get(column) + return try! get(column) } public subscript(column: Expression) -> Date? { - return get(column) + return try! get(column) } } diff --git a/Sources/SQLite/Typed/Query.swift b/Sources/SQLite/Typed/Query.swift index c9d2ea9c..6f35f343 100644 --- a/Sources/SQLite/Typed/Query.swift +++ b/Sources/SQLite/Typed/Query.swift @@ -1021,6 +1021,17 @@ extension Connection { } +public enum SQLiteErrorType { + case unexpectedNullValue + case noSuchColumn + case ambiguousColumn +} + +public struct SQLiteError: Error { + let type: SQLiteErrorType + let message: String +} + public struct Row { fileprivate let columnNames: [String: Int] @@ -1037,13 +1048,18 @@ public struct Row { /// - Parameter column: An expression representing a column selected in a Query. /// /// - Returns: The value for the given column. - public func get(_ column: Expression) -> V { - return get(Expression(column))! + public func get(_ column: Expression) throws -> V { + if let value = try get(Expression(column)) { + return value + } else { + throw SQLiteError(type: .unexpectedNullValue, message: "Unexpected NULL value in column \(column.template)") + } } - public func get(_ column: Expression) -> V? { + + public func get(_ column: Expression) throws -> V? { func valueAtIndex(_ idx: Int) -> V? { guard let value = values[idx] as? V.Datatype else { return nil } - return (V.fromDatatypeValue(value) as? V)! + return V.fromDatatypeValue(value) as? V } guard let idx = columnNames[column.template] else { @@ -1051,11 +1067,11 @@ public struct Row { switch similar.count { case 0: - fatalError("no such column '\(column.template)' in columns: \(columnNames.keys.sorted())") + throw SQLiteError(type: .noSuchColumn, message: "No such column '\(column.template)' in columns: \(columnNames.keys.sorted())") case 1: return valueAtIndex(columnNames[similar[0]]!) default: - fatalError("ambiguous column '\(column.template)' (please disambiguate: \(similar))") + throw SQLiteError(type: .ambiguousColumn, message: "Ambiguous column '\(column.template)' (please disambiguate: \(similar))") } } @@ -1065,45 +1081,45 @@ public struct Row { // FIXME: rdar://problem/18673897 // subscript… public subscript(column: Expression) -> Blob { - return get(column) + return try! get(column) } public subscript(column: Expression) -> Blob? { - return get(column) + return try! get(column) } public subscript(column: Expression) -> Bool { - return get(column) + return try! get(column) } public subscript(column: Expression) -> Bool? { - return get(column) + return try! get(column) } public subscript(column: Expression) -> Double { - return get(column) + return try! get(column) } public subscript(column: Expression) -> Double? { - return get(column) + return try! get(column) } public subscript(column: Expression) -> Int { - return get(column) + return try! get(column) } public subscript(column: Expression) -> Int? { - return get(column) + return try! get(column) } public subscript(column: Expression) -> Int64 { - return get(column) + return try! get(column) } public subscript(column: Expression) -> Int64? { - return get(column) + return try! get(column) } public subscript(column: Expression) -> String { - return get(column) + return try! get(column) } public subscript(column: Expression) -> String? { - return get(column) + return try! get(column) } }