diff --git a/Examples/Examples.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Examples/Examples.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index adf158ba..7021d90a 100644 --- a/Examples/Examples.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Examples/Examples.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -123,8 +123,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-structured-queries", "state" : { - "revision" : "14f79c6dad72e385c564c66dbe333522a11eaa48", - "version" : "0.16.0" + "revision" : "1b653aba57486afef66d8aafdbe83246249118fd", + "version" : "0.19.0" } }, { diff --git a/Examples/Reminders/Schema.swift b/Examples/Reminders/Schema.swift index f2eed39f..b00b59b2 100644 --- a/Examples/Reminders/Schema.swift +++ b/Examples/Reminders/Schema.swift @@ -82,7 +82,7 @@ struct ReminderTag: Hashable, Identifiable { } @Table @Selection -struct ReminderText: StructuredQueries.FTS5 { +struct ReminderText: StructuredQueriesSQLite.FTS5 { let rowid: Int let title: String let notes: String diff --git a/Package.resolved b/Package.resolved index 40558cc0..bdb098a4 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "bf7f65a97bc0744011b5a84033dae2413dabad76028eccac59d6837fd798cf8a", + "originHash" : "6dc59eead60386f2f139d8a3ccedd49d62321fc3156858a7ed2c64d5afe19528", "pins" : [ { "identity" : "combine-schedulers", @@ -123,8 +123,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-structured-queries", "state" : { - "revision" : "14f79c6dad72e385c564c66dbe333522a11eaa48", - "version" : "0.16.0" + "revision" : "1b653aba57486afef66d8aafdbe83246249118fd", + "version" : "0.19.0" } }, { diff --git a/Package.swift b/Package.swift index c664a0ca..37d333e8 100644 --- a/Package.swift +++ b/Package.swift @@ -39,7 +39,7 @@ let package = Package( .package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", from: "1.5.0"), .package(url: "https://github.com/pointfreeco/swift-sharing", from: "2.3.0"), .package(url: "https://github.com/pointfreeco/swift-snapshot-testing", from: "1.18.4"), - .package(url: "https://github.com/pointfreeco/swift-structured-queries", from: "0.16.0"), + .package(url: "https://github.com/pointfreeco/swift-structured-queries", from: "0.19.0"), ], targets: [ .target( diff --git a/Sources/StructuredQueriesGRDBCore/CustomFunctions.swift b/Sources/StructuredQueriesGRDBCore/CustomFunctions.swift index 2b93a3f2..8ea3961f 100644 --- a/Sources/StructuredQueriesGRDBCore/CustomFunctions.swift +++ b/Sources/StructuredQueriesGRDBCore/CustomFunctions.swift @@ -98,20 +98,26 @@ extension [QueryBinding] { extension QueryBinding { fileprivate func result(db: OpaquePointer?) { switch self { - case .blob(let value): - sqlite3_result_blob(db, Array(value), Int32(value.count), SQLITE_TRANSIENT) - case .double(let value): - sqlite3_result_double(db, value) - case .date(let value): - sqlite3_result_text(db, value.iso8601String, -1, SQLITE_TRANSIENT) - case .int(let value): - sqlite3_result_int64(db, value) + case .blob(let blob): + sqlite3_result_blob(db, Array(blob), Int32(blob.count), SQLITE_TRANSIENT) + case .bool(let bool): + sqlite3_result_int64(db, bool ? 1 : 0) + case .double(let double): + sqlite3_result_double(db, double) + case .date(let date): + sqlite3_result_text(db, date.iso8601String, -1, SQLITE_TRANSIENT) + case .int(let int): + sqlite3_result_int64(db, int) case .null: sqlite3_result_null(db) - case .text(let value): - sqlite3_result_text(db, value, -1, SQLITE_TRANSIENT) - case .uuid(let value): - sqlite3_result_text(db, value.uuidString.lowercased(), -1, SQLITE_TRANSIENT) + case .text(let text): + sqlite3_result_text(db, text, -1, SQLITE_TRANSIENT) + case .uint(let uint) where uint <= UInt64(Int64.max): + sqlite3_result_int64(db, Int64(uint)) + case .uint(let uint): + sqlite3_result_error(db, "Unsigned integer \(uint) overflows Int64.max", -1) + case .uuid(let uuid): + sqlite3_result_text(db, uuid.uuidString.lowercased(), -1, SQLITE_TRANSIENT) case .invalid(let error): sqlite3_result_error(db, error.underlyingError.localizedDescription, -1) } diff --git a/Sources/StructuredQueriesGRDBCore/QueryCursor.swift b/Sources/StructuredQueriesGRDBCore/QueryCursor.swift index 41876241..9bb396b2 100644 --- a/Sources/StructuredQueriesGRDBCore/QueryCursor.swift +++ b/Sources/StructuredQueriesGRDBCore/QueryCursor.swift @@ -150,6 +150,8 @@ extension QueryBinding { switch self { case let .blob(blob): return Data(blob).databaseValue + case let .bool(bool): + return (bool ? 1 : 0).databaseValue case let .date(date): return date.iso8601String.databaseValue case let .double(double): @@ -160,6 +162,10 @@ extension QueryBinding { return .null case let .text(text): return text.databaseValue + case let .uint(uint) where uint <= UInt64(Int64.max): + return uint.databaseValue + case let .uint(uint): + throw Int64OverflowError(unsignedInteger: uint) case let .uuid(uuid): return uuid.uuidString.lowercased().databaseValue case let .invalid(error): @@ -168,3 +174,12 @@ extension QueryBinding { } } } + +@usableFromInline +struct Int64OverflowError: Error { + let unsignedInteger: UInt64 + @usableFromInline + init(unsignedInteger: UInt64) { + self.unsignedInteger = unsignedInteger + } +} diff --git a/Sources/StructuredQueriesGRDBCore/SQLiteQueryDecoder.swift b/Sources/StructuredQueriesGRDBCore/SQLiteQueryDecoder.swift index 8c66318f..4aed866e 100644 --- a/Sources/StructuredQueriesGRDBCore/SQLiteQueryDecoder.swift +++ b/Sources/StructuredQueriesGRDBCore/SQLiteQueryDecoder.swift @@ -68,6 +68,13 @@ struct SQLiteQueryDecoder: QueryDecoder { return String(cString: sqlite3_column_text(statement, currentIndex)) } + @inlinable + mutating func decode(_ columnType: UInt64.Type) throws -> UInt64? { + guard let n = try decode(Int64.self) else { return nil } + guard n >= 0 else { throw UInt64OverflowError(signedInteger: n) } + return UInt64(n) + } + @inlinable mutating func decode(_ columnType: UUID.Type) throws -> UUID? { guard let uuidString = try decode(String.self) else { return nil } @@ -81,3 +88,13 @@ struct InvalidUUID: Error { @usableFromInline init() {} } + +@usableFromInline +struct UInt64OverflowError: Error { + let signedInteger: Int64 + + @usableFromInline + init(signedInteger: Int64) { + self.signedInteger = signedInteger + } +}