Overview

KQLite is a lightweight, multiplatform SQLite wrapper to write typesafe DSL queries. KQLite allows you to write SQLite queries using a Kotlin object-style DSL instead of raw SQL strings. KQLite exposes typesafe KQLiteCursor which executes lazily and autoclosed when fully iterated. It utilizes androidx.sqlite:sqlite multiplatform drivers internally to ensure safe query execution and binding arguments.

KQLite supports following KMP targets
  • Android
  • iOS
  • JVM
  • macOS
  • Linux
  • tvOS
  • watchOS

Adding KQLite dependency

sourceSets {
        commonMain.dependencies {
            implementation("com.kqlite:kqlite:0.2.0")
        }
    }

KQLite Sample Queries

// Selecting all contacts
val cursor: KQLiteCursor = TblContact.select().execute()
cursor.forEach {  it: KQLiteCursor 
    println(it[TblContact.firstName])
}
// Selecting specific columns
TblContact
    .select(TblContact.id, TblContact.firstName)
    .where { it.firstName LIKE "%John%" }
    .execute()
    .forEach {  it: KQLiteCursor 
        println("id=${it[TblContact.id]}, name=${it[TblContact.firstName]}")
    }
// Mapping results to other types
val cursor = TblContact
    .select(TblContact.id, TblContact.firstName)
    .where {  it: TblContact 
        it.firstName LIKE "%John%" 
    }.execute()

cursor
    .asSequence()
    .map {  it: KQLiteCursor 
        Pair(it[TblContact.id], it[TblContact.firstName])
    }.forEach {  it: Pair<Int,String> 
        println(it)
    }
// Quick select convenience API
TblContact.quickSelect {  it: TblContact 
    it.firstName LIKE "%John%"
}.forEach {  it: KQLiteCursor 
    println(it[TblContact.firstName])
}
// Mapping results to Contact entity
val list: List<Contact> =
    TblContact.quickSelect {  it: TblContact 
        it.deleted NOT_EQ true
    }.mapToList(TblContact::mapper)
// Flow re-emit on table updates (INSERT/UPDATE/DELETE)
val list: Flow<List<Contact>> =
    TblContact.quickSelect {  it: TblContact 
        it.deleted NOT_EQ true
    }
    .asCallbackFlow()
    .mapToList(mapper = TblContact::mapper)
// Getting single row
val contact: Contact =
    TblContact.quickSelect {  it: TblContact 
        it.id EQ 1
    }.mapToSingle(TblContact::mapper)
// Insert returning row id
val id: Int =
    TblContact
        .insert(TblContact.firstName, TblContact.phone)
        .bind {  it: TblContact 
            it.firstName.bind("John")
            it.phone.bind(JSON_ARRAY("1234567890", "0987654321"))
        }.executeReturning(TblContact.id)
// Insert Contact entity
TblContact
    .insert(onConflict = Action.REPLACE)
    .bind {  it: TblContact 
        it.binder(this, contact)
    }.execute()
// Quick insert item
TblContact.quickInsert {  it: TblContact 
    it.binder(this, contact)
}
// Update anything
TblContact
    .update {  it: TblContact 
        it.firstName.bind("Jane")
    }
    .where {  it: TblContact 
        it.id EQ 1
    }.execute()
// Delete anything
TblContact.quickDelete {  it: TblContact 
    it.id EQ 1
}
Tables ⮕