Skip to content

hub-bla/room-vec

Repository files navigation

room-vec

room-vec is a Kotlin Multiplatform helper for wiring the sqlite-vec extension into Room's bundled SQLite driver.

Supported platforms

  • Android
  • iOS
  • JVM
    • Windows (x64)
    • macOS (x64, ARM64/Apple Silicon)
    • Linux (x64, ARM64)

Setup

Add room-vec-common to your shared module to load sqlite-vec. Add room-vec-runtime and room-vec-annotations when you want generated Vec tables and DAO operations. With a version catalog:

[versions]
roomVec = "<version>"

[libraries]
room-vec-annotations = { module = "io.github.hub-bla:room-vec-annotations", version.ref = "roomVec" }
room-vec-common = { module = "io.github.hub-bla:room-vec-common", version.ref = "roomVec" }
room-vec-runtime = { module = "io.github.hub-bla:room-vec-runtime", version.ref = "roomVec" }
room-vec-compiler = { module = "io.github.hub-bla:room-vec-compiler", version.ref = "roomVec" }
kotlin {
    sourceSets {
        commonMain.dependencies {
            implementation(libs.room.vec.annotations)
            implementation(libs.room.vec.common)
            implementation(libs.room.vec.runtime)
        }
    }
}

dependencies {
    add("kspCommonMainMetadata", libs.roomvec.compiler)
    add("kspJvm", libs.room.vec.compiler)
    add("kspAndroid", libs.room.vec.compiler)
    add("kspIosArm64", libs.room.vec.compiler)
    add("kspIosSimulatorArm64", libs.room.vec.compiler)
}

tasks.matching { it.name.startsWith("ksp") && it.name != "kspCommonMainKotlinMetadata" }.configureEach {
    dependsOn("kspCommonMainKotlinMetadata")
}

Usage

room-vec can be used in two ways: load sqlite-vec into Room's bundled driver with room-vec-common, or add the annotations, runtime, and compiler to generate Vec tables and DAO operations.

Option 1: Load sqlite-vec only

If you want to write sqlite-vec SQL yourself, add withSqliteVec() only to Room's bundled SQLite driver:

import io.github.hubbla.roomvec.withSqliteVec

val db = Room.databaseBuilder<AppDatabase>(/* platform-specific arguments */)
    .setDriver(BundledSQLiteDriver().withSqliteVec())
    .build()

Option 2: Generate Vec tables and DAOs

Use the generated path when you want room-vec to create the sqlite-vec side tables and DAO implementation.

Configure the database builder with both withSqliteVec() hooks:

  • BundledSQLiteDriver().withSqliteVec() loads sqlite-vec into the driver.
  • .withSqliteVec() on RoomDatabase.Builder<AppDb> installs Vec table callbacks and the DAO factory.
import io.github.hubbla.roomvec.withSqliteVec

val db = Room.databaseBuilder<AppDb>(/* platform-specific arguments */)
    .setDriver(BundledSQLiteDriver().withSqliteVec())
    .withSqliteVec()
    .build()

Declare Vec companion tables next to normal Room entities:

@Database(entities = [Document::class], version = 1)
@VecDatabase(tables = [DocumentEmbedding::class])
abstract class AppDb : RoomDatabase() {
    abstract fun documentDao(): DocumentDao
    fun documentEmbeddingDao(): DocumentEmbeddingDao = sqliteVecDao()
}

@Entity(tableName = "documents")
data class Document(
    @PrimaryKey val id: Long,
    val title: String,
    val body: String,
)

@VecTable(
    name = "document_vec",
    owner = Document::class,
    ownerPrimaryKey = "id",
)
data class DocumentEmbedding(
    @VecColumn(type = VecType.FLOAT32, dimensions = 768)
    val embedding: FloatArray,
)

@VecDao(table = DocumentEmbedding::class)
interface DocumentEmbeddingDao {
    @VecUpsert
    suspend fun upsert(documentId: Long, embedding: DocumentEmbedding)

    @VecDelete
    suspend fun delete(documentId: Long)

    @VecNearest
    suspend fun nearest(embedding: FloatArray, limit: Int): List<VecMatch<Document>>

    @VecNearestIds
    suspend fun nearestIds(embedding: FloatArray, limit: Int): List<VecIdMatch>
}

Then use normal Room transactions together with the generated Vec DAO:

db.withWriteTransaction {
    db.documentDao().insert(document)
    db.documentEmbeddingDao().upsert(document.id, DocumentEmbedding(embedding))
}

val matches: List<VecMatch<Document>> =
    db.documentEmbeddingDao().nearest(queryEmbedding, limit = 10)

Room API parity

room-vec mirrors the Room APIs that make sense for sqlite-vec companion tables.

Room API room-vec API Status
@Database(entities = [...]) @VecDatabase(tables = [...]) Supported as a companion annotation on the same RoomDatabase.
@Entity @VecTable(owner = Entity::class) Supported for Vec tables owned by Room entities.
Entity field @VecColumn Supports one non-null FloatArray column per Vec table.
@Dao @VecDao Supports interfaces returned from sqliteVecDao() accessors.
@Upsert / @Delete @VecUpsert / @VecDelete Supported for Vec row writes and deletes.
@Query @VecNearest / @VecNearestIds Supported only for nearest-neighbor lookup shapes.
RoomDatabase.Builder generated .withSqliteVec() Supported for installing sqlite-vec table callbacks.
Migration / AutoMigration No Vec equivalent yet Fresh databases and destructive migrations create Vec tables; existing DB migrations need manual handling.
@Transaction, Flow, PagingSource, Rx, LiveData, relations, embedded objects, projections No Vec equivalent yet To be created

Other resources

About

Kotlin Multiplatform integration of sqlite-vec with Room

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages