diff --git a/Sources/PowerSync/Kotlin/db/KotlinConnectionContext.swift b/Sources/PowerSync/Kotlin/db/KotlinConnectionContext.swift index 0b7f314..c280a26 100644 --- a/Sources/PowerSync/Kotlin/db/KotlinConnectionContext.swift +++ b/Sources/PowerSync/Kotlin/db/KotlinConnectionContext.swift @@ -97,6 +97,11 @@ final class KotlinTransactionContext: Transaction, KotlinConnectionContextProtoc // Allows nil values to be passed to the Kotlin [Any] params func mapParameters(_ parameters: [Any?]?) -> [Any] { parameters?.map { item in - item ?? NSNull() + switch item { + case .none: NSNull() + case let item as PowerSyncDataTypeConvertible: + item.psDataType?.unwrap() ?? NSNull() + default: item + } } ?? [] } diff --git a/Sources/PowerSync/Kotlin/db/PowerSyncDataTypeConvertible.swift b/Sources/PowerSync/Kotlin/db/PowerSyncDataTypeConvertible.swift new file mode 100644 index 0000000..bfe6d05 --- /dev/null +++ b/Sources/PowerSync/Kotlin/db/PowerSyncDataTypeConvertible.swift @@ -0,0 +1,32 @@ +import struct Foundation.Data + +/// Represents the set of types that are supported +/// by the PowerSync Kotlin Multiplatform SDK +public enum PowerSyncDataType { + case bool(Bool) + case string(String) + case int64(Int64) + case int32(Int32) + case double(Double) + case data(Data) +} + +/// Types conforming to this protocol will be +/// mapped to the specified ``PowerSyncDataType`` +/// before use by SQLite +public protocol PowerSyncDataTypeConvertible { + var psDataType: PowerSyncDataType? { get } +} + +extension PowerSyncDataType { + func unwrap() -> Any { + switch self { + case let .bool(bool): bool + case let .string(string): string + case let .int32(int32): int32 + case let .int64(int64): int64 + case let .double(double): double + case let .data(data): data + } + } +} \ No newline at end of file diff --git a/Tests/PowerSyncTests/Kotlin/KotlinPowerSyncDatabaseImplTests.swift b/Tests/PowerSyncTests/Kotlin/KotlinPowerSyncDatabaseImplTests.swift index dd181b8..2cd3843 100644 --- a/Tests/PowerSyncTests/Kotlin/KotlinPowerSyncDatabaseImplTests.swift +++ b/Tests/PowerSyncTests/Kotlin/KotlinPowerSyncDatabaseImplTests.swift @@ -1,4 +1,5 @@ @testable import PowerSync +import struct Foundation.UUID import XCTest final class KotlinPowerSyncDatabaseImplTests: XCTestCase { @@ -156,6 +157,25 @@ final class KotlinPowerSyncDatabaseImplTests: XCTestCase { } } + func testCustomDataTypeConvertible() async throws { + let uuid = UUID() + try await database.execute( + sql: "INSERT INTO users (id, name, email) VALUES (?, ?, ?)", + parameters: [uuid, "Test User", "test@example.com"] + ) + + let _ = try await database.getOptional( + sql: "SELECT id, name, email FROM users WHERE id = ?", + parameters: [uuid] + ) { cursor throws in + try ( + cursor.getString(name: "id"), + cursor.getString(name: "name"), + cursor.getString(name: "email") + ) + } + } + func testGetAll() async throws { try await database.execute( sql: "INSERT INTO users (id, name, email) VALUES (?, ?, ?), (?, ?, ?)", @@ -698,3 +718,10 @@ final class KotlinPowerSyncDatabaseImplTests: XCTestCase { try deleteSQLiteFiles(dbFilename: testDbFilename, in: databaseDirectory) } } + + +extension UUID: @retroactive PowerSyncDataTypeConvertible { + public var psDataType: PowerSyncDataType? { + .string(uuidString) + } +} \ No newline at end of file