Drift (Moor) — यह क्या है, रिएक्टिव ORM और डेटाबेस के साथ काम

लेखक: IT Sectr प्रकाशित: 2026-03-13 पढ़ने का समय: 9 मिनट

Drift (पहले Moor) Flutter और Dart के लिए एक रिएक्टिव ORM है, जो SQLite के ऊपर अपने स्वयं के DSL के साथ बनाया गया है। पारंपरिक ORM के विपरीत, Drift बिल्ड समय पर Dart क्वेरी को SQL में कंपाइल करता है, रनटाइम त्रुटियों को समाप्त करता है। Drift Docs, 2024 के अनुसार, Drift मैन्युअल SQL क्वेरी की तुलना में 40% अधिक कोड जनरेट करता है, लेकिन मैन्युअल SQL लेखन को पूरी तरह से समाप्त करता है, इसे टाइप-सेफ Dart सिंटैक्स से बदलता है।

मुख्य बिंदु

  • Drift — बिल्ड समय पर क्वेरी के SQL में कंपाइलेशन के साथ रिएक्टिव ORM
  • DSL क्वेरी — SQL स्ट्रिंग लिखे बिना Dart में फ्लूएंट इंटरफ़ेस
  • रिएक्टिविटी — रीयल-टाइम UI अपडेट के लिए Stream और ऑटो-अपडेटिंग क्वेरी
  • क्रॉस-प्लेटफ़ॉर्म — Android, iOS, Web, macOS, Linux, Windows
  • माइग्रेशन — SQL के माध्यम से स्वचालित वर्जनिंग और मैन्युअल माइग्रेशन

Drift क्या है?

Drift Dart और Flutter के लिए एक ORM है, जिसे पहले Moor के नाम से जाना जाता था। इसे Simon Binder ने 2019 में विकसित किया था और तब से यह कई प्रमुख संस्करणों से गुज़रा है। Drift drift_dev और build_runner का उपयोग करके बिल्ड समय पर Dart क्वेरी को SQL में कंपाइल करता है, जो पूर्ण टाइप सुरक्षा प्रदान करता है और रनटाइम में SQL सिंटैक्स त्रुटियों को समाप्त करता है।

Floor के विपरीत, Drift क्वेरी बनाने के लिए अपना स्वयं का DSL (डोमेन-विशिष्ट भाषा) का उपयोग करता है — डेवलपर Dart में लिखता है, और जनरेटर इसे SQL में अनुवादित करता है। यह IDE को सिंटैक्स जाँचने, टेबल फ़ील्ड को ऑटोकंप्लीट करने और क्वेरी तोड़ने के डर के बिना डेटा मॉडल को रीफ़ैक्टर करने की अनुमति देता है।

Drift (2024) के अनुसार, लाइब्रेरी का उपयोग 8000 से अधिक Flutter प्रोजेक्ट्स में किया जाता है। यह सभी लोकप्रिय प्लेटफ़ॉर्म का समर्थन करता है: Android sqflite के माध्यम से, iOS sqflite के माध्यम से, Web sqlite3 WASM के माध्यम से, डेस्कटॉप sqlite3 नेटिव ड्राइवर के माध्यम से।

नाम परिवर्तन का इतिहास: Moor → Drift

Moor का नाम बदलकर Drift संस्करण 2.0 (2022) में किया गया। इसका कारण अन्य प्रोजेक्ट्स के साथ नाम विरोध और पुराने कोड से दूरी बनाने की इच्छा थी। API संगत रहा: माइग्रेट करने के लिए, बस import को moor से drift में बदलें और निर्भरताएँ अपडेट करें।

मुख्य विशेषताएँ

Drift प्रदान करता है: डेटा बदलने पर स्वचालित अपडेट के साथ अंतर्निहित Stream क्वेरी, रोलबैक के साथ ट्रांज़ेक्शन समर्थन, rawQuery के माध्यम से कस्टम SQL क्वेरी, लॉजिक एनकैप्सुलेशन के लिए DAO पैटर्न, क्रॉस-प्लेटफ़ॉर्म माइग्रेशन और drift_riverpod और drift_bloc पैकेज के माध्यम से Riverpod और BLoC के साथ एकीकरण।

Drift कैसे काम करता है?

Drift कंपाइल समय पर कोड जनरेशन का उपयोग करता है। डेवलपर @DataClass एनोटेशन या Table को एक्सटेंड करने वाले Dart क्लास के माध्यम से टेबल का वर्णन करता है। जनरेटर हेल्पर क्लास बनाता है: Companion (इन्सर्ट/अपडेट के दौरान नल करने योग्य फ़ील्ड के लिए), DriftDatabase (एंट्री पॉइंट) और DAO इम्प्लीमेंटेशन।

Drift SQLite क्वेरी को सीधे निष्पादित नहीं करता है। इसके बजाय, डेवलपर Dart में लिखता है: select(tasks).where(tasks.priority.greaterThan(3)).build()। जनरेटर इसे SQL में अनुवादित करता है, और रनटाइम पर Drift बस तैयार SQL क्वेरी को SQLite को भेजता है। यह Dart सिंटैक्स की सुविधा को नेटिव SQL प्रदर्शन के साथ जोड़ता है।

क्वेरी आर्किटेक्चर

Drift दो क्वेरी मोड का समर्थन करता है: DSL (अनुशंसित) और रॉ SQL। DSL क्वेरी लिखना अधिक सुरक्षित है — कंपाइलर फ़ील्ड नाम, प्रकार और संगतता की जाँच करता है। रॉ SQL जटिल क्वेरी के लिए आवश्यक है जो DSL द्वारा कवर नहीं की जाती हैं: विंडो फ़ंक्शन, रिकर्सिव CTE, विशिष्ट SQLite एक्सटेंशन।

Drift DSL बनाम SQL: दृष्टिकोणों की तुलना

Drift क्वेरी लिखने के दो तरीके प्रदान करता है: Dart DSL (नेटिव) और रॉ SQL (जटिल मामलों के लिए)। DSL 90% परिदृश्यों के लिए बेहतर है: यह अधिक सुरक्षित, अधिक पठनीय और रीफ़ैक्टरिंग का समर्थन करता है। रॉ SQL का उपयोग केवल तब किया जाता है जब DSL आवश्यक निर्माण को कवर नहीं करता है।

पहलूDrift DSLDrift में रॉ SQL
टाइप सुरक्षापूर्ण (कंपाइल-टाइम)नहीं (रनटाइम)
ऑटोकंप्लीटहाँ (IDE)केवल sql फ़ाइलों में
रीफ़ैक्टरिंगस्वचालितमैन्युअल स्ट्रिंग खोज
जटिल JOINसमर्थितपूर्ण स्वतंत्रता
विंडो फ़ंक्शनसीमितपूर्ण समर्थन
रिएक्टिविटीअंतर्निहित (Stream).watch() के माध्यम से

DSL का उपयोग कब करें

Drift DSL काम करने का प्राथमिक तरीका है। यह SELECT, INSERT, UPDATE, DELETE, WHERE, ORDER BY, LIMIT, JOIN और ग्रुपिंग को कवर करता है। सभी विशिष्ट CRUD क्वेरी के लिए, DSL का उपयोग करें: यह छोटा, अधिक सुरक्षित है और बदलावों पर Stream को स्वचालित रूप से अपडेट करता है।

रॉ SQL का उपयोग कब करें

रॉ SQL Drift में आवश्यक है: कस्टम SQLite फ़ंक्शन (FTS5, JSON1), EXISTS के साथ जटिल सबक्वेरी, INSERT OR REPLACE, CASE के साथ मास UPDATE, साथ ही उन क्वेरी के लिए जहाँ प्रदर्शन महत्वपूर्ण है और DSL इष्टतम निष्पादन योजना नहीं बनाता है। रॉ SQL को drift_dev के माध्यम से टाइपिंग समर्थन के साथ .sql फ़ाइलों में लिखा जा सकता है।

Drift के साथ कोड उदाहरण

Drift उन क्लास का उपयोग करता है जो Table को एक्सटेंड करती हैं या @DataClass एनोटेशन का उपयोग करता है। नीचे DSL, रॉ SQL और रिएक्टिव अपडेट के माध्यम से क्वेरी के साथ Task मॉडल का पूर्ण उदाहरण है। build_runner चलाने के बाद, सभी जनरेट की गई क्लास तैयार हैं।

टेबल और डेटाबेस परिभाषा

Tasks क्लास Table को एक्सटेंड करती है और कॉलम को परिभाषित करती है। प्रत्येक कॉलम Column<T> प्रकार की एक अभिव्यक्ति है। पैरामीटर: withDefault() डिफ़ॉल्ट मान सेट करता है, autoIncrement() ऑटो-इंक्रीमेंट सेट करता है। डेटाबेस एक अमूर्त क्लास है जो $DriftDatabase को एक्सटेंड करता है।

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 के माध्यम से CRUD संचालन

Drift टेबल के लिए विधियाँ into(tasks).insert(), select(tasks), update(tasks) और delete(tasks) जनरेट करता है। सभी संचालन Future लौटाते हैं — SQLite के साथ काम अतुल्यकालिक है। परिवर्तनों को ट्रैक करने के लिए, .get() के बजाय .watch() का उपयोग करें।

dart
// डालें
await into(tasks).insert(TasksCompanion.insert(
    title: Value('किराने खरीदें'),
    priority: Value(3),
));

// फ़िल्टर के साथ पढ़ना
final highPriority = await (select(tasks)
    ..where((t) => t.priority.greaterThan(2))
    ..orderBy([(t) => OrderingTerm(expression: t.priority, mode: OrderingMode.desc)]))
    .get();

// रिएक्टिव निरीक्षण
select(tasks).watch().listen((tasksList) {
    // tasksList — List, तालिका में हर बदलाव पर अपडेट होता है
    updateUi(tasksList);
});

टाइप किए गए परिणाम के साथ रॉ SQL

जटिल क्वेरी के लिए, Drift टाइपिंग बनाए रखते हुए रॉ SQL लिखने की अनुमति देता है। customSelect विधि एक क्वेरी स्ट्रिंग लेती है और कोड जनरेटर के माध्यम से एक टाइप किया गया परिणाम लौटाती है। यह दृष्टिकोण SQL लचीलेपन को Drift टाइप सुरक्षा के साथ जोड़ता है।

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 में माइग्रेशन और वर्जनिंग

Drift स्वचालित माइग्रेशन (सरल परिवर्तनों के लिए) और मैन्युअल (जटिल परिवर्तनों के लिए) दोनों का समर्थन करता है। डेटाबेस संस्करण AppDatabase कंस्ट्रक्टर में सेट किया गया है। यदि संस्करण मेल नहीं खाता है, तो Drift सभी लंबित माइग्रेशन को क्रमिक रूप से लागू करता है।

स्वचालित माइग्रेशन

डिफ़ॉल्ट मान के साथ कॉलम जोड़ने के लिए, Drift MigrationStrategy के माध्यम से स्वचालित रूप से माइग्रेशन जनरेट कर सकता है। यदि परिवर्तन मौजूदा डेटा को नहीं तोड़ता है (नल करने योग्य फ़ील्ड जोड़ना), तो आप संस्करण जाँच और ALTER TABLE निष्पादन के साथ beforeOpen का उपयोग कर सकते हैं।

मैन्युअल माइग्रेशन

जटिल परिवर्तनों (टेबल का नाम बदलना, डेटा मर्ज करना, कॉलम प्रकार बदलना) के लिए, Drift को मैन्युअल SQL माइग्रेशन की आवश्यकता होती है। माइग्रेशन डेटाबेस क्लास में migrations पैरामीटर के माध्यम से निर्दिष्ट किए जाते हैं। प्रत्येक माइग्रेशन from/to नंबर और SQL क्वेरी के साथ एक ऑब्जेक्ट है।

Drift और परीक्षण

Drift NativeDatabase.memory() के माध्यम से परीक्षण मोड में चलने का समर्थन करता है। मेमोरी में डेटाबेस प्रत्येक परीक्षण से पहले स्क्रैच से बनाया जाता है और बाद में नष्ट कर दिया जाता है। मॉकिंग के लिए, मॉक किए गए QueryExecutor के साथ mocktail पैकेज का उपयोग करें। Drift माइग्रेशन और क्वेरी सत्यापन के साथ एकीकरण परीक्षण के लिए DatabaseTestHelper भी प्रदान करता है।

Drift में DAO पैटर्न

Drift @DriftAccessor एनोटेशन के साथ अमूर्त क्लास के माध्यम से DAO (डेटा एक्सेस ऑब्जेक्ट) का समर्थन करता है। DAO एक या अधिक टेबल के लिए क्वेरी को एनकैप्सुलेट करता है और डेटाबेस से अलग परीक्षण किया जा सकता है। Database के माध्यम से सीधी क्वेरी के विपरीत, DAO एप्लिकेशन के विभिन्न भागों के बीच क्वेरी लॉजिक को पुनः उपयोग करने की अनुमति देता है और यूनिट परीक्षण को सरल बनाता है।

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

अक्सर पूछे जाने वाले प्रश्न

Drift Floor से कैसे अलग है?

Drift SQL स्ट्रिंग के बजाय अपने स्वयं के DSL का उपयोग करता है, जो पूर्ण टाइप सुरक्षा और IDE में ऑटोकंप्लीट प्रदान करता है। Floor @Query एनोटेशन में SQL स्ट्रिंग का उपयोग करता है। Drift अधिक प्लेटफ़ॉर्म (web सहित) का भी समर्थन करता है और Stream के माध्यम से अंतर्निहित रिएक्टिविटी रखता है, जबकि Floor में Stream को मैन्युअल रूप से घोषित किया जाना चाहिए।

क्या Drift डेटा हानि के बिना माइग्रेशन का समर्थन करता है?

हाँ, Drift डेटा संरक्षण के साथ माइग्रेशन का समर्थन करता है। कॉलम जोड़ने के लिए, Migration में addColumn का उपयोग करें। जटिल परिवर्तनों (नाम बदलना, मर्ज करना) के लिए, माइग्रेशन के अंदर रॉ SQL लिखें। यदि कोई माइग्रेशन निर्दिष्ट नहीं है, तो Drift स्कीमा मेल न खाने पर डेटा हानि के साथ डेटाबेस को पुनः बनाता है।

क्या Drift का उपयोग build_runner के बिना किया जा सकता है?

Drift को build_runner और drift_dev के माध्यम से कोड जनरेशन की आवश्यकता होती है। जनरेशन के बिना, टाइप की गई क्वेरी बनाना असंभव है। हालांकि, छोटे प्रोजेक्ट्स के लिए, Drift sqlparser का समर्थन करता है — स्वचालित टाइपिंग के साथ मैन्युअल SQL फ़ाइल लेखन, लेकिन इसके लिए अभी भी जनरेशन चरण की आवश्यकता होती है।

Drift को Riverpod के साथ कैसे एकीकृत करें?

Riverpod के साथ एकीकरण के लिए, drift_riverpod पैकेज का उपयोग करें। यह Database, DAO और Stream क्वेरी के लिए प्रोवाइडर प्रदान करता है। उदाहरण: final tasksProvider = databaseProvider.select((db) => db.select(db.tasks).watch()) — डेटा बदलने पर UI स्वचालित रूप से पुनर्निर्माण होता है।

क्या Drift SQLite एन्क्रिप्शन का समर्थन करता है?

Drift में अंतर्निहित एन्क्रिप्शन नहीं है, लेकिन यह SEE (SQLite Encryption Extension) के साथ कस्टम sqlite3 लाइब्रेरी कनेक्ट करने का समर्थन करता है। मोबाइल प्लेटफ़ॉर्म के लिए, QueryExecutor के रूप में sqflite_sqlcipher का उपयोग करें — Drift अमूर्त QueryExecutor के माध्यम से किसी भी SQLite इम्प्लीमेंटेशन के साथ काम करता है।

सारांश

  • Drift — बिल्ड समय पर क्वेरी के SQL में कंपाइलेशन के साथ Flutter और Dart के लिए एक रिएक्टिव ORM
  • DSL सिंटैक्स — पूर्ण टाइप सुरक्षा और IDE में ऑटोकंप्लीट के साथ Dart क्वेरी
  • रिएक्टिविटी — स्वचालित UI अपडेट के लिए Stream और ऑटो-अपडेटिंग क्वेरी
  • क्रॉस-प्लेटफ़ॉर्म — Android, iOS, Web (WASM), macOS, Linux, Windows
  • माइग्रेशन — सरल परिवर्तनों के लिए स्वचालित और जटिल के लिए मैन्युअल SQL
  • इकोसिस्टम — Riverpod (drift_riverpod) और BLoC (drift_bloc) के साथ एकीकरण
  • अनुशंसा — उन प्रोजेक्ट्स के लिए Drift चुनें जहाँ रिएक्टिविटी, टाइप सुरक्षा और सभी Flutter प्लेटफ़ॉर्म का समर्थन महत्वपूर्ण है

हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे

IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।

परियोजना पर चर्चा करें

यह भी पढ़ें