Drift (Moor) — bu nədir, reaktiv ORM və verilənlər bazaları ilə iş

Müəllif: IT Sectr Dərc olunub: 2026-03-13 Oxuma vaxtı: 9 dəq

Drift (əvvəlki adı Moor) — SQLite üzərində qurulmuş və öz DSL-i ilə Flutter və Dart üçün reaktiv ORM. Ənənəvi ORM-lərdən fərqli olaraq, Drift Dart sorğularını qurulma mərhələsində SQL-ə kompilyasiya edir və runtime səhvlərini aradan qaldırır. Drift Docs, 2024-yə görə, Drift əl ilə yazılan SQL sorğularından 40% çox kod yaradır, lakin SQL-in əl ilə yazılmasını tamamilə aradan qaldıraraq onu tip-təhlükəsiz Dart sintaksisi ilə əvəz edir.

Əsas

  • Drift — sorğuları qurulma mərhələsində SQL-ə kompilyasiya edən reaktiv ORM
  • DSL sorğuları — SQL sətrləri yazmadan Dart-da fluent interfeys
  • Reaktivlik — real vaxtda UI yenilənməsi üçün Stream və auto-updating sorğuları
  • Platformalararası — Android, iOS, Web, macOS, Linux, Windows
  • Miqrasiyalar — avtomatik versiyalaşdırma və SQL vasitəsilə əl miqrasiyaları

Drift nədir?

Drift — Dart və Flutter üçün ORM, əvvəllər Moor kimi tanınır. Simon Binder tərəfindən 2019-cu ildə hazırlanmışdır və bir neçə böyük versiya keçmişdir. Drift Dart sorğularını drift_devbuild_runner köməyi ilə qurulma mərhələsində SQL-ə kompilyasiya edir, bu da tam tip təhlükəsizliyi və runtime-da SQL sintaksis səhvlərinin qarşısını alır.

Floor-dan fərqli olaraq, Drift sorğuları qurmaq üçün öz DSL-indən (Domain-Specific Language) istifadə edir — tərtibatçı Dart-da yazır, generator isə bunu SQL-ə çevirir. Bu, IDE-yə sintaksisi yoxlamağa, cədvəl sahələrini avtomatik tamamlamağa və sorğunu pozmaq qorxusu olmadan məlumat modelini refaktor etməyə imkan verir.

Drift (2024) məlumatlarına görə, kitabxana 8000-dən çox Flutter layihəsində istifadə olunur. Bütün populyar platformaları dəstəkləyir: Android sqflite vasitəsilə, iOS sqflite vasitəsilə, web sqlite3 WASM vasitəsilə, desktop yerli sqlite3 sürücüsü vasitəsilə.

Ad dəyişikliyi tarixi: Moor → Drift

Moor 2.0 versiyasında (2022) Drift olaraq dəyişdirildi. Səbəb — digər layihələrlə ad qarışıqlığı və köhnə koddan uzaqlaşmaq istəyi. API uyğun qaldı: miqrasiya üçün import-u moor-dan drift-ə dəyişmək və asılılıqları yeniləmək kifayətdir.

Əsas imkanlar

Drift təmin edir: məlumat dəyişikliyində avtomatik yenilənən daxili Stream sorğuları, geri qaytarma ilə əməliyyatlar dəstəyi, rawQuery vasitəsilə fərdi SQL sorğuları, məntiqi inkapsulyasiya üçün DAO nümunəsi, platformalararası miqrasiyalar və drift_riverpod və drift_bloc paketləri vasitəsilə Riverpod və BLoC ilə inteqrasiya.

Drift necə işləyir?

Drift kompilyasiya mərhələsində kod generasiyasından istifadə edir. Tərtibatçı cədvəlləri @DataClass annotasiyaları və ya Table-i genişləndirən Dart sinifləri vasitəsilə təsvir edir. Generator köməkçi siniflər yaradır: Companion (əlavə/yeniləmə zamanı nullable sahələr üçün), DriftDatabase (giriş nöqtəsi) və DAO tətbiqləri.

SQLite sorğuları Drift birbaşa yerinə yetirmir. Bunun əvəzinə tərtibatçı Dart-da yazır: select(tasks).where(tasks.priority.greaterThan(3)).build(). Generator bunu SQL-ə çevirir və icra zamanı Drift sadəcə hazır SQL sorğusunu SQLite-ə göndərir. Bu, Dart sintaksisinin rahatlığını yerli SQL performansı ilə birləşdirir.

Sorğu arxitekturası

Drift iki sorğu rejimini dəstəkləyir: DSL (tövsiyə olunur) və raw SQL. DSL sorğuları daha təhlükəsizdir — kompilyator sahə adlarını, tipləri və uyğunluğu yoxlayır. Raw SQL DSL ilə əhatə olunmayan mürəkkəb sorğular üçün lazımdır: pəncərə funksiyaları, rekursiv CTE, spesifik SQLite əlavələri.

