Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## 1.0.0-Beta.4
* Allow cursor to use column name to get value by including the following functions that accept a column name parameter:
`getBoolean`,`getBooleanOptional`,`getString`,`getStringOptional`, `getLong`,`getLongOptional`, `getDouble`,`getDoubleOptional`
* BREAKING CHANGE: This should not affect anyone but made `KotlinPowerSyncCredentials`, `KotlinPowerSyncDatabase` and `KotlinPowerSyncBackendConnector` private as these should never have been public.


## 1.0.0-Beta.3

* BREAKING CHANGE: Update underlying powersync-kotlin package to BETA18.0 which requires transactions to become synchronous as opposed to asynchronous.
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 13 additions & 13 deletions Demo/PowerSyncExample/PowerSync/SystemManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ class SystemManager {
parameters: [],
mapper: { cursor in
ListContent(
id: cursor.getString(index: 0)!,
name: cursor.getString(index: 1)!,
createdAt: cursor.getString(index: 2)!,
ownerId: cursor.getString(index: 3)!
id: try cursor.getString(name: "id"),
name: try cursor.getString(name: "name"),
createdAt: try cursor.getString(name: "created_at"),
ownerId: try cursor.getString(name: "owner_id")
)
}
) {
Expand Down Expand Up @@ -77,15 +77,15 @@ class SystemManager {
parameters: [listId],
mapper: { cursor in
return Todo(
id: cursor.getString(index: 0)!,
listId: cursor.getString(index: 1)!,
photoId: cursor.getString(index: 2),
description: cursor.getString(index: 3)!,
isComplete: cursor.getBoolean(index: 4)! as! Bool,
createdAt: cursor.getString(index: 5),
completedAt: cursor.getString(index: 6),
createdBy: cursor.getString(index: 7),
completedBy: cursor.getString(index: 8)
id: try cursor.getString(name: "id"),
listId: try cursor.getString(name: "list_id"),
photoId: try cursor.getStringOptional(name: "photo_id"),
description: try cursor.getString(name: "description"),
isComplete: try cursor.getBoolean(name: "completed"),
createdAt: try cursor.getString(name: "created_at"),
completedAt: try cursor.getStringOptional(name: "completed_at"),
createdBy: try cursor.getStringOptional(name: "created_by"),
completedBy: try cursor.getStringOptional(name: "completed_by")
)
}
) {
Expand Down
4 changes: 2 additions & 2 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ let package = Package(
targets: ["PowerSync"]),
],
dependencies: [
.package(url: "https://github.com/powersync-ja/powersync-kotlin.git", exact: "1.0.0-BETA18.0"),
.package(url: "https://github.com/powersync-ja/powersync-kotlin.git", exact: "1.0.0-BETA20.0"),
.package(url: "https://github.com/powersync-ja/powersync-sqlite-core-swift.git", "0.3.9"..<"0.4.0")
],
targets: [
Expand Down
65 changes: 64 additions & 1 deletion Sources/PowerSync/Kotlin/KotlinPowerSyncDatabaseImpl.swift
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,21 @@ final class KotlinPowerSyncDatabaseImpl: PowerSyncDatabaseProtocol {
mapper: mapper
) as! RowType
}


func get<RowType>(
sql: String,
parameters: [Any]?,
mapper: @escaping (SqlCursor) throws -> RowType
) async throws -> RowType {
try await kotlinDatabase.get(
sql: sql,
parameters: parameters,
mapper: { cursor in
try! mapper(cursor)
}
) as! RowType
}

func getAll<RowType>(
sql: String,
parameters: [Any]?,
Expand All @@ -91,6 +105,20 @@ final class KotlinPowerSyncDatabaseImpl: PowerSyncDatabaseProtocol {
mapper: mapper
) as! [RowType]
}

func getAll<RowType>(
sql: String,
parameters: [Any]?,
mapper: @escaping (SqlCursor) throws -> RowType
) async throws -> [RowType] {
try await kotlinDatabase.getAll(
sql: sql,
parameters: parameters,
mapper: { cursor in
try! mapper(cursor)
}
) as! [RowType]
}

func getOptional<RowType>(
sql: String,
Expand All @@ -103,6 +131,20 @@ final class KotlinPowerSyncDatabaseImpl: PowerSyncDatabaseProtocol {
mapper: mapper
) as! RowType?
}

func getOptional<RowType>(
sql: String,
parameters: [Any]?,
mapper: @escaping (SqlCursor) throws -> RowType
) async throws -> RowType? {
try await kotlinDatabase.getOptional(
sql: sql,
parameters: parameters,
mapper: { cursor in
try! mapper(cursor)
}
) as! RowType?
}

func watch<RowType>(
sql: String,
Expand All @@ -123,6 +165,27 @@ final class KotlinPowerSyncDatabaseImpl: PowerSyncDatabaseProtocol {
}
}

func watch<RowType>(
sql: String,
parameters: [Any]?,
mapper: @escaping (SqlCursor) throws -> RowType
) -> AsyncStream<[RowType]> {
AsyncStream { continuation in
Task {
for await values in self.kotlinDatabase.watch(
sql: sql,
parameters: parameters,
mapper: { cursor in
try! mapper(cursor)
}
) {
continuation.yield(values as! [RowType])
}
continuation.finish()
}
}
}

public func writeTransaction<R>(callback: @escaping (any PowerSyncTransaction) -> R) async throws -> R {
return try await kotlinDatabase.writeTransaction(callback: callback) as! R
}
Expand Down
9 changes: 4 additions & 5 deletions Sources/PowerSync/Kotlin/KotlinTypes.swift
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import PowerSyncKotlin

public typealias KotlinPowerSyncBackendConnector = PowerSyncKotlin.PowerSyncBackendConnector
typealias KotlinPowerSyncBackendConnector = PowerSyncKotlin.PowerSyncBackendConnector
public typealias CrudEntry = PowerSyncKotlin.CrudEntry
public typealias CrudBatch = PowerSyncKotlin.CrudBatch
public typealias SyncStatus = PowerSyncKotlin.SyncStatus
public typealias SqlCursor = PowerSyncKotlin.RuntimeSqlCursor
public typealias SqlCursor = PowerSyncKotlin.SqlCursor
public typealias JsonParam = PowerSyncKotlin.JsonParam
public typealias CrudTransaction = PowerSyncKotlin.CrudTransaction
public typealias KotlinPowerSyncCredentials = PowerSyncKotlin.PowerSyncCredentials
public typealias KotlinPowerSyncDatabase = PowerSyncKotlin.PowerSyncDatabase

typealias KotlinPowerSyncCredentials = PowerSyncKotlin.PowerSyncCredentials
typealias KotlinPowerSyncDatabase = PowerSyncKotlin.PowerSyncDatabase
68 changes: 68 additions & 0 deletions Sources/PowerSync/Kotlin/SqlCursor.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import Foundation
import PowerSyncKotlin

extension SqlCursor {
private func getColumnIndex(name: String) throws -> Int32 {
guard let columnIndex = columnNames[name]?.int32Value else {
throw SqlCursorError.columnNotFound(name)
}
return columnIndex
}

private func getValue<T>(name: String, getter: (Int32) -> T?) throws -> T {
let columnIndex = try getColumnIndex(name: name)
guard let value = getter(columnIndex) else {
throw SqlCursorError.nullValueFound(name)
}
return value
}

private func getOptionalValue<T>(name: String, getter: (String) -> T?) throws -> T? {
_ = try getColumnIndex(name: name)
return getter(name)
}

public func getBoolean(name: String) throws -> Bool {
try getValue(name: name) { getBoolean(index: $0)?.boolValue }
}

public func getDouble(name: String) throws -> Double {
try getValue(name: name) { getDouble(index: $0)?.doubleValue }
}

public func getLong(name: String) throws -> Int {
try getValue(name: name) { getLong(index: $0)?.intValue }
}

public func getString(name: String) throws -> String {
try getValue(name: name) { getString(index: $0) }
}

public func getBooleanOptional(name: String) throws -> Bool? {
try getOptionalValue(name: name) { getBooleanOptional(name: $0)?.boolValue }
}

public func getDoubleOptional(name: String) throws -> Double? {
try getOptionalValue(name: name) { getDoubleOptional(name: $0)?.doubleValue }
}

public func getLongOptional(name: String) throws -> Int? {
try getOptionalValue(name: name) { getLongOptional(name: $0)?.intValue }
}

public func getStringOptional(name: String) throws -> String? {
try getOptionalValue(name: name) { PowerSyncKotlin.SqlCursorKt.getStringOptional(self, name: $0) }
}
}

enum SqlCursorError: Error {
case nullValue(message: String)

static func columnNotFound(_ name: String) -> SqlCursorError {
.nullValue(message: "Column '\(name)' not found")
}

static func nullValueFound(_ name: String) -> SqlCursorError {
.nullValue(message: "Null value found for column \(name)")
}
}
31 changes: 31 additions & 0 deletions Sources/PowerSync/QueriesProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,43 @@ public protocol Queries {
mapper: @escaping (SqlCursor) -> RowType
) async throws -> RowType

/// Execute a read-only (SELECT) query and return a single result.
/// If there is no result, throws an IllegalArgumentException.
/// See `getOptional` for queries where the result might be empty.
func get<RowType>(
sql: String,
parameters: [Any]?,
mapper: @escaping (SqlCursor) throws -> RowType
) async throws -> RowType

/// Execute a read-only (SELECT) query and return the results.
func getAll<RowType>(
sql: String,
parameters: [Any]?,
mapper: @escaping (SqlCursor) -> RowType
) async throws -> [RowType]

/// Execute a read-only (SELECT) query and return the results.
func getAll<RowType>(
sql: String,
parameters: [Any]?,
mapper: @escaping (SqlCursor) throws -> RowType
) async throws -> [RowType]

/// Execute a read-only (SELECT) query and return a single optional result.
func getOptional<RowType>(
sql: String,
parameters: [Any]?,
mapper: @escaping (SqlCursor) -> RowType
) async throws -> RowType?

/// Execute a read-only (SELECT) query and return a single optional result.
func getOptional<RowType>(
sql: String,
parameters: [Any]?,
mapper: @escaping (SqlCursor) throws -> RowType
) async throws -> RowType?

/// Execute a read-only (SELECT) query every time the source tables are modified
/// and return the results as an array in a Publisher.
func watch<RowType>(
Expand All @@ -38,6 +61,14 @@ public protocol Queries {
mapper: @escaping (SqlCursor) -> RowType
) -> AsyncStream<[RowType]>

/// Execute a read-only (SELECT) query every time the source tables are modified
/// and return the results as an array in a Publisher.
func watch<RowType>(
sql: String,
parameters: [Any]?,
mapper: @escaping (SqlCursor) throws -> RowType
) -> AsyncStream<[RowType]>

/// Execute a write transaction with the given callback
func writeTransaction<R>(callback: @escaping (any PowerSyncTransaction) -> R) async throws -> R

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ final class KotlinPowerSyncDatabaseImplTests: XCTestCase {
parameters: ["1"]
) { cursor in
(
cursor.getString(index: 0)!,
cursor.getString(index: 1)!,
cursor.getString(index: 2)!
try cursor.getString(name: "id"),
try cursor.getString(name: "name"),
try cursor.getString(name: "email")
)
}

Expand Down Expand Up @@ -84,7 +84,10 @@ final class KotlinPowerSyncDatabaseImplTests: XCTestCase {
sql: "SELECT id, name FROM users ORDER BY id",
parameters: nil
) { cursor in
(cursor.getString(index: 0)!, cursor.getString(index: 1)!)
(
try cursor.getString(name: "id"),
try cursor.getString(name: "name")
)
}

XCTAssertEqual(users.count, 2)
Expand Down
Loading