Multiplatform setup with the SqlJs Driver
First apply the gradle plugin in your project.
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.squareup.sqldelight:gradle-plugin:1.5.4'
}
}
apply plugin: 'com.squareup.sqldelight'
sqldelight {
Database { // This will be the name of the generated database class.
packageName = "com.example"
}
}
Put your SQL statements in a .sq
file under src/main/sqldelight
. Typically the first statement in the SQL file creates a table.
-- src/main/sqldelight/com/example/sqldelight/hockey/data/Player.sq
CREATE TABLE hockeyPlayer (
player_number INTEGER NOT NULL,
full_name TEXT NOT NULL
);
CREATE INDEX hockeyPlayer_full_name ON hockeyPlayer(full_name);
INSERT INTO hockeyPlayer (player_number, full_name)
VALUES (15, 'Ryan Getzlaf');
From this SQLDelight will generate a Database
Kotlin class with an associated Schema
object that can be used to create your database and run your statements on it. Doing this also requires a driver, which SQLDelight provides implementations of:
kotlin {
// The drivers needed will change depending on what platforms you target:
sourceSets.androidMain.dependencies {
implementation "com.squareup.sqldelight:android-driver:1.5.4"
}
// or sourceSets.iosMain, sourceSets.windowsMain, etc.
sourceSets.nativeMain.dependencies {
implementation "com.squareup.sqldelight:native-driver:1.5.4"
}
sourceSets.jvmMain.dependencies {
implementation "com.squareup.sqldelight:sqlite-driver:1.5.4"
}
sourceSets.jsMain.dependencies {
implementation "com.squareup.sqldelight:sqljs-driver:1.5.4"
}
}
Because the SqlJs driver must be initialized asynchronously, the drivers for other platforms must be initialized in a compatible way to be usable in a common source set.
The drivers can be initialized in a coroutine, and a higher-order function can be used to ensure that the driver is initialized before executing a block of code that requires the database:
// in src/commonMain/kotlin
expect suspend fun provideDbDriver(schema: SqlDriver.Schema): SqlDriver
class SharedDatabase(
private val driverProvider: suspend (SqlDriver.Schema) -> SqlDriver
) {
private var database: Database? = null
suspend fun initDatabase() {
if (database == null) {
database = driverProvider(Database.Schema).createDatabase()
}
}
suspend operator fun <R> invoke(block: suspend (Database) -> R): R {
initDatabase()
return block(database!!)
}
private fun SqlDriver.createDatabase(): Database { /* ... */ }
}
val sharedDb = SharedDatabase(::createTestDbDriver)
class DataRepository(
private val withDatabase: SharedDatabase = sharedDb
) {
suspend fun getData() = withDatabase { database ->
/* Do something with the database */
}
}
// in src/jsMain/kotlin
actual suspend fun provideDbDriver(schema: SqlDriver.Schema): SqlDriver {
return initSqlDriver(schema).await()
}
// in src/nativeMain/kotlin
actual suspend fun provideDbDriver(schema: SqlDriver.Schema): SqlDriver {
return NativeSqliteDriver(schema, "test.db")
}
// in src/jvmMain/kotlin
actual suspend fun provideDbDriver(schema: SqlDriver.Schema): SqlDriver {
return JdbcSqliteDriver(JdbcSqliteDriver.IN_MEMORY).also { driver ->
schema.create(driver)
}
}