Skip to content

About

Driver for library SQLDelight that supports sqlite3 Node.js module

Resources

Stars

5 stars

Watchers

1 watching

Forks

Repository files navigation

BUILD stability-beta Maven Central

sqldelight-node-sqlite-driver

Driver for the library SQLDelight that runs on Node.js with one of three SQLite modules:

Backend Artifact Node.js Native build
node:sqlite node-sqlite-driver-node-sqlite-js 24+ no, built into Node.js
better-sqlite3 node-sqlite-driver-better-sqlite3-js 22+ no, prebuilt binary in package
sqlite3 node-sqlite-driver-sqlite3-js 20+ yes, install script

All of them share node-sqlite-driver-core-js with the driver itself (SQLiteDriver), so you always add core and one backend.

node:sqlite is the easiest choice, no npm package and no install script. sqlite3 still depends on deprecated prebuild-install, which prints a warning on every clean install.

Gradle set up

Pretty much it's almost the same as with https://sqldelight.github.io/sqldelight/2.4.0/js_sqlite

Initialization of SQLDelight is needed

plugins {
    kotlin("multiplatform") version "2.4.20" // probably would work even with different one
    id("app.cash.sqldelight") version "2.4.1"
}
፧
፧
፧
sqldelight {
    databases {
        create("Database") {
            packageName.set("com.example")
            generateAsync.set(true) // required for this driver!
        }
    }
}

Add dependency to core and to one backend:

kotlin {
    js {
        binaries.executable()
        nodejs()
    }
    sourceSets {
        jsMain.dependencies {
            implementation("cz.sazel.sqldelight:node-sqlite-driver-core-js:1.1.0")
            implementation("cz.sazel.sqldelight:node-sqlite-driver-node-sqlite-js:1.1.0")
            // or node-sqlite-driver-better-sqlite3-js / node-sqlite-driver-sqlite3-js
        }
    }
}

Install scripts for sqlite3

Kotlin's Yarn skips npm install scripts by default, so sqlite3 would miss its native binding. Turn them on in the root project:

import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootEnvSpec

plugins.withType<YarnPlugin> {
    the<YarnRootEnvSpec>().ignoreScripts.set(false)
}

node:sqlite and better-sqlite3 don't need this.

Simple example

Queries are written as here - https://sqldelight.github.io/sqldelight/2.4.0/js_sqlite/#using-queries

import cz.sazel.sqldelight.node.sqlite.initNodeSqliteSqlDriver

suspend fun main() {
    val driver = initNodeSqliteSqlDriver(filename = "test.db", schema = Database.Schema)

    val database = Database(driver)

    val playerQueries: PlayerQueries = database.playerQueries

    println(playerQueries.selectAll().awaitAsList())
    // Prints [HockeyPlayer(15, "Ryan Getzlaf")]

    playerQueries.insert(player_number = 10, full_name = "Corey Perry")
    println(playerQueries.selectAll().awaitAsList())
    // Prints [HockeyPlayer(15, "Ryan Getzlaf"), HockeyPlayer(10, "Corey Perry")]

    val player = HockeyPlayer(20, "Ronald McDonald")
    playerQueries.insertFullPlayerObject(player)

    driver.close()
}

Init function per backend:

Backend Function
node:sqlite cz.sazel.sqldelight.node.sqlite.initNodeSqliteSqlDriver
better-sqlite3 cz.sazel.sqldelight.node.sqlite.betterSqlite3.initBetterSqlite3SqlDriver
sqlite3 cz.sazel.sqldelight.node.sqlite3.initSqlite3SqlDriver

Note: Please use awaitAsList() or executeAsFlow() in queries instead of executeAsList() as that API is not suspending and will throw an exception with this driver.

The API is asynchronous for all backends. sqlite3 runs queries on libuv threads by itself, node:sqlite and better-sqlite3 run them in a worker thread. That one has some build requirements and option for parallel reads, see Worker threads.

Upgrade from 0.9.x

Artifacts and some package names changed in 1.0.0, steps are in Upgrade from 0.9.x to 1.0.0.

Limitations

  • Long (SQLite INTEGER) columns round-trip exactly only up to 2^53 (JS's safe integer range), because binding and reading a value both pass through a JS Number. Binding or reading a value beyond 2^53 throws SQLiteException instead of silently losing precision. Same for all backends.

Transactions

By default a transaction starts with BEGIN TRANSACTION (deferred locking). Pass beginImmediate = true to init function to start with BEGIN IMMEDIATE instead, which acquires the write lock up front instead of failing with SQLITE_BUSY when the transaction later upgrades from a read lock:

val driver = initNodeSqliteSqlDriver(filename = "test.db", schema = Database.Schema, beginImmediate = true)

AI disclaimer

AI/LLM assistance is used in every step of the development process.

Thanks

To Isuru Rajapakse and the project KStore which is an inspiration for the set-up of publishing in Gradle scripts.

To authors of SQLDelight, implementation is based on the sqljs implementation of the driver which is already included in the library.s.

License

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

About

Driver for library SQLDelight that supports sqlite3 Node.js module

Resources

Stars

5 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages