Getting started on Kotlin JS with SQLDelight
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 {
sourceSets.jsMain.dependencies {
implementation "com.squareup.sqldelight:sqljs-driver:1.5.4"
}
}
Unlike on other platforms, the SqlJs driver can not be instantiated directly.
The driver must be loaded asynchronously by calling the initSqlDriver
function which returns a Promise<SqlDriver>
.
// As a Promise
val promise: Promise<SqlDriver> = initSqlDriver(Database.Schema)
promise.then { driver -> /* ... */ }
// In a coroutine
suspend fun createDriver() {
val driver: SqlDriver = initSqlDriver(Database.Schema).await()
/* ... */
}
If building for browsers, some additional webpack configuration is also required.
// project/webpack.conf.d/fs.js
config.resolve = {
fallback: {
fs: false,
path: false,
crypto: false,
}
};
// project/webpack.conf.d/wasm.js
const CopyWebpackPlugin = require('copy-webpack-plugin');
config.plugins.push(
new CopyWebpackPlugin({
patterns: [
{
from: '../../node_modules/sql.js/dist/sql-wasm.wasm',
to: '../../../{your project}/build/distributions'
}
]
})
);
SQL statements inside a .sq
file can be labeled to have a typesafe function generated for them available at runtime.
selectAll:
SELECT *
FROM hockeyPlayer;
insert:
INSERT INTO hockeyPlayer(player_number, full_name)
VALUES (?, ?);
insertFullPlayerObject:
INSERT INTO hockeyPlayer(player_number, full_name)
VALUES ?;
Files with labeled statements in them will have a queries file generated from them that matches the .sq
file name - putting the above sql into Player.sq
generates PlayerQueries.kt
. To get a reference to PlayerQueries
you need to wrap the driver we made above:
// In reality the database and driver above should be created a single time
// and passed around using your favourite dependency injection/service
// locator/singleton pattern.
val database = Database(driver)
val playerQueries: PlayerQueries = database.playerQueries
println(playerQueries.selectAll().executeAsList())
// Prints [HockeyPlayer(15, "Ryan Getzlaf")]
playerQueries.insert(player_number = 10, full_name = "Corey Perry")
println(playerQueries.selectAll().executeAsList())
// Prints [HockeyPlayer(15, "Ryan Getzlaf"), HockeyPlayer(10, "Corey Perry")]
val player = HockeyPlayer(10, "Ronald McDonald")
playerQueries.insertFullPlayerObject(player)
And that's it! Check out the other pages on the sidebar for other functionality.