A Kotlin Multiplatform library for database storage, which aims to support all functionality offered by Room.
Kabin uses drivers from SQLDelight, offering a stable interaction with SQL
on all targets supported by the latter.
Caution
This library is still under development. Avoid using it in production. You are very welcome to create issues and Pull Requests. Contribution will accelerate development, and pave the way for a production ready solution.
Using Kabin is straight forward. Annotations are identical to those in Room, which means usage is identical too. Here's how you declare a simple database:
- Create an
Entity
:
@Entity
data class UserEntity(
@PrimaryKey
val id: Int,
val name: String
)
- Create a
Dao
:
@Dao
interface UserDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertOrReplace(entity: UserEntity)
}
- Create a
Database
:
@Database(
entities = [
UserEntity::class
],
version = 1
)
interface SampleDatabase : KabinDatabase {
val userDao: UserDao
}
Kabin will generate code for you and glue everything together.
- Finally, create a platform configuration, then pass it to the
newInstance
method, to initializeSampleDatabase
:
// Create configuration for every platform, here's an example for android
val configuration = KabinDatabaseConfiguration(
context = this,
name = "sample-database"
)
val sampleDatabase = SampleDatabase::class.newInstance(
configuration,
migrations = emptyList(),
migrationStrategy = KabinMigrationStrategy.DESTRUCTIVE
)
For more advanced topics, read Room documentation and tutorials, and apply the same logic using Kabin.
Latest Kabin version
Add common
modules to your sourceSet
:
kotlin {
sourceSets {
val commonMain by getting {
dependencies {
// Kabin
implementation("com.attafitamim.kabin:core:$kabin_version")
}
// Make generated code visible for commonMain
kotlin.srcDir("$buildDir/generated/ksp/metadata/commonMain/kotlin/")
}
}
}
Add ksp
compiler:
plugins {
alias(libs.plugins.kotlin.multiplatform)
alias(libs.plugins.ksp)
}
dependencies {
add("kspCommonMainMetadata", "com.attafitamim.kabin:compiler:$kabin_version")
}
// Workaround for using KSP in common
tasks.withType<KotlinCompile<*>>().configureEach {
if (name != "kspCommonMainKotlinMetadata") {
dependsOn("kspCommonMainKotlinMetadata")
}
}
afterEvaluate {
tasks.filter { task ->
task.name.contains("SourcesJar", true)
}.forEach { task ->
task.dependsOn("kspCommonMainKotlinMetadata")
}
}
Configure ksp
processor to generate more suitable code for you
ksp {
// Use this prefix for fts tables to keep the old room scheme
arg("FTS_TRIGGER_NAME_PREFIX", "room_fts_content_sync")
}
Available keys, with their default values
TABLE_SUFFIX("KabinTable")
ENTITY_MAPPER_SUFFIX("KabinMapper")
DATABASE_SUFFIX("KabinDatabase")
DAO_SUFFIX("KabinDao")
DAO_QUERIES_SUFFIX("KabinQueries")
INDEX_NAME_PREFIX("index")
FTS_TRIGGER_NAME_PREFIX("kabin_fts_content_sync")
BEFORE_UPDATE_TRIGGER_NAME_SUFFIX("BEFORE_UPDATE")
AFTER_UPDATE_TRIGGER_NAME_SUFFIX("AFTER_UPDATE")
BEFORE_DELETE_TRIGGER_NAME_SUFFIX("BEFORE_DELETE")
AFTER_INSERT_TRIGGER_NAME_SUFFIX("AFTER_INSERT")
This list shows Room features, which are already supported by Kabin, or under development
Note
To accelerate the development of certain features, create issues to increase priority, or upvote existing ones
-
tableName
-
indices
-
inheritSuperIndices
-
primaryKeys
-
foreignKeys
-
ignoredColumns
-
autoGenerate
- Use
@PrimaryKey
on multiple columns - Use
@PrimaryKey
on@Embedded
columns
-
prefix
- Nested
@Embedded
(@Embedded
inside an@Embedded
) - Compound (
@Embedded
entity inside a class for working with@Relations
) -
@Embedded
columns as primary keys using@PrimaryKey
-
name
-
typeAffinity
-
index
-
collate
-
defaultValue
- Skip columns annotated with
@Ignore
-
entity
-
parentColumns
-
childColumns
-
onDelete
-
onUpdate
-
deferred
-
columns
-
orders
-
name
-
unique
-
entity
-
parentColumn
-
entityColumn
-
associateBy
-
projection
- Detect entity from property type
- Detect entity from list property type
- Insert entities automatically when inserting Compound classes with
@Embedded
entities
-
value
-
parentColumn
-
entityColumn
- Retrieve data using
@Junction
table - Create and insert
@Junction
entities automatically when inserting classes with@Relation
-
contentEntity
-
tokenizerArgs
-
languageId
-
notIndexed
-
prefix
-
order
- Create virtual table with triggers
- Use coroutines and
suspend
functions - Support
Collection
andFlow
return types - Execute operations on
Dispatcher.IO
- Interfaces annotated with
@Dao
- Abstract classes annotated with
@Dao
-
entity
-
onConflict
- Insert single entity, multiple entities as distinct parameters or lists of entities
- Insert Compound classes with
@Embedded
entities including their@Relation
and@Junction
-
entity
- Delete single entity, multiple entities as distinct parameters or lists of entities
- Delete Compound classes with
@Embedded
entities including their@Relation
and@Junction
-
entity
-
onConflict
- Update single entity, multiple entities as distinct parameters or lists of entities
- Update Compound classes with
@Embedded
entities including their@Relation
and@Junction
Caution
This annotation is currently treated as @Insert with REPLACE strategy
-
entity
- Use Upsert logic instead of simple insert with REPLACE strategy
- Upsert single entity, multiple entities as distinct parameters or lists of entities
- Upsert Compound classes with
@Embedded
entities including their@Relation
and@Junction
-
observedEntities
- Detect observed entities by return type
-
value
- Detect observed entities by return type
- Detect observed entities by queried tables
- Named parameters declared as
:parameter
- Nullable parameters
- List and nullable list parameters
- Parameters declared as
?
- Highlight SQL Syntax
- Validate SQL Syntax
- Auto complete SQL Syntax and named parameters
- Functions with
@Transaction
annotation - Functions working with multiple entity parameters, collections and compounds
-
entities
-
views
-
version
-
exportSchema
-
autoMigrations
- Interfaces annotated with
@Database
- Abstract classes annotated with
@Database
- Generate adapters for primitive and enum classes
- Manual migration
- Destructive migration
- Validate Schema
Caution
This annotation can only accept converter object
that implement app.cash.sqldelight.ColumnAdapter
-
value
-
builtInTypeConverters
-
enums
(Enums are supported by default) -
uuid
-
from
-
to
-
spec
- Support auto migration functionality
- Used to map results returned by a dao to data classes that are not entities or primitives
- This annotation is meant to be used with
Database
class value
acceptsobject
that implementsKabinMapper<T>
- Classes that use
@Embedded
and@Relation
annotations can be used with@Insert
,@Upsert
,@Delete
and@Update
@Junction
inside a compound is automatically created and inserted as well
- Add Tests
- Clean and refactor
compiler
andprocessor
logic, make it more flexible and maintainable - Generate more optimized code
- Fix bugs and issues
- Implement more Room features, especially the essential ones for basic and simple apps
- Add more features to make working with SQL easier and more interesting
- Add multiplatform sample with UI
- Make a stable release