Skip to content

Commit a2077e6

Browse files
committed
Add SQLDelight driver
# Conflicts: # gradle/libs.versions.toml
1 parent 37ddc67 commit a2077e6

File tree

11 files changed

+637
-5
lines changed

11 files changed

+637
-5
lines changed

compose/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ plugins {
88
alias(libs.plugins.compose.compiler)
99
alias(libs.plugins.kotlinter)
1010
id("com.powersync.plugins.sonatype")
11+
id("com.powersync.plugins.sharedbuild")
1112
id("dokka-convention")
1213
}
1314

gradle/libs.versions.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ compose-lifecycle = "2.9.2"
3333
androidxSqlite = "2.6.0-rc02"
3434
androidxSplashscreen = "1.0.1"
3535
room = "2.8.0-rc02"
36+
sqldelight = "2.1.0"
3637

3738
# plugins
3839
android-gradle-plugin = "8.12.1"
@@ -103,6 +104,9 @@ androidx-sqlite-sqlite = { module = "androidx.sqlite:sqlite", version.ref = "and
103104
androidx-sqlite-bundled = { module = "androidx.sqlite:sqlite-bundled", version.ref = "androidxSqlite" }
104105
androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" }
105106
androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" }
107+
sqldelight-coroutines = { module = "app.cash.sqldelight:coroutines-extensions", version.ref = "sqldelight" }
108+
sqldelight-runtime = { module = "app.cash.sqldelight:runtime", version.ref = "sqldelight" }
109+
sqldelight-dialect-sqlite38 = { module = "app.cash.sqldelight:sqlite-3-38-dialect", version.ref = "sqldelight" }
106110

107111
# Sample - Android
108112
androidx-core = { group = "androidx.core", name = "core-ktx", version.ref = "androidx-core" }
@@ -151,3 +155,4 @@ kotlin-atomicfu = { id = "org.jetbrains.kotlinx.atomicfu", version.ref = "atomic
151155
buildKonfig = { id = "com.codingfeline.buildkonfig", version.ref = "buildKonfig" }
152156
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
153157
androidx-room = { id = "androidx.room", version.ref = "room" }
158+
sqldelight = { id = "app.cash.sqldelight", version.ref = "sqldelight" }
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import com.powersync.plugins.utils.powersyncTargets
2+
import org.jmailen.gradle.kotlinter.tasks.FormatTask
3+
import org.jmailen.gradle.kotlinter.tasks.LintTask
4+
5+
plugins {
6+
alias(libs.plugins.kotlinMultiplatform)
7+
alias(libs.plugins.kotlinter)
8+
alias(libs.plugins.sqldelight)
9+
id("com.powersync.plugins.sharedbuild")
10+
}
11+
12+
kotlin {
13+
// We don't test on Android devices, JVM tests are enough for the SQLDelight test package since
14+
// it doesn't contain Android-specific code.
15+
powersyncTargets(android = false)
16+
17+
explicitApi()
18+
applyDefaultHierarchyTemplate()
19+
20+
sourceSets {
21+
commonMain.dependencies {
22+
api(libs.sqldelight.runtime)
23+
}
24+
}
25+
}
26+
27+
sqldelight {
28+
databases {
29+
linkSqlite.set(false)
30+
31+
create("TestDatabase") {
32+
packageName.set("com.powersync.integrations.sqldelight")
33+
generateAsync.set(true)
34+
deriveSchemaFromMigrations.set(false)
35+
dialect(libs.sqldelight.dialect.sqlite38)
36+
}
37+
}
38+
}
39+
40+
tasks.withType<LintTask> {
41+
exclude { it.file.path.contains("build/generated") }
42+
}
43+
44+
tasks.withType<FormatTask> {
45+
exclude { it.file.path.contains("build/generated") }
46+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CREATE TABLE todos (
2+
id TEXT NOT NULL DEFAULT '',
3+
title TEXT,
4+
content TEXT
5+
);
6+
7+
all:
8+
SELECT * FROM todos;
9+
10+
create:
11+
INSERT INTO todos (id, title, content) VALUES (uuid(), ?, ?);

integrations/sqldelight/README.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
## PowerSync SQLDelight driver
2+
3+
This library provides the `PowerSyncDriver` class, which implements an `SqlDriver` for `SQLDelight`
4+
backed by PowerSync.
5+
6+
## Setup
7+
8+
Add a dependency on `com.powersync:integration-sqldelight`, using the same version you use for the
9+
PowerSync SDK.
10+
11+
## Usage
12+
13+
To get started, ensure that SQLDelight is not linking sqlite3 (the PowerSync SDK takes care of that,
14+
and you don't want to link it twice). Also, ensure the async generator is active because the
15+
PowerSync driver does not support synchronous reads:
16+
17+
```kotlin
18+
sqldelight {
19+
databases {
20+
linkSqlite.set(false)
21+
22+
create("MyAppDatabase") {
23+
generateAsync.set(true)
24+
deriveSchemaFromMigrations.set(false)
25+
26+
dialect("app.cash.sqldelight:sqlite-3-38-dialect")
27+
}
28+
}
29+
}
30+
```
31+
32+
Next, define your tables in `.sq` files (but note that the `CREATE TABLE` statement won't be used,
33+
PowerSync creates JSON-backed views for tables instead).
34+
Open a PowerSync database [in the usual way](https://docs.powersync.com/client-sdk-references/kotlin-multiplatform#getting-started)
35+
and finally pass it to the constructor of your generated SQLDelight database:
36+
37+
```kotlin
38+
val db: PowerSyncDatabase = openPowerSyncDatabase()
39+
val yourSqlDelightDatabase = YourDatabase(PowerSyncDriver(db))
40+
```
41+
42+
Afterwards, writes on both databases (the original `PowerSyncDatabase` instance and the SQLDelight
43+
database) will be visible to each other, update each other's query flows and will get synced
44+
properly.
45+
46+
## Limitations
47+
48+
Please note that this library is currently in alpha. It is tested, but API changes are still
49+
possible.
50+
51+
There are also some limitations to be aware of:
52+
53+
1. Due to historical reasons, the PowerSync SDK migrates all databases to `user_version` 1 when
54+
created (but it will never downgrade a database).
55+
So if you want to use SQLDelight's schema tools, the first version would have to be `2`.
56+
2. While you can write `CREATE TABLE` statements in your `.sq` files, note that these aren't
57+
actually used - you still have to define your PowerSync schema and the SDK will auto-create the
58+
tables from there.
59+
If you want to use the schema managed by SQLDelight, configure PowerSync to use
60+
[raw tables](https://docs.powersync.com/usage/use-case-examples/raw-tables).
61+
3. Functions and tables contributed by the PowerSync core extension are not visible to `.sq` files
62+
at the moment. We might revisit this with a custom dialect in the future.
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import com.powersync.plugins.utils.powersyncTargets
2+
3+
plugins {
4+
alias(libs.plugins.kotlinMultiplatform)
5+
alias(libs.plugins.android.library)
6+
alias(libs.plugins.kotlinter)
7+
alias(libs.plugins.kotlin.atomicfu)
8+
id("com.powersync.plugins.sonatype")
9+
id("dokka-convention")
10+
}
11+
12+
kotlin {
13+
powersyncTargets()
14+
explicitApi()
15+
applyDefaultHierarchyTemplate()
16+
17+
sourceSets {
18+
commonMain.dependencies {
19+
api(projects.core)
20+
api(libs.sqldelight.runtime)
21+
implementation(libs.kotlinx.coroutines.core)
22+
}
23+
24+
jvmTest.dependencies {
25+
// Separate project because SQLDelight can't generate code in test source sets.
26+
implementation(projects.integrations.sqldelightTestDatabase)
27+
28+
implementation(libs.kotlin.test)
29+
implementation(libs.test.turbine)
30+
implementation(libs.test.coroutines)
31+
implementation(libs.test.kotest.assertions)
32+
33+
implementation(libs.sqldelight.coroutines)
34+
}
35+
}
36+
}
37+
38+
android {
39+
namespace = "com.powersync.drivers.common"
40+
compileSdk =
41+
libs.versions.android.compileSdk
42+
.get()
43+
.toInt()
44+
defaultConfig {
45+
minSdk =
46+
libs.versions.android.minSdk
47+
.get()
48+
.toInt()
49+
}
50+
kotlin {
51+
jvmToolchain(17)
52+
}
53+
}
54+
55+
dokka {
56+
moduleName.set("PowerSync for SQLDelight")
57+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
POM_ARTIFACT_ID=integration-sqldelight
2+
POM_NAME=PowerSync SQLDelight driver
3+
POM_DESCRIPTION=Use a PowerSync database for your SQLDelight database.

0 commit comments

Comments
 (0)