Skip to content

Cursor Exceptions and Type Casts #23

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 18, 2025
Merged

Cursor Exceptions and Type Casts #23

merged 2 commits into from
Feb 18, 2025

Conversation

stevensJourney
Copy link
Contributor

@stevensJourney stevensJourney commented Feb 17, 2025

Overview

Cursor Exceptions

We currently support a SQL query cursor callback, which can throw exceptions if there are issues processing the result columns.

For example:

let _ = try await database.get(
    sql: "SELECT id, name, email FROM users WHERE id = ?",
    parameters: ["1"]
) { cursor in
    try (
        cursor.getString(name: "fakecolumn")
    )
}

In the above query, if the fakecolumn does not exist, an exception would be thrown during the mapping phase.

The current implementation uses a forced unwrap (try!) during the cursor's invocation. This could lead to a runtime crash if an exception occurs during the mapping process. Errors thrown in the cursor should propagate to the relevant execution method (such as get in the above example).

Unfortunately, throwing exceptions in a Swift callback passed internally to the Kotlin SDK is quite tricky. While we've managed to achieve this for read and write transactions here, the current method could potentially break compatibility with the existing Kotlin SDK's mapper parameter.

At present, we wrap the Kotlin SDK PowerSyncDatabase client directly in the Swift SDK, forcing us to use the "public" Kotlin SDK methods in Swift. Ideally, in the future, we would split the Kotlin SDK into smaller components and use the internals directly (with some modifications) to better accommodate Swift-specific behavior.

This PR implements a workaround by intercepting the mapper provided to the Kotlin SDK. Exceptions are tracked and manually propagated. Although this isn't the ideal solution, it works with the current setup. A better approach could be possible once the proposal above is implemented.

Type Casting

The Kotlin SDK query methods (get, execute, etc.) return Any after being processed by SKIEE. Currently, we explicitly cast the return type to the one provided by the mapper using as!. This forced as! cast can result in a runtime crash if there is an issue with the casting. While the cast should be safe in most cases, for consistency, we've now added safeguards to catch any potential casting errors and throw an exception that can be handled.

Formatting
I ran the modified files through swiftformat to clean up the code, which resulted in some formatting improvements.

@stevensJourney stevensJourney marked this pull request as ready for review February 17, 2025 14:30
@DominicGBauer
Copy link
Contributor

Code looks good to me, will do a test on the demo tomorrow

DominicGBauer
DominicGBauer previously approved these changes Feb 18, 2025
@stevensJourney stevensJourney merged commit abca0c9 into main Feb 18, 2025
1 check passed
@stevensJourney stevensJourney deleted the mapper-types branch February 18, 2025 13:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants