PowerSync supports the SQLDelight library to safely build and run SQL statements on all platforms.
SQLDelight support is currently in beta.
https://mintcdn.com/powersync/T2mdeXADaWyXCq-s/logo/maven.svg?fit=max&auto=format&n=T2mdeXADaWyXCq-s&q=85&s=5d5148dc17eeb2df0dd8bf0e3235bfb0

Maven: com.powersync:integration-sqldelight

Features

When adopting SQLDelight with PowerSync, you can safely define your SQL statements and let the SQLDelight compiler generate code to map rows into typed classes. All Flows from SQLDelight will automatically update for PowerSync writes (including those from sync).

Installation

This guide assumes that you already have a PowerSync database for Kotlin. See the general documentation for notes on getting started with PowerSync. To use SQLDelight, you can generally follow SQLDelight documentation. A few steps are different though, and these are highlighted here. In addition to SQLDelight, add a dependency on com.powersync:integration-sqldelight. When defining your schema, note that the CREATE TABLE statements don’t actually run. PowerSync creates views for the schema passed to the PowerSyncDatabase factory instead. This also means that triggers, views and indexes defined in .sq files are ignored. To ensure your defined queries are valid, the CREATE TABLE syntax should still mirror your PowerSync schema. Since PowerSync links SQLite, configure SQLDelight to not do that in your build.gradle.kts file:
sqldelight {
    databases {
        linkSqlite.set(false)

        create("YourDatabase") {
            generateAsync.set(true)
            deriveSchemaFromMigrations.set(false)

            dialect("app.cash.sqldelight:sqlite-3-38-dialect")
        }
    }
}

Usage

Assuming that your SQLDelight database and its queries have been defined and that you’ve opened the PowerSyncDatabase, you can create your SQLDelight database ontop of PowerSync:
val powersync = PowerSyncDatabase(...)
val sqldelight = Yourdatabase(PowerSyncDriver(powersync))
That’s it! The PowerSyncDriver will automatically keep the two databases in sync and update SQLDelight flows for all writes, regardless of whether they’ve been issued against the sqldelight database or against the source powersync connection.

Example

CREATE TABLE todo_items (
    id TEXT NOT NULL,
    title TEXT NOT NULL,
    author_id TEXT NOT NULL  
);

all:
SELECT * FROM todo_items;

create:
INSERT INTO todo_items (id, title, author_id) VALUES (uuid(), ?, ?);
sqldelight.todosQueries.create("my title", "my content")

sqldelight.todosQueries.all().asFlow().mapToList(Dispatchers.IO).collect {
    println("This flow emits events for writes from SQLDelight and synced data from PowerSync")
}