Drift (ilgari Moor) — SQLite asosida qurilgan va o'z DSLiga ega Flutter va Dart uchun reaktiv ORM. An'anaviy ORMlardan farqli o'laroq, Drift Dart so'rovlarini qurilish bosqichida SQLga kompilyatsiya qiladi va runtime xatolarini bartaraf etadi. Drift Docs, 2024 ma'lumotlariga ko'ra, Drift qo'lda yozilgan SQL so'rovlaridan 40% ko'proq kod yaratadi, ammo SQLni qo'lda yozishni butunlay yo'q qilib, uni type-safe Dart sintaksisi bilan almashtiradi.
Asosiy
Drift — Dart va Flutter uchun ORM, ilgari Moor nomi bilan tanilgan. Simon Binder tomonidan 2019-yilda yaratilgan va bir nechta asosiy versiyalarni bosib o'tgan. Drift Dart so'rovlarini drift_dev va build_runner yordamida qurilish bosqichida SQLga kompilyatsiya qiladi, bu to'liq tip xavfsizligini ta'minlaydi va runtime da SQL sintaksis xatolarini bartaraf etadi.
Floor dan farqli o'laroq, Drift so'rovlarni qurish uchun o'z DSLidan (Domain-Specific Language) foydalanadi — dasturchi Dartda yozadi, generator esa buni SQLga tarjima qiladi. Bu IDE ga sintaksisni tekshirish, jadval maydonlarini avtomatik to'ldirish va so'rovni buzish qo'rquvisiz ma'lumot modelini refaktor qilish imkonini beradi.
Drift (2024) ma'lumotlariga ko'ra, kutubxona 8000 dan ortiq Flutter loyihalarida qo'llaniladi. Barcha mashhur platformalarni qo'llab-quvvatlaydi: Android sqflite orqali, iOS sqflite orqali, web sqlite3 WASM orqali, desktop mahalliy sqlite3 drayveri orqali.
Moor 2.0 versiyasida (2022) Drift ga o'zgartirildi. Sabab — boshqa loyihalar bilan nom ziddiyati va eski koddan uzoqlashish istagi. API mos qoldi: migratsiya uchun import ni moordan driftga o'zgartirish va bog'liqliklarni yangilash kifoya.
Drift ta'minlaydi: ma'lumot o'zgarishida avtomatik yangilanadigan o'rnatilgan Stream so'rovlari, qaytarish bilan tranzaksiyalarni qo'llab-quvvatlash, rawQuery orqali maxsus SQL so'rovlari, mantiqni inkapsulyatsiya qilish uchun DAO namunasi, platformalararo migratsiyalar va drift_riverpod va drift_bloc paketlari orqali Riverpod va BLoC bilan integratsiya.
Drift kompilyatsiya bosqichida kod generatsiyasidan foydalanadi. Dasturchi jadvallarni @DataClass annotatsiyalari yoki Table ni kengaytiruvchi Dart sinflari orqali tavsiflaydi. Generator yordamchi sinflarni yaratadi: Companion (qo'shish/yangilashda nullable maydonlar uchun), DriftDatabase (kirish nuqtasi) va DAO tatbiqlari.
SQLite so'rovlarini Drift bevosita bajarmaydi. Buning o'rniga dasturchi Dartda yozadi: select(tasks).where(tasks.priority.greaterThan(3)).build(). Generator buni SQLga tarjima qiladi va ijro vaqtida Drift shunchaki tayyor SQL so'rovini SQLite ga yuboradi. Bu Dart sintaksisining qulayligini mahalliy SQL samaradorligi bilan birlashtiradi.
Drift ikkita so'rov rejimini qo'llab-quvvatlaydi: DSL (tavsiya etiladi) va raw SQL. DSL so'rovlari xavfsizroq — kompilyator maydon nomlari, turlari va moslikni tekshiradi. Raw SQL DSL bilan qamrab olinmagan murakkab so'rovlar uchun kerak: oyna funksiyalari, rekursiv CTE, maxsus SQLite kengaytmalari.
Drift ikkita so'rov yozish usulini taklif etadi: Dart DSL (mahalliy) va raw SQL (murakkab holatlar uchun). DSL 90% ssenariylar uchun afzal: xavfsizroq, o'qilishi oson va refaktoringni qo'llab-quvvatlaydi. Raw SQL faqat DSL talab qilinadigan konstruksiyani qamrab olmaganida ishlatiladi.
| Aspekt | Drift DSL | Drift da Raw SQL |
|---|---|---|
| Tip xavfsizligi | To'liq (kompilyatsiya) | Yo'q (runtime) |
| Avtomatik to'ldirish | Ha (IDE) | Faqat sql fayllarida |
| Refaktoring | Avtomatik | Satrlar bo'yicha qo'l qidirish |
| Murakkab JOIN | Qo'llab-quvvatlanadi | To'liq erkinlik |
| Oyna funksiyalari | Cheklangan | To'liq qo'llab-quvvatlash |
| Reaktivlik | O'rnatilgan (Stream) | .watch() orqali |
Drift DSL — asosiy ish usuli. SELECT, INSERT, UPDATE, DELETE, WHERE, ORDER BY, LIMIT, JOIN va guruhlashni qamrab oladi. Barcha odatiy CRUD so'rovlari uchun DSL dan foydalaning: qisqaroq, xavfsizroq va o'zgarishlarda Stream ni avtomatik yangilaydi.
Raw SQL Drift da quyidagilar uchun kerak: maxsus SQLite funksiyalari (FTS5, JSON1), EXISTS bilan murakkab quyi so'rovlar, INSERT OR REPLACE, CASE bilan ommaviy UPDATE, shuningdek samaradorlik muhim bo'lgan va DSL optimal ijro rejasini yaratmaydigan so'rovlar. Raw SQL drift_dev orqali tiplash qo'llab-quvvatlashi bilan .sql fayllarida yozilishi mumkin.
Drift Table ni kengaytiruvchi sinflar yoki @DataClass annotatsiyasidan foydalanadi. Quyida — DSL, raw SQL va reaktiv yangilash bilan Task modelining to'liq namunasi. build_runner ishga tushirilgandan so'ng, barcha yaratilgan sinflar tayyor.
Tasks sinfi Table ni kengaytiradi va ustunlarni belgilaydi. Har bir ustun Column
class Tasks extends Table {
IntColumn get id => integer().autoIncrement();
TextColumn get title => text().withDefault(const Constant(''))();
BoolColumn get isCompleted => boolean().withDefault(const Constant(false))();
IntColumn get priority => integer().withDefault(const Constant(0))();
}
@DriftDatabase(tables: [Tasks])
class AppDatabase extends $AppDatabase {
AppDatabase(QueryExecutor e) : super(e);
}
Drift jadvallar uchun into(tasks).insert(), select(tasks), update(tasks) va delete(tasks) metodlarini yaratadi. Barcha operatsiyalar Future qaytaradi — SQLite bilan ishlash asinxrondir. O'zgarishlarni kuzatish uchun .get() o'rniga .watch() dan foydalaning.
// Yozish
await into(tasks).insert(TasksCompanion.insert(
title: Value('Mahsulotlarni sotib olish'),
priority: Value(3),
));
// Filtrlash bilan o'qish
final highPriority = await (select(tasks)
..where((t) => t.priority.greaterThan(2))
..orderBy([(t) => OrderingTerm(expression: t.priority, mode: OrderingMode.desc)]))
.get();
// Reaktiv kuzatish
select(tasks).watch().listen((tasksList) {
// tasksList — List, jadval har o'zgarganida yangilanadi
updateUi(tasksList);
});
Murakkab so'rovlar uchun Drift raw SQL yozishga imkon beradi, bir vaqtning o'zida tiplashni saqlaydi. customSelect metodi so'rov satrini qabul qiladi va kod generatori orqali tiplangan natija qaytaradi. Bu yondashuv SQL egiluvchanligini Drift tip xavfsizligi bilan birlashtiradi.
final result = await customSelect(
'SELECT title, COUNT(*) as cnt FROM tasks GROUP BY title',
readsFrom: { tasks },
).get();
for (final row in result) {
print('${row.readString("title")}: ${row.readInt("cnt")}');
}
Drift ham avtomatik migratsiyalarni (oddiy o'zgarishlar uchun), ham qo'l migratsiyalarni (murakkab transformatsiyalar uchun) qo'llab-quvvatlaydi. Ma'lumotlar bazasi versiyasi AppDatabase konstruktorida o'rnatiladi. Versiya mos kelmasa, Drift barcha yopilmagan migratsiyalarni ketma-ket qo'llaydi.
Standart qiymatga ega ustun qo'shish uchun Drift MigrationStrategy orqali avtomatik migratsiya yaratishi mumkin. Agar o'zgarish mavjud ma'lumotlarni buzmasa (nullable maydon qo'shish), versiya tekshiruvi va ALTER TABLE bajarilishi bilan beforeOpen dan foydalanish mumkin.
Murakkab o'zgarishlar (jadval nomini o'zgartirish, ma'lumotlarni birlashtirish, ustun turini o'zgartirish) uchun Drift qo'l SQL migratsiyasini talab qiladi. Migratsiyalar ma'lumotlar bazasi sinfidagi migrations parametri orqali belgilanadi. Har bir migratsiya from/to raqamlari va SQL so'rovlari bo'lgan obyektdir.
Drift NativeDatabase.memory() orqali test rejimida ishga tushirishni qo'llab-quvvatlaydi. Xotiradagi ma'lumotlar bazasi har bir testdan oldin noldan yaratiladi va testdan keyin yo'q qilinadi. Mock qilish uchun mocklangan QueryExecutor bilan mocktail paketidan foydalaning. Drift shuningdek migratsiyalar va so'rovlarni tekshirish bilan integrasion testlar uchun DatabaseTestHelper ni taqdim etadi.
Drift @DriftAccessor annotatsiyasi bilan abstrakt sinflar orqali DAO (Data Access Object) ni qo'llab-quvvatlaydi. DAO bir yoki bir nechta jadvalga so'rovlarni inkapsulyatsiya qiladi va ma'lumotlar bazasidan alohida sinovdan o'tkazilishi mumkin. To'g'ridan-to'g'ri Database so'rovlaridan farqli o'laroq, DAO so'rov mantiqini ilovaning turli qismlari o'rtasida qayta ishlatish imkonini beradi va modul testlarini soddalashtiradi.
@DriftDatabase(tables: [Tasks])
class AppDatabase extends $AppDatabase {
AppDatabase(QueryExecutor e) : super(e) {
migrations.add(Migration(1, 2, (m) async {
await m.addColumn(tasks, tasks.dueDate);
await m.createIndex(tasks.idxPriority);
}));
}
}
Tez-tez beriladigan savollar
Drift o'z DSLidan SQL satrlari o'rniga foydalanadi, bu to'liq tip xavfsizligi va IDE da avtomatik to'ldirishni ta'minlaydi. Floor @Query annotatsiyasida SQL satrlaridan foydalanadi. Drift shuningdek ko'proq platformalarni (shu jumladan web) qo'llab-quvvatlaydi va Stream orqali o'rnatilgan reaktivlikka ega, Floor da esa Stream qo'lda e'lon qilinishi kerak.
Ha, Drift ma'lumotlarni saqlagan holda migratsiyalarni qo'llab-quvvatlaydi. Ustun qo'shish uchun Migration da addColumn dan foydalaning. Murakkab transformatsiyalar (nom o'zgartirish, birlashtirish) uchun migratsiya ichida raw SQL yozing. Agar migratsiya ko'rsatilmagan bo'lsa, sxema mos kelmasa Drift ma'lumot yo'qotishi bilan bazani qayta yaratadi.
Drift build_runner va drift_dev orqali kod generatsiyasini talab qiladi. Generatsiyasiz tiplangan so'rovlar yaratib bo'lmaydi. Biroq, kichik loyihalar uchun Drift sqlparser ni qo'llab-quvvatlaydi — avtomatik tiplash bilan qo'lda SQL fayl yozish, ammo bu hali ham generatsiya bosqichini talab qiladi.
Riverpod bilan integratsiya uchun drift_riverpod paketidan foydalaning. U Database, DAO va Stream so'rovlari uchun providerlarni taqdim etadi. Misol: final tasksProvider = databaseProvider.select((db) => db.select(db.tasks).watch()) — UI ma'lumot o'zgarishida avtomatik qayta quriladi.
Drift ichki shifrlashga ega emas, lekin SEE (SQLite Encryption Extension) bilan maxsus sqlite3 kutubxonalarini ulashni qo'llab-quvvatlaydi. Mobil platformalar uchun QueryExecutor sifatida sqflite_sqlcipher dan foydalaning — Drift abstrakt QueryExecutor orqali har qanday SQLite tatbiqi bilan ishlaydi.
Xulosa
Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz
IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.