Drift DSL vs SQL: yanaşmaların müqayisəsi

Drift sorğu yazmağın iki üsulunu təklif edir: Dart DSL (yerli) və raw SQL (mürəkkəb hallar üçün). DSL 90% ssenarilər üçün üstünlük təşkil edir: daha təhlükəsiz, daha oxunaqlı və refaktoringi dəstəkləyir. Raw SQL yalnız DSL tələb olunan konstruksiyanı əhatə etmədikdə istifadə olunur.

AspektDrift DSLDrift-də Raw SQL
Tip təhlükəsizliyiTam (kompilyasiya)Yox (runtime)
Avtomatik tamamlamaBəli (IDE)Yalnız sql fayllarında
RefaktoringAvtomatikSətrlər üzrə əl axtarışı
Mürəkkəb JOINDəstəklənirTam sərbəstlik
Pəncərə funksiyalarıMəhdudTam dəstək
ReaktivlikDaxili (Stream).watch() vasitəsilə

DSL nə vaxt istifadə olunmalı

Drift DSL — əsas iş üsulu. SELECT, INSERT, UPDATE, DELETE, WHERE, ORDER BY, LIMIT, JOIN və qruplaşdırmanı əhatə edir. Bütün tipik CRUD sorğuları üçün DSL-dən istifadə edin: daha qısa, daha təhlükəsiz və dəyişikliklərdə Stream-i avtomatik yeniləyir.

Raw SQL nə vaxt istifadə olunmalı

Raw SQL Drift-də aşağıdakılar üçün lazımdır: fərdi SQLite funksiyaları (FTS5, JSON1), EXISTS ilə mürəkkəb alt sorğular, INSERT OR REPLACE, CASE ilə kütləvi UPDATE, həmçinin performansın kritik olduğu və DSL-in optimal icra planı yaratmadığı sorğular. Raw SQL tipizasiya dəstəyi ilə drift_dev vasitəsilə .sql fayllarında yazıla bilər.

Drift ilə kod nümunələri

Drift Table-i genişləndirən siniflər və ya @DataClass annotasiyasından istifadə edir. Aşağıda — DSL, raw SQL və reaktiv yeniləmə ilə Task modelinin tam nümunəsi. build_runner işə salındıqdan sonra bütün yaradılan siniflər hazırdır.

Cədvəl və verilənlər bazasının təyini

Tasks sinfi Table-i genişləndirir və sütunları müyyən edir. Hər bir sütun Column<T> tipli ifadədir. Parametrlər: withDefault() standart dəyər təyin edir, autoIncrement() avtomatik artımı təmin edir. Verilənlər bazası $DriftDatabase-i genişləndirən abstrakt sinifdir.

dart
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);
}

DSL vasitəsilə CRUD əməliyyatları

Drift cədvəllər üçün into(tasks).insert(), select(tasks), update(tasks)delete(tasks) metodlarını yaradır. Bütün əməliyyatlar Future qaytarır — SQLite ilə iş asinxrondur. Dəyişiklikləri izləmək üçün .get() əvəzinə .watch() istifadə edin.

dart
// Yazı
await into(tasks).insert(TasksCompanion.insert(
    title: Value('Məhsulları al'),
    priority: Value(3),
));

// Filterlə oxu
final highPriority = await (select(tasks)
    ..where((t) => t.priority.greaterThan(2))
    ..orderBy([(t) => OrderingTerm(expression: t.priority, mode: OrderingMode.desc)]))
    .get();

// Reaktiv müşahidə
select(tasks).watch().listen((tasksList) {
    // tasksList — List, cədvəl hər dəyişdikdə yenilənir
    updateUi(tasksList);
});

Tipləşdirilmiş nəticə ilə Raw SQL

Mürəkkəb sorğular üçün Drift raw SQL yazmağa imkan verir, eyni zamanda tipizasiyanı qoruyur. customSelect metodu sorğu sətrini qəbul edir və kod generatoru vasitəsilə tipləşdirilmiş nəticə qaytarır. Bu yanaşma SQL elastikliyini Drift tip təhlükəsizliyi ilə birləşdirir.

dart
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-də miqrasiyalar və versiyalaşdırma

Drift həm avtomatik miqrasiyaları (sadə dəyişikliklər üçün), həm də əl miqrasiyaları (mürəkkəb transformasiyalar üçün) dəstəkləyir. Verilənlər bazasının versiyası AppDatabase konstruktorunda təyin edilir. Versiya uyğunsuzluğunda Drift bütün bağlanmamış miqrasiyaları ardıcıl olaraq tətbiq edir.

Avtomatik miqrasiyalar

Standart dəyərə malik sütun əlavə etmək üçün Drift MigrationStrategy vasitəsilə avtomatik miqrasiya yarada bilər. Dəyişiklik mövcud məlumatları pozmursa (nullable sahə əlavə etmək), versiya yoxlaması və ALTER TABLE icrası ilə beforeOpen istifadə edilə bilər.

Əl miqrasiyalar

Mürəkkəb dəyişikliklər (cədvəlin adını dəyişmək, məlumatları birləşdirmək, sütun tipini dəyişmək) üçün Drift əl SQL miqrasiyası tələb edir. Miqrasiyalar verilənlər bazası sinfində migrations parametri ilə təyin edilir. Hər miqrasiya from/to nömrələri və SQL sorğuları olan obyektdir.

Drift və test etmə

Drift NativeDatabase.memory() vasitəsilə test rejimində işə salınmasını dəstəkləyir. Yaddaşda verilənlər bazası hər testdən əvvəl sıfırdan yaradılır və testdən sonra məhv edilir. Mock etmək üçün mocklanmış QueryExecutor ilə mocktail paketindən istifadə edin. Drift həmçinin miqrasiyaları və sorğuları yoxlamaq üçün inteqrasiya testləri üçün DatabaseTestHelper təqdim edir.

Drift-də DAO nümunəsi

Drift @DriftAccessor annotasiyası ilə abstrakt siniflər vasitəsilə DAO (Data Access Object) dəstəkləyir. DAO bir və ya bir neçə cədvələ sorğuları inkapsulyasiya edir və verilənlər bazasından ayrı test edilə bilər. Birbaşa Database sorğularından fərqli olaraq, DAO sorğu məntiqinin tətbiqin müxtəlf hissələri arasında təkrar istifadəsinə imkan verir və modul testlərini sadələşdirir.

dart
@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 verilən suallar

Drift Floor-dan nə ilə fərqlənir?

Drift SQL sətrləri əvəzinə öz DSL-indən istifadə edir, bu da tam tip təhlükəsizliyi və IDE-də avtomatik tamamlama təmin edir. Floor @Query annotasiyasında SQL sətrlərindən istifadə edir. Drift həmçinin daha çox platformanı (web daxil olmaqla) dəstəkləyir və Stream vasitəsilə daxili reaktivliyə malikdir, Floor-da isə Stream əl ilə elan edilməlidir.

Drift məlumat itkisi olmadan miqrasiyaları dəstəkləyirmi?

Bəli, Drift məlumatları qoruyaraq miqrasiyaları dəstəkləyir. Sütun əlavə etmək üçün Migration-da addColumn istifadə edin. Mürəkkəb transformasiyalar (ad dəyişikliyi, birləşmə) üçün miqrasiya daxilində raw SQL yazın. Miqrasiya göstərilməyibsə, sxem uyğunsuzluğunda Drift məlumat itkisi ilə bazanı yenidən yaradır.

Drift-dən build_runner olmadan istifadə etmək olarmı?

Drift build_runner və drift_dev vasitəsilə kod generasiyası tələb edir. Generasiya olmadan tipləşdirilmiş sorğular yaratmaq mümkün deyil. Bununla belə, kiçik layihələr üçün Drift sqlparser-i dəstəkləyir — avtomatik tipizasiya ilə əl SQL fayl yazmaq, lakin bu hələ də generasiya mərhələsi tələb edir.

Drift-i Riverpod ilə necə inteqrasiya etmək olar?

Riverpod ilə inteqrasiya üçün drift_riverpod paketindən istifadə edin. O, Database, DAO və Stream sorğuları üçün provider-lər təqdim edir. Nümunə: final tasksProvider = databaseProvider.select((db) => db.select(db.tasks).watch()) — UI məlumat dəyişikliyində avtomatik yenidən qurulur.

Drift SQLite şifrələməsini dəstəkləyirmi?

Drift daxili şifrələməyə malik deyil, lakin SEE (SQLite Encryption Extension) ilə fərdi sqlite3 kitabxanalarını qoşmağı dəstəkləyir. Mobil platformalar üçün QueryExecutor kimi sqflite_sqlcipher istifadə edin — Drift abstrakt QueryExecutor vasitəsilə istənilən SQLite tətbiqi ilə işləyir.

Yekun

  • Drift — sorğuları qurulma mərhələsində SQL-ə kompilyasiya edən Flutter və Dart üçün reaktiv ORM
  • DSL sintaksisi — tam tip təhlükəsizliyi və IDE-də avtomatik tamamlama ilə Dart sorğuları
  • Reaktivlik — UI-nın avtomatik yenilənməsi üçün Stream və auto-updating sorğuları
  • Platformalararası — Android, iOS, Web (WASM), macOS, Linux, Windows
  • Miqrasiyalar — sadə dəyişikliklər üçün avtomatik və mürəkkəb üçün əl SQL
  • Ekosistem — Riverpod (drift_riverpod) və BLoC (drift_bloc) ilə inteqrasiya
  • Tövsiyə — reaktivlik, tip təhlükəsizliyi və bütün Flutter platformalarının dəstəyinin vacib olduğu layihələr üçün Drift seçin

Açar təslim mobil tətbiq hazırlayacağıq

IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.

Layihəni müzakirə et

Həm də oxuyun