kabin
kabin copied to clipboard
A Kotlin Multiplatform library for database storage inspired by Room
Kabin: Multiplatform Database Library
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.
Showcase
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.
Installation
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")
}
}
Optional
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")
Supported Room Features
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
@Entity
- [x]
tableName
- [x]
indices
- [ ]
inheritSuperIndices
- [x]
primaryKeys
- [x]
foreignKeys
- [x]
ignoredColumns
@PrimaryKey
- [x]
autoGenerate
- [x] Use
@PrimaryKey
on multiple columns - [x] Use
@PrimaryKey
on@Embedded
columns
@Embedded
- [x]
prefix
- [x] Nested
@Embedded
(@Embedded
inside an@Embedded
) - [x] Compound (
@Embedded
entity inside a class for working with@Relations
) - [x]
@Embedded
columns as primary keys using@PrimaryKey
@ColumnInfo
- [x]
name
- [x]
typeAffinity
- [x]
index
- [ ]
collate
- [x]
defaultValue
@Ignore
- [x] Skip columns annotated with
@Ignore
@ForeignKey
- [x]
entity
- [x]
parentColumns
- [x]
childColumns
- [x]
onDelete
- [x]
onUpdate
- [x]
deferred
@Index
- [x]
columns
- [x]
orders
- [x]
name
- [x]
unique
@Relation
- [x]
entity
- [x]
parentColumn
- [x]
entityColumn
- [x]
associateBy
- [ ]
projection
- [x] Detect entity from property type
- [x] Detect entity from list property type
- [x] Insert entities automatically when inserting Compound classes with
@Embedded
entities
@Junction
- [x]
value
- [x]
parentColumn
- [x]
entityColumn
- [x] Retrieve data using
@Junction
table - [x] Create and insert
@Junction
entities automatically when inserting classes with@Relation
@Fts4
- [x]
contentEntity
- [ ]
tokenizerArgs
- [ ]
languageId
- [ ]
notIndexed
- [ ]
prefix
- [ ]
order
- [x] Create virtual table with triggers
@Dao
- [x] Use coroutines and
suspend
functions - [x] Support
Collection
andFlow
return types - [x] Execute operations on
Dispatcher.IO
- [x] Interfaces annotated with
@Dao
- [ ] Abstract classes annotated with
@Dao
@Insert
- [x]
entity
- [x]
onConflict
- [x] Insert single entity, multiple entities as distinct parameters or lists of entities
- [x] Insert Compound classes with
@Embedded
entities including their@Relation
and@Junction
@Delete
- [x]
entity
- [x] Delete single entity, multiple entities as distinct parameters or lists of entities
- [x] Delete Compound classes with
@Embedded
entities including their@Relation
and@Junction
@Update
- [x]
entity
- [x]
onConflict
- [x] Update single entity, multiple entities as distinct parameters or lists of entities
- [x] Update Compound classes with
@Embedded
entities including their@Relation
and@Junction
@Upsert
[!CAUTION] This annotation is currently treated as @Insert with REPLACE strategy
- [x]
entity
- [ ] Use Upsert logic instead of simple insert with REPLACE strategy
- [x] Upsert single entity, multiple entities as distinct parameters or lists of entities
- [x] Upsert Compound classes with
@Embedded
entities including their@Relation
and@Junction
@RawQuery
- [x]
observedEntities
- [x] Detect observed entities by return type
@Query
- [x]
value
- [x] Detect observed entities by return type
- [x] Detect observed entities by queried tables
- [x] Named parameters declared as
:parameter
- [x] Nullable parameters
- [x] List and nullable list parameters
- [ ] Parameters declared as
?
- [ ] Highlight SQL Syntax
- [ ] Validate SQL Syntax
- [ ] Auto complete SQL Syntax and named parameters
@Transaction
- [x] Functions with
@Transaction
annotation - [x] Functions working with multiple entity parameters, collections and compounds
@Database
- [x]
entities
- [ ]
views
- [x]
version
- [ ]
exportSchema
- [ ]
autoMigrations
- [x] Interfaces annotated with
@Database
- [ ] Abstract classes annotated with
@Database
- [x] Generate adapters for primitive and enum classes
- [x] Manual migration
- [x] Destructive migration
- [ ] Validate Schema
@TypeConverters
[!CAUTION] This annotation can only accept converter
object
that implementapp.cash.sqldelight.ColumnAdapter
- [x]
value
- [ ]
builtInTypeConverters
@BuiltInTypeConverters
- [ ]
enums
(Enums are supported by default) - [ ]
uuid
@AutoMigration
- [ ]
from
- [ ]
to
- [ ]
spec
- [ ] Support auto migration functionality
Additional Features
@Mappers
- 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>
Compound
- 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
Plans and Priorities
- [ ] 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