Skip to content

Commit 07cda49

Browse files
committed
Fix UUID endianness, add SQL literal support for UUID, and make SQLRowDecoder public
1 parent 1938b29 commit 07cda49

File tree

2 files changed

+25
-9
lines changed

2 files changed

+25
-9
lines changed

Sources/SQLClientSwift/SQLClient.swift

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,16 @@ public actor SQLClient {
350350
guard len == 16 else { return NSNull() }
351351
var bytes = [UInt8](repeating: 0, count: 16)
352352
memcpy(&bytes, dataPtr, 16)
353-
return NSUUID(uuidBytes: &bytes) as UUID
353+
354+
// SQL Server UniqueIdentifier mixed-endian -> RFC 4122 Big-Endian
355+
// Data1 (4 bytes), Data2 (2 bytes), Data3 (2 bytes) are little-endian in TDS
356+
let swapped: [UInt8] = [
357+
bytes[3], bytes[2], bytes[1], bytes[0],
358+
bytes[5], bytes[4],
359+
bytes[7], bytes[6],
360+
bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15]
361+
]
362+
return NSUUID(uuidBytes: swapped) as UUID
354363
case 31: // SYBVOID
355364
return NSNull()
356365
default:
@@ -417,6 +426,7 @@ public actor SQLClient {
417426
switch value {
418427
case let s as String: return "'" + s.replacingOccurrences(of: "'", with: "''") + "'"
419428
case let n as NSNumber: return n.stringValue
429+
case let u as UUID: return "'" + u.uuidString + "'"
420430
case let d as Date:
421431
let df = DateFormatter()
422432
df.locale = Locale(identifier: "en_US_POSIX")

Sources/SQLClientSwift/SQLRowDecoder.swift

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,29 @@
1010

1111
import Foundation
1212

13-
/// Internal decoder that bridges a `SQLRow` into Swift's `Decodable` protocol.
14-
internal struct SQLRowDecoder: Decoder {
15-
let row: SQLRow
16-
var codingPath: [CodingKey] = []
17-
var userInfo: [CodingUserInfoKey: Any] = [:]
13+
/// Decoder that bridges a `SQLRow` into Swift's `Decodable` protocol.
14+
public struct SQLRowDecoder: Decoder {
15+
public let row: SQLRow
16+
public var codingPath: [CodingKey]
17+
public var userInfo: [CodingUserInfoKey: Any]
18+
19+
public init(row: SQLRow, codingPath: [CodingKey] = [], userInfo: [CodingUserInfoKey: Any] = [:]) {
20+
self.row = row
21+
self.codingPath = codingPath
22+
self.userInfo = userInfo
23+
}
1824

19-
func container<Key: CodingKey>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> {
25+
public func container<Key: CodingKey>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> {
2026
KeyedDecodingContainer(SQLRowKeyedContainer<Key>(row: row, codingPath: codingPath))
2127
}
2228

23-
func unkeyedContainer() throws -> UnkeyedDecodingContainer {
29+
public func unkeyedContainer() throws -> UnkeyedDecodingContainer {
2430
throw DecodingError.typeMismatch(
2531
[Any].self,
2632
.init(codingPath: codingPath, debugDescription: "SQLRow does not support unkeyed decoding."))
2733
}
2834

29-
func singleValueContainer() throws -> SingleValueDecodingContainer {
35+
public func singleValueContainer() throws -> SingleValueDecodingContainer {
3036
throw DecodingError.typeMismatch(
3137
Any.self,
3238
.init(codingPath: codingPath, debugDescription: "SQLRow does not support single-value decoding."))

0 commit comments

Comments
 (0)