SQLDelight: типобезопасная БД
Пишете SQL — получаете типобезопасный Kotlin API, одинаково работающий на обеих платформах.
SQLDelight — мультиплатформенная библиотека, которая по
.sq-файлам с SQL генерирует типобезопасные Kotlin-функции запросов, используя платформенный драйвер SQLite.
Перевёрнутый подход
В отличие от ORM, где вы описываете классы, а SQL генерируется, SQLDelight идёт от SQL. Вы пишете схему и запросы в .sq-файле, а библиотека генерирует Kotlin-код. Это даёт полный контроль над SQL и типобезопасность: ошибка в запросе — это ошибка компиляции, а не падение в рантайме.
-- Order.sq
CREATE TABLE OrderEntity (
id INTEGER PRIMARY KEY,
total REAL NOT NULL
);
selectAll:
SELECT * FROM OrderEntity;
insertOrder:
INSERT INTO OrderEntity(id, total) VALUES (?, ?);Из этого SQLDelight сгенерирует функции selectAll() и insertOrder(id, total) с правильными типами.
Платформенный драйвер
Сам доступ к SQLite платформенный, поэтому драйвер — в платформенных наборах, и его создание выносят через expect/actual:
// commonMain
expect fun createDriver(): SqlDriver// androidMain
actual fun createDriver(): SqlDriver =
AndroidSqliteDriver(Database.Schema, appContext, "app.db")// iosMain
actual fun createDriver(): SqlDriver =
NativeSqliteDriver(Database.Schema, "app.db")Реактивные запросы
SQLDelight умеет отдавать запросы как Flow: при изменении таблицы подписчики получают новые данные. Это удобно для общего слоя, питающего UI на обеих платформах.
Как работает под капотом
Gradle-плагин SQLDelight парсит .sq-файлы, проверяет SQL по схеме и генерирует Kotlin-обёртки на этапе сборки. В рантайме эти обёртки вызывают платформенный драйвер, который через JNI (Android) или нативный SQLite (iOS) исполняет запрос. Драйвер скрыт за общим интерфейсом SqlDriver, поэтому общий код базы не знает, под какой платформой выполняется. Это та же формула «общий API + платформенный движок», что у Ktor.
Частые ошибки
Положить драйвер в общий код — он платформенный, как и движок Ktor. Вторая ошибка — забыть передать схему при создании драйвера, из-за чего таблицы не создаются. Третья — ожидать диалект PostgreSQL; SQLDelight работает с SQLite, и диалект-специфичные конструкции там недоступны.
Итоги
- SQLDelight идёт от SQL к Kotlin: типобезопасность на этапе компиляции.
- Драйвер SQLite платформенный, создаётся через
expect/actual. - Запросы можно получать как
Flowдля реактивного UI. - Это снова «общий API + платформенный движок».