Alec Strong Jake Wharton data class Player(A val name: String, val ranking: Int, val country: String )A @Entity data class Player(A val name: String, val ranking: Int, val country: String )A @Entity data class Player(A val name: String, val ranking: Int, val country: String )A
@Entity data class Match(A val player1: Player, val player2: Player, val winner: Player )A Annotation Processor
@Entity data class Player(A val name: String, val ranking: Int, val country: String )A
@Entity data class Match(A Source val player1: PlayerCode, val player2: Player, val winner: Player )A
Reflection Annotation Processor
@Entity data class Player(A val name: String, val ranking: Int, val country: String )A
@Entity data class Match(A Source val player1: PlayerCode, SQLite val player2: Player, val winner: Player )A
Reflection CREATE TABLE player (A name TEXT NOT NULL, country TEXT NOT NULL, ranking INTEGER NOT NULL );
CREATE TABLE match (A player1 INTEGER NOT NULL REFERENCES player, player2 INTEGER NOT NULL REFERENCES player, winner INTEGER NOT NULL REFERENCES player ); CREATE TABLE player (A id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, country TEXT NOT NULL, ranking INTEGER NOT NULL );
CREATE TABLE match (A player1 INTEGER NOT NULL REFERENCES player, player2 INTEGER NOT NULL REFERENCES player, winner INTEGER NOT NULL REFERENCES player );B CREATE TABLE player (A id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, country TEXT NOT NULL, ranking INTEGER NOT NULL );
CREATE TABLE match (A player1 INTEGER NOT NULL REFERENCES player, player2 INTEGER NOT NULL REFERENCES player, winner INTEGER NOT NULL REFERENCES player, PRIMARY KEY (player1, player2) ) WITHOUT ROWID;B Annotation Processor
@Entity CREATE TABLE player (A data class Player( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, val name: String, name TEXT NOT NULL, val ranking: Int, country TEXT NOT NULL, ranking INTEGER NOT NULL val country: String ); ) CREATE TABLE match (A @Entity player1 INTEGER NOT NULL REFERENCES player, Sourcedata class Match( Code player2 INTEGERSQLite NOT NULL REFERENCES player, val player1: Player, winner INTEGER NOT NULL REFERENCES player, val player2: Player, PRIMARY KEY (player1, player2) val winner: Player ) WITHOUT ROWID; )
Reflection @Entity data class Player(A val name: String, val ranking: Int, val country: String )A
@Entity data class Match(A val player1: Player, val player2: Player, val winner: Player )A @Entity data class Player(A @PrimaryKey @Autoincrement val id: Int, val name: String, val ranking: Int, val country: String )A
@Entity data class Match(A val player1: Player, val player2: Player, val winner: Player )A @Entity data class Player(A @PrimaryKey @Autoincrement val id: Int, val name: String, val ranking: Int, val country: String )A
@Entity(primaryKeys = ['player1', ‘player2']) data class Match(A val player1: Player, val player2: Player, val winner: Player )A @Entity dataA class Player(A @PrimaryKey @Autoincrement val id: Int, val name: String, val ranking: Int, val country: String )A
@Entity(primaryKeys = ['player1', ‘player2']) data class Match(A val player1: Player, val player2: Player, val winner: Player )A ALTER TABLE player ADD COLUMN id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT;
CREATE TABLE new_match ( player1 INTEGER NOT NULL REFERENCES player, player2 INTEGER NOT NULL REFERENCES player, winner INTEGER NOT NULL REFERENCES player, PRIMARY KEY (player1, player2) ) WITHOUT ROWID;
-- migrate match to new_match QueryBuilders
QueryBuilders
jakes.link/resurgence-of-sql SQL Delight Annotation Processor
Source Code SQLite
Reflection Generated SQLite Compiler Code CREATE TABLE player (A id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, country TEXT NOT NULL, ranking INTEGER NOT NULL ); CREATE TABLE player (A id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, country TEXT NOT NULL, ranking INTEGER NOT NULL ); withRanking: SELECT * FROM player WHERE ranking = ?; CREATE TABLE player (A id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, country TEXT NOT NULL, ranking INTEGER NOT NULL Generated ); withRanking:SQLite Compiler SELECT * FROM player WHERE ranking = ?; Code interface PlayerModel {A long id(); @NonNull String name(); @NonNull String country(); long ranking();
final class Factory
public SqlDelightQuery withRanking(long ranking);
public RowMapper
@AutoValue public abstract class MyPlayerModel implements PlayerModel {A public static Factory
public SqlDelightQuery withRanking(long ranking);
public RowMapper
SqlDelightStatement query = MyPlayerModel.FACTORY.withRanking(10); Observable> rank10 = db.createQuery(query.tables, query.statement, query.args) .mapToList(MyPlayerModel.FACTORY::withRankingMapper); SQL Delight 0.7
QueryBuilders
jakes.link/embracing-sql SQL Delight 1.0 CREATE TABLE player ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, country TEXT NOT NULL, ranking INTEGER NOT NULL ); withRanking: Generated SELECT * FROM player SQLite Compiler WHERE ranking = ?; insertPlayer: INSERT INTO player (name, country, ranking) Code VALUES (?, ?, ?); CREATE TABLE player ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, country TEXT NOT NULL, ranking INTEGER NOT NULL ); withRanking: SELECT * FROM player WHERE ranking = ?; insertPlayer: INSERT INTO player (name, country, ranking) VALUES (?, ?, ?); CREATE TABLE player ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, country TEXT NOT NULL, ranking INTEGER NOT NULL ); withRanking: Generated SELECT * FROM player SQLite Compiler WHERE ranking = ?; insertPlayer: INSERT INTO player (name, country, ranking) Code VALUES (?, ?, ?); interface Player {A val id: Long val name: String val country: String val ranking: Long
data class Impl(A override val id: Long, override val name: String, override val country: String, override val ranking: Long ) : Player }A class PlayerQueries : Transacter {A fun
fun withRanking(ranking: Long): Query
fun insertPlayer( name: String, country: String, ranking: Long ): Long }A headToHead: SELECT player1.name AS player1Name, player2.name AS player2Name, count(nullif(match.winner = player1.id, 0)) AS player1Wins, count(nullif(match.winner = player2.id, 0)) AS player2Wins FROM match JOIN player AS player1 ON (player1.name = :firstPlayerName AND (player1.id = match.player1 OR player1.id = match.player2) ) JOIN player AS player2 ON (player2.name = :secondPlayerName AND (player2.id = match.player1 OR player2.id = match.player2) ) ; class PlayerQueries : Transacter {A fun
fun headToHead( firstPlayerName: String, secondPlayerName: String ): Query
fun withRanking(ranking: Long): Query
fun insertPlayer( name: String, country: String, ranking: Long ): Long }A class PlayerQueries : Transacter {A fun withRanking(ranking: Long): Query
val player: Query
val player: Query< Player => playerQueries.withRanking(10).executeAsOne() class PlayerQueries : Transacter {A fun withRanking(ranking: Long): Query
val player: Observable
val player: Observable> = playerQueries.withRanking(10) .asObservable() .mapToList() class PlayerQueries : Transacter {A fun
val player = playerQueries.withRanking(10, ::MyPlayer) class PlayerQueries : Transacter {A fun insertPlayer( name: String, country: String, ranking: Long ): Long }A
val id = playerQueries.insertPlayer( name = "Roger Federer", country = "Switzerland", ranking = 2 ) CREATE TABLE player (A id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, class PlayerQueries : Transacter {A country TEXT NOT NULL, fun insertPlayer( ranking INTEGER NOT NULL Generated name: String, ); country: String, ranking: Long SQLite Compiler ): Long withRanking: }A SELECT * FROM player Code WHERE ranking = ?; CREATE TABLE player ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, country TEXT NOT NULL, ranking INTEGER NOT NULL ); import com.tennis.db.CountryCode;
CREATE TABLE player ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, country TEXT AS CountryCode NOT NULL, ranking INTEGER NOT NULL ); import com.tennis.db.CountryCode;
CREATE TABLE player ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, country TEXT AS CountryCode NOT NULL, ranking INTEGER NOT NULL ); import com.tennis.db.CountryCode;
CREATE TABLE player ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, Generated name TEXT NOT NULL, country TEXTSQLite AS CountryCode NOT NULL, Compiler ranking INTEGER NOT NULL ); Code class QueryWrapper( database: SqlDatabase, internal val playerAdapter: Player.Adapter ) {A val playerQueries: PlayerQueries }A class QueryWrapper( database: SqlDatabase, internal val playerAdapter: Player.Adapter ) {A val playerQueries: PlayerQueries }A interface Player {A class Adapter( val countryAdapter: ColumnAdapter
val queryWrapper = QueryWrapper( database = database, playerAdapter = Player.Adapter( countryAdapter = EnumColumnAdapter() ), ) class QueryWrapper( database: SqlDatabase, internal val playerAdapter: Player.Adapter ) {A val playerQueries: PlayerQueries }A
val queryWrapper = QueryWrapper( database = database, playerAdapter = Player.Adapter( countryAdapter = EnumColumnAdapter() ), ) val playerQueries: PlayerQueries = queryWrapper.playerQueries class QueryWrapper {A object Schema : SqlDatabase.Schema {A override val version: Int get() = 2
override fun create(db: SqlDatabaseConnection)
override fun migrate( db: SqlDatabaseConnection, oldVersion: Int, newVersion: Int ) }A }A class QueryWrapper {A object Schema : SqlDatabase.Schema {A CREATE TABLE player (A override val version: Int id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, get() = 2 name TEXT NOT NULL, country TEXT NOT NULL, override fun create(db: SqlDatabaseConnection) ranking INTEGER NOT NULL Generated ); override fun migrate( db: SqlDatabaseConnection, SQLite Compiler oldVersion: Int, withRanking: newVersion: Int SELECT * ) FROM player }A Code WHERE ranking = ?; }A SQLite
Generated Compiler Code
SQLite Migrations ALTER TABLE player ADD COLUMN id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT;
CREATE TABLE new_match ( player1 INTEGER NOT NULL REFERENCES player, player2 INTEGER NOT NULL REFERENCES player, winner INTEGER NOT NULL REFERENCES player, PRIMARY KEY (player1, player2) ) WITHOUT ROWID;
-- migrate match to new_match SQLite
Generated Compiler Code
ALTER TABLE player ADD COLUMN id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT;
CREATE TABLE new_match ( player1 INTEGERSQLite NOT NULL REFERENCES player, player2 INTEGER NOT NULL REFERENCES player, winner INTEGER NOT NULL REFERENCES player, PRIMARY KEY (player1, player2) ) WITHOUT ROWID; -- migrateMigrations match to new_match SQL Delight 1.0 SQL Delight Multiplatform? SQL Delight Multiplatform? CashApp api proto
viewmodels CashApp presenters
backend db db db
CREATE TABLE player (A id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, country TEXT NOT NULL, ranking INTEGER NOT NULL Generated ); SQLite SQL Delight withRanking: SELECT * FROM player Code WHERE ranking = ?; db
Generated SQLite SQL Delight Code db
Generated SQL Delight Code
SQLite
Generated Compiler Swift Code protos
Generated wire Java
.proto
protoc Generated C db
Generated SQL Delight Code
SQLite
Generated Compiler Swift Code db
Generated SQL Delight Code
SQLite kotlinc Android Generated Code Kotlin/Native Native kotlinc Android
Kotlin/Native Native Generated Code kotlinc JVM
kotlin2js JavaScript Android Native
JVM JavaScript Android Native
android.database.* android.database.sqlite.*
JVM JavaScript Android Native
android.database.* sqlite3.h android.database.sqlite.*
JVM JavaScript Android Native
android.database.* sqlite3.h android.database.sqlite.*
JVM JavaScript
java.sql.* org.sqlite.* Android Native
android.database.* sqlite3.h android.database.sqlite.*
JVM JavaScript
java.sql.* org.sqlite.* (xerial) Android Native
android.database.* sqlite3.h android.database.sqlite.*
JVM JavaScript
java.sql.* Node? WASM? Vanilla JS? org.sqlite.* (xerial) android.database.* android.database.sqlite.*Android
sqlite3.hNative Generated Code java.sql.* org.sqlite.* JVM (xerial)
Node? WASM?JavaScript Vanilla JS? android.database.* android.database.sqlite.*Android
sqlite3.hNative Generated Database Code Abstraction java.sql.* org.sqlite.* JVM (xerial)
Node? WASM?JavaScript Vanilla JS? Database Abstraction
SqlDatabase Database Abstraction
SqlDatabase.Schema
SqlDatabase Database Abstraction
SqlDatabase.Schema
SqlDatabase SqlPreparedStatement Database Abstraction
SqlDatabase.Schema
SqlPreparedStatement SqlDatabase
Transacter.Transaction Database Abstraction
SqlDatabase.Schema
SqlPreparedStatement SqlDatabase
Transacter.Transaction Transacter Database Abstraction
SqlDatabase.Schema
SqlPreparedStatement SqlDatabase
Transacter.Transaction Transacter Database Abstraction
SqlDatabase.Schema
SqlPreparedStatement SqlCursor SqlDatabase
Transacter.Transaction Transacter Database Abstraction
SqlDatabase.Schema Query
SqlPreparedStatement SqlCursor SqlDatabase
Transacter.Transaction Transacter android.database.* android.database.sqlite.*Android
sqlite3.hNative Generated SqlDatabaseQ Code S AbstractionSql S Tran T java.sql.* org.sqlite.* JVM (xerial)
Node? WASM?JavaScript Vanilla JS? Android android.database.* Driver android.database.sqlite.*Android
knarch.db sqlite3.h Driver Native Generated Database Code Abstraction JDBC java.sql.* Driver org.sqlite.* JVM (xerial)
JS Driver Node? WASM?JavaScript Vanilla JS? Android android.database.* Driver android.database.sqlite.*Android
knarch.db sqlite3.h Driver Native Database Abstraction JDBC java.sql.* Driver org.sqlite.* JVM (xerial)
JS Driver Node? WASM?JavaScript Vanilla JS? Android AndroidX Sqlite AndroidX Sqlite android.database.* Driver Abstraction Framework Impl android.database.sqlite.*Android knarch.db sqlite3.h Driver Native
JDBC java.sql.* Driver org.sqlite.* JVM (xerial)
JS Driver Node? WASM?JavaScript Vanilla JS? AndroidX Sqlite android.database.* Framework Impl android.database.sqlite.*Android Android AndroidX Sqlite Driver Abstraction
AndroidX android.database.* knarch.db SQLCipher Impl net.sqlcipher.database.*Android sqlite3.h Driver Native
JDBC java.sql.* Driver org.sqlite.* JVM (xerial)
JS Driver Node? WASM?JavaScript Vanilla JS? AndroidX Sqlite android.database.* Framework Impl android.database.sqlite.*Android Android AndroidX Sqlite Driver Abstraction
AndroidX android.database.* knarch.db SQLCipher Impl net.sqlcipher.database.*Android sqlite3.h Driver Native Generated Database Code Abstraction JDBC java.sql.* Driver org.sqlite.* JVM (xerial)
JS Driver Node? WASM?JavaScript Vanilla JS? AndroidX Sqlite android.database.* Framework Impl android.database.sqlite.*Android Android AndroidX Sqlite Driver Abstraction
AndroidX android.database.* knarch.db SQLCipher Impl net.sqlcipher.database.*Android AAA sqlite3.h Driver Native Generated Database Code Abstraction JDBC java.sql.* Driver org.sqlite.* JVM (xerial)
JS Node? WASM? Vanilla JS? Driver JavaScriptBBB Android AndroidX Sqlite Driver Abstraction
AndroidX android.database.* knarch.db SQLCipher Impl net.sqlcipher.database.*Android AAA sqlite3.h Driver Native Generated Database Code Abstraction JDBC java.sql.* Driver org.sqlite.* JVM (xerial)
JS Node? WASM? Vanilla JS? Driver JavaScriptBBB Android AndroidX Sqlite Driver Abstraction
AndroidX android.database.* knarch.db SQLCipher Impl net.sqlcipher.database.*Android sqlite3.h Driver Native Generated Database Code Abstraction JDBC java.sql.* Driver org.sqlite.* JVM (xerial)
Node? WASM?JavaScript Vanilla JS? AndroidX Sqlite android.database.* Framework Impl android.database.sqlite.*Android Android AndroidX Sqlite Driver Abstraction
AndroidX android.database.* knarch.db SQLCipher Impl net.sqlcipher.database.*Android sqlite3.h Driver Generated Database Native Code Abstraction JDBC java.sql.* Driver org.sqlite.* JVM (xerial)
Node?JavaScript WASM? Vanilla JS? AndroidX Sqlite android.database.* Framework Impl android.database.sqlite.*Android Android AndroidX Sqlite Driver Abstraction
AndroidX android.database.* knarch.db SQLCipher Impl net.sqlcipher.database.*Android sqlite3.h Driver Generated Database Native Code Abstraction JDBC java.sql.* Driver org.sqlite.* JVM (xerial)
Node?JavaScript WASM? Vanilla JS? Database Abstraction
SqlDatabase.Schema Query
SqlPreparedStatement SqlCursor SqlDatabase
Transacter.Transaction Transacter Database Abstraction
SqlDatabase.Schema Query
SqlPreparedStatement SqlCursor SqlDatabase
Transacter.Transaction Transacter package com.squareup.sqldelight.db expect interface Closeable { fun close() } expect inline fun
// settings.gradle enableFeaturePreview('GRADLE_METADATA') com.squareup.sqldelight + runtime com.squareup.sqldelight - runtime runtime-1.0.0-sources.jar runtime-1.0.0-javadoc.jar runtime-1.0.0.pom runtime-1.0.0.module runtime-1.0.0.module
{ "variants": [ { "name": "iosArm64-api", "available-at": { "url": "../../runtime-iosarm64/runtime-iosarm64-1.0.0.module" } }, ... ] } com.squareup.sqldelight - runtime runtime-1.0.0-sources.jar runtime-1.0.0-javadoc.jar runtime-1.0.0.pom runtime-1.0.0.module com.squareup.sqldelight + runtime com.squareup.sqldelight + runtime + runtime-common + runtime-iosarm64 + runtime-iosx64 + runtime-jvm + runtime-js com.squareup.sqldelight + android-driver + runtime + runtime-common + runtime-iosarm64 + runtime-iosx64 + runtime-jvm + runtime-js com.squareup.sqldelight - android-driver android-driver-1.0.0.aar android-driver-1.0.0-javador.jar android-driver-1.0.0-sources.jar android-driver-1.0.0-pom.xml + runtime + runtime-common + runtime-iosarm64 + runtime-iosx64 + runtime-jvm + runtime-js com.squareup.sqldelight - android-driver android-driver-1.0.0.aar android-driver-1.0.0-javador.jar android-driver-1.0.0-sources.jar android-driver-1.0.0-pom.xml + runtime + runtime-common + runtime-iosarm64 + runtime-iosx64 + runtime-jvm + runtime-js com.squareup.sqldelight - android-driver android-driver-1.0.0.aar android-driver-1.0.0-javador.jar android-driver-1.0.0-sources.jar android-driver-1.0.0-pom.xml + runtime + runtime-common + runtime-iosarm64 + runtime-iosx64 + runtime-jvm + runtime-js com.squareup.sqldelight - android-driver android-driver-1.0.0.aar android-driver-1.0.0-javador.jar android-driver-1.0.0-sources.jar android-driver-1.0.0-pom.xml + runtime + runtime-common + runtime-iosarm64 + runtime-iosx64 + runtime-jvm + runtime-js + runtime-jdk apply plugin: ‘com.android.application’ apply plugin: 'org.jetbrains.kotlin.multiplatform' dependencies {A implementation 'com.squareup.sqldelight:android-driver:1.0.0' }A kotlin {A sourceSets {A commonMain {A dependencies {A implementation project(':sqldelight-sample:sample-common') }A }A }A }A apply plugin: ‘com.android.application’ apply plugin: 'org.jetbrains.kotlin.multiplatform' dependenciesA {A implementation 'com.squareup.sqldelight:android-driver:1.0.0''com.squareup.sqldelight:android-driver:1.0.0' }AA kotlin {A sourceSets {A commonMain {A A dependencies {A implementation project(':sqldelight-sample:sample-common') }A }A }A }A apply plugin: ‘com.android.application’ apply plugin: 'org.jetbrains.kotlin.multiplatform' dependencies {A implementation (“com.squareup.sqldelight:android-driver:1.0.0'com.squareup.sqldelight:android-driver:1.0.0')) {A{ A exclude group: 'com.squareup.sqldelight', module: 'runtime-jdk' }A }A kotlin {A sourceSets {A commonMain {A dependencies {A implementation project(':sqldelight-sample:sample-common') }A }A }A }A SqlDatabase.Schema Query
SqlPreparedStatement SqlCursor SqlDatabase
Transacter.Transaction Transacter SqlDatabase.Schema Query
SqlPreparedStatement SqlCursor SqlDatabase
Transacter.Transaction Transacter abstract class Query
SqlDatabase.Schema
SqlPreparedStatement SqlCursor SqlDatabase
Transacter.Transaction Transacter abstract class Query
fun addListener(listener: Listener) fun removeListener(listener: Listener)
interface Listener { fun queryResultsChanged() }Y }X abstract class Query
fun addListener(listener: Listener) fun removeListener(listener: Listener)
interface Listener { fun queryResultsChanged() }Y
fun notifyDataChanged() }X val usersQuery: Query> Query = usersQuery.asObservable() .map { it.executeAsList() } val usersQuery: Query
> = usersQuery.asObservable() .mapToList() val usersQuery: Query
> Query = usersQuery.asChannel() .map { it.executeAsList() } val usersQuery: Query
> = usersQuery.asChannel() .mapToList() suspend fun users() { val usersQuery: Query
> = usersQuery.asChannel() .mapToList()
return usersChannel.receive() } suspend fun users() { val usersQuery: Query> = usersQuery.asChannel() .mapToList()
return usersChannel.receive() } suspend fun users() { val usersQuery: Query> = usersQuery.asChannel() .mapToList()
return usersChannel.receive() } val usersQuery: Query> Query = usersQuery.asLiveDataList()B val usersQuery: Query
> = usersQuery.asLiveDataList(executor)B val pagedQuery = QueryDataSourceFactory( queryProvider = { limit, offset -> queries.users(limit, offset) }, count = queries.usersCount()) apply plugin: 'com.squareup.sqldelight' apply plugin: 'com.squareup.sqldelight' apply plugin: 'org.jetbrains.kotlin.jvm' apply plugin: 'com.squareup.sqldelight' apply plugin: 'org.jetbrains.kotlin.jvm'
// automatically adds… dependencies { api 'com.squareup.sqldelight:runtime-jdk:1.0.0' }X apply plugin: 'com.squareup.sqldelight' apply plugin: 'org.jetbrains.kotlin.jvm'
// automatically adds… dependencies { api 'com.squareup.sqldelight:runtime-jdk:1.0.0' }X tasks.create('generateSqlDelight', SqlDelightTask) { // … }X tasks.getByName('compileKotlin').dependsOn('generateSqlDelight') apply plugin: 'com.squareup.sqldelight' apply plugin: 'org.jetbrains.kotlin.js' apply plugin: 'com.squareup.sqldelight' apply plugin: 'org.jetbrains.kotlin.js'
// automatically adds… dependencies { api 'com.squareup.sqldelight:runtime-js:1.0.0' }X tasks.create('generateSqlDelight', SqlDelightTask) { // … }X tasks.getByName('compileKotlin').dependsOn('generateSqlDelight') apply plugin: 'com.squareup.sqldelight' apply plugin: 'org.jetbrains.kotlin.multiplatform' apply plugin: 'com.squareup.sqldelight' apply plugin: 'org.jetbrains.kotlin.multiplatform'
// automatically adds… dependencies { api 'com.squareup.sqldelight:runtime:1.0.0' }X tasks.create('generateSqlDelight', SqlDelightTask) { // … }X tasks.getByName('compileKotlin').dependsOn('generateSqlDelight') apply plugin: 'com.squareup.sqldelight' apply plugin: 'org.jetbrains.kotlin.android' apply plugin: 'com.squareup.sqldelight' apply plugin: 'org.jetbrains.kotlin.android'
// automatically adds… dependencies { api 'com.squareup.sqldelight:runtime-jdk:1.0.0' }X tasks.create('generateSqlDelight', SqlDelightTask) { // … }X tasks.getByName('compileKotlin').dependsOn('generateSqlDelight') apply plugin: 'com.squareup.sqldelight' apply plugin : 'org.jetbrains.kotlin.android' multiplatform
// automatically adds… dependencies { api 'com.squareup.sqldelight:runtime-jdk:1.0.0' }X tasks.create('generateDebugSqlDelight', SqlDelightTask) { // … }X tasks.getByName('compileDebugKotlin').dependsOn('generateDebugSqlDelight') tasks.create('generateReleaseSqlDelight', SqlDelightTask) { // … }X tasks.getByName('compileReleaseKotlin').dependsOn('generateReleaseSqlDelight') apply plugin: 'com.squareup.sqldelight' apply plugin : 'org.jetbrains.kotlin.android' multiplatform
// automatically adds… dependencies { api 'com.squareup.sqldelight:runtime-jdk:1.0.0' }X tasks.create('generateDebugSqlDelight', SqlDelightTask) { /* … */ }X tasks.create('generateReleaseSqlDelight', SqlDelightTask) { /* … */ }X tasks.getByName('compileDebugKotlin').dependsOn('generateDebugSqlDelight')tasks.create('verifySqlDelightMigration', VerifyMigrationTask) { // … }X tasks.getByName('compileReleaseKotlin').dependsOn('generateReleaseSqlDelight') IntelliJ Plugin IntelliJ Plugin IntelliJ Plugin Gradle Generated Compiler Plugin Code
IntelliJ Plugin Gradle Generated Compiler Plugin Code
IntelliJ Plugin Gradle Plugin
Generated Compiler Code
IntelliJ Plugin SQLDelight 0.7
Gradle Plugin
antlr Compiler
IntelliJ Plugin SQLDelight 0.7
Gradle Plugin
antlr Compiler
IntelliJ PSI Plugin SQLDelight 1.0
Gradle Plugin
PSI Compiler
IntelliJ Plugin SQLDelight 1.0
Gradle Plugin
sqlite-psi Compiler
IntelliJ Plugin JavaScript Android AndroidX Sqlite Driver Abstraction
AndroidX android.database.* knarch.db SQLCipher Impl net.sqlcipher.database.*Android sqlite3.h Driver Native Generated Database Code Abstraction JDBC java.sql.* Driver org.sqlite.* JVM (xerial)
JS Driver Node? WASM?JavaScript Vanilla JS? Android AndroidX Sqlite Driver Abstraction
AndroidX android.database.* knarch.db SQLCipher Impl net.sqlcipher.database.*Android sqlite3.h Driver Native Generated Database Code Abstraction JDBC java.sql.* Driver org.sqlite.* JVM (xerial)
Node? WASM?JavaScript Vanilla JS? runtime storage
Node
WASM
Vanilla JS runtime storage
Node sqlite3
WASM
Vanilla JS runtime storage
Node sqlite3
WASM sqlite-wasm
Vanilla JS runtime storage
Node sqlite3
WASM sqlite-wasm
Vanilla JS sql.js runtime storage
Node sqlite3 filesystem
WASM sqlite-wasm
Vanilla JS sql.js runtime storage
Node sqlite3 filesystem
WASM sqlite-wasm ???
Vanilla JS sql.js ??? iOS let firstPlace = playerQueries.withRanking( ranking: 1 ).executeAsOne() struct Player {A var id: NSNumber var name: String var country: String var ranking: NSNumber }A let firstPlace = playerQueries.withRanking( ranking: 1 ).executeAsOne() struct Player {A var id: NSNumber var name: String var country: String var ranking: NSNumber }A func createPlayer(id: NSNumber, name: String, country: String, ranking: NSNumber) -> Player {A return Player(id: id, name: name, country: country, ranking: ranking) }A let firstPlace = playerQueries.withRanking( ranking: 1 ).executeAsOne() struct Player {A var id: NSNumber var name: String var country: String var ranking: NSNumber }A func createPlayer(id: NSNumber, name: String, country: String, ranking: NSNumber) -> Player {A return Player(id: id, name: name, country: country, ranking: ranking) }A let firstPlace = playerQueries.withRanking( ranking: 1, mapper: createPlayer ).executeAsOne() as! Player Generated SQL Delight Code
SQLite
Generated Compiler Swift Code Generated SQL Delight Code
SQLite
Generated Compiler Swift Code
withRanking: SELECT name FROM player WHERE ranking = ?; insert: INSERT INTO player (name, country, ranking) VALUES (?, ?, ?); withRanking: SELECT name FROM player WHERE ranking = ?; insert: INSERT INTO player (name, country, ranking) VALUES (?, ?, ?); private inner class Insert { fun execute(): Long { val result = statement.execute() notifyQueries(queryWrapper.playerQueries.withRanking) return result } }
withRanking: SELECT name FROM player WHERE ranking = ?; insert: INSERT INTO player (name, country, ranking) VALUES (?, ?, ?); private inner class Insert { fun executeexecute():(): Long { val result = statementstatement.execute().execute() notifyQueries(queryWrapper.playerQueries.withRanking) return result } }
withRanking: SELECT name FROM player WHERE ranking = ??;; insert: INSERT INTO player (name,(name, countrycountry,, ranking) VALUES (?(?,, ??,, ?)?);; private inner class Insert { fun execute(): Long { val result = statement.execute() notifyQueries(queryWrapper.playerQueries.withRanking) return result } }
withRanking: SELECT name FROM player WHERE ranking = ?; insert: INSERT INTO player (name(name,, countrycountry,, ranking)ranking) VALUES (?(?,, ??,, ?)?);; Other SQL Dialects 1.0! 1.0! (RC) github.com/square/sqldelight github.com/square/sqldelight
jakes.link/resurgence-of-sql jakes.link/embracing-sql github.com/square/sqldelight
jakes.link/resurgence-of-sql jakes.link/embracing-sql
IntelliJ Plugins – Friday @ 15:15, Berlagezaal @Strongolopolis @JakeWharton