Skip to content

Multiplatform setup with the Web Worker Driver

First apply the gradle plugin in your project. Make sure to set generateAsync to true when creating your database.

plugins {
  id("app.cash.sqldelight") version "2.0.0-rc02"
}

repositories {
  google()
  mavenCentral()
}

sqldelight {
  databases {
    create("Database") {
      packageName.set("com.example")
      generateAsync.set(true)
    }
  }
}
plugins {
  id "app.cash.sqldelight" version "2.0.0-rc02"
}

repositories {
  google()
  mavenCentral()
}

sqldelight {
  databases {
    Database { // This will be the name of the generated database class.
      packageName = "com.example"
      generateAsync = true
    }
  }
}

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 PRIMARY KEY 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. Generating the Database file happens during the 'generateSqlDelightInterface' gradle task. This task runs during the 'make project'/'make module' build task, or automatically if you have the SQLDelight IDE plugin.

Accessing the generated database 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 "app.cash.sqldelight:android-driver:2.0.0-rc02"
  }

  // or sourceSets.iosMain, sourceSets.windowsMain, etc.
  sourceSets.nativeMain.dependencies {
    implementation "app.cash.sqldelight:native-driver:2.0.0-rc02"
  }

  sourceSets.jvmMain.dependencies {
    implementation "app.cash.sqldelight:sqlite-driver:2.0.0-rc02"
  }

  sourceSets.jsMain.dependencies {
    implementation "app.cash.sqldelight:sqljs-driver:2.0.0-rc02"
    implementation npm("sql.js", "1.6.2")
    implementation devNpm("copy-webpack-plugin", "9.1.0")
  }
}

Creating Drivers

First set up a way to create a driver in your common code. This can be done using expect/actual, or simply with a common interface a platform-specific implementations of the interface.

src/commonMain/kotlin
expect suspend fun provideDbDriver(
  schema: SqlSchema<QueryResult.AsyncValue<Unit>>
): SqlDriver
The SqlSchema interface contains a generic QueryResult type argument which is used to differentiate schema code that is generated with the generateAsync configuration option set to true. Some drivers rely on synchronous behaviours when creating or migrating the schema, so to use an asynchronous schema you can use the synchronous() extension method to adapt it for use with synchronous drivers.

actual suspend fun provideDbDriver(
  schema: SqlSchema<QueryResult.AsyncValue<Unit>>
): SqlDriver {
  return WebWorkerDriver(
    Worker(
      js("""new URL("@cashapp/sqldelight-sqljs-worker/sqljs.worker.js", import.meta.url)""")
    )
  ).also { schema.create(it).await() }
}
actual suspend fun provideDbDriver(
  schema: SqlSchema<QueryResult.AsyncValue<Unit>>
): SqlDriver {
  return JdbcSqliteDriver(JdbcSqliteDriver.IN_MEMORY)
    .also { schema.create(it).await() }
}
actual suspend fun provideDbDriver(
  schema: SqlSchema<QueryResult.AsyncValue<Unit>>
): SqlDriver {
  return AndroidSqliteDriver(schema.synchronous(), context, "test.db")
}
actual suspend fun provideDbDriver(
  schema: SqlSchema<QueryResult.AsyncValue<Unit>>
): SqlDriver {
  return NativeSqliteDriver(schema.synchronous(), "test.db")
}