sqlx4k¶
A coroutine-first SQL toolkit with compile-time query validations for Kotlin Multiplatform. PostgreSQL, MySQL/MariaDB, and SQLite are supported.
sqlx4k is not an ORM. Instead, it provides a comprehensive toolkit of primitives and utilities to communicate directly with your database. The focus is on giving you control while catching errors early through compile-time query validation, preventing runtime surprises before they happen (see SQL syntax and schema validation).
The library is designed to be extensible, with a growing ecosystem of tools and extensions like PGMQ (PostgreSQL Message Queue), SQLDelight integration, and more.
Quick look¶
The suggested way to use sqlx4k: map your tables with @Table, declare your queries in a @Repository interface, and
let the code generator write the implementation (with the CRUD operations), the row mappers, and
validate every query while it builds:
@Table("users")
data class User(
@Id
val id: Long = 0, // Generated by the database, and read back on insert.
val name: String,
@Column(name = "mail_address")
val email: String,
)
@Repository
interface UserRepository : ContextCrudRepository<User> {
@Query("SELECT * FROM users WHERE mail_address = :email")
context(context: QueryExecutor)
suspend fun findOneByEmail(email: String): Result<User?>
}
// The transaction returns the value of its block: here, the updated user.
val updated: User = db.transaction {
val alice = UserRepositoryImpl.insert(User(name = "Alice", email = "alice@example.com")).getOrThrow()
UserRepositoryImpl.update(alice.copy(name = "Alice Smith")).getOrThrow()
}
with(db) {
val alice: User? = UserRepositoryImpl.findOneByEmail("alice@example.com").getOrThrow()
}
See Repositories for the details.
Or run your SQL directly with the driver:
val db = PostgreSQL(
url = "postgresql://localhost:15432/test",
username = "postgres",
password = "postgres",
)
db.execute("insert into users(id, name) values (1, 'Alice');").getOrThrow()
db.transaction {
execute("update users set name = 'Bob' where id = 1;").getOrThrow()
fetchAll("select * from users;").getOrThrow().forEach { println(it) }
}
Features¶
-
PostgreSQL, MySQL, MariaDB, SQLite and SQLCipher (encrypted SQLite).
-
Every query API is a
suspendfunction returning aResult, on non-blocking I/O on every platform. -
One
sqlx4k { }block adds the driver, the extensions and the code generator. -
CRUD and
@Repositoryimplementations, row mappers, batch operations, optimistic locking. -
@QuerySQL is checked for syntax, columns, tables and statement kind during the build. -
Generated, thread-safe in-memory implementations of your repositories for unit tests.
-
Block-scoped transactions, savepoints and transaction propagation through the coroutine context.
-
Run pending migrations and validate the ones already applied.
Supported databases¶
(encrypted SQLite,
sqlx4k-sqlite-cipher)
sqlx4k runs on the JVM, Android, iOS, macOS, Linux and Windows: see Supported targets.
Articles¶
Short deep-dive posts covering Kotlin/Native, FFI, and Rust ↔ Kotlin interop used in sqlx4k, published on the author's homepage (under construction):
- Introduction to the Kotlin Native and FFI: [Part 1], [Part 2]
- Interoperability between Kotlin and Rust, using FFI: [Part 1], (Part 2 soon)
License¶
MIT, see LICENSE.