Skip to content

Getting Started

Drift provides a dart_api to define tables and to write SQL queries. Especially when you are already familiar with SQL, it might be easier to define your tables directly in SQL, with CREATE TABLE statements. Thanks to a powerful SQL parser and analyzer built into drift, you can still run type-safe SQL queries with support for auto-updating streams and all the other drift features. The validity of your SQL is checked at build time, with drift generating matching methods for each table and SQL statement.

Setup

The basic setup of adding the drift dependencies matches the setup for the dart_apis. It is described in the setup page.

What's different is how tables and queries are declared. For SQL to be recognized by drift, it needs to be put into a .drift file. In this example, we use a .drift file next to the database class named tables.drift:

-- this is the tables.drift file
CREATE TABLE todos (
    id INT NOT NULL PRIMARY KEY AUTOINCREMENT,
    title TEXT,
    body TEXT,
    category INT REFERENCES categories (id)
);

CREATE TABLE categories (
    id INT NOT NULL PRIMARY KEY AUTOINCREMENT,
    description TEXT
) AS Category; -- see the explanation on "AS Category" below

/* after declaring your tables, you can put queries in here. Just
   write the name of the query, a colon (:) and the SQL: */
todosInCategory: SELECT * FROM todos WHERE category = ?;

/* Here's a more complex query: It counts the amount of entries per
category, including those entries which aren't in any category at all. */
countEntries:
  SELECT
    c.description,
    (SELECT COUNT(*) FROM todos WHERE category = c.id) AS amount
  FROM categories c
  UNION ALL
  SELECT null, (SELECT COUNT(*) FROM todos WHERE category IS NULL);

On that AS Category

Drift will generate Dart classes for your tables, and the name of those classes is based on the table name. By default, drift just strips away the trailing s from your table. That works for most cases, but in some (like the categories table above), it doesn't. We'd like to have a Category class (and not Categorie) generated, so we tell drift to generate a different name with the AS <name> declaration at the end.

Integrating drift files into the database simple, they just need to be added to the include parameter of the @DriftDatabase annotation. The tables parameter can be omitted here, since there are no Dart-defined tables to be added to the database.

import 'dart:io';

import 'package:drift/drift.dart';
// These imports are used to open the database
import 'package:drift/native.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart' as p;

part 'database.g.dart';

@DriftDatabase(
  // relative import for the drift file. Drift also supports `package:`
  // imports
  include: {'tables.drift'},
)
class AppDb extends _$AppDb {
  AppDb() : super(_openConnection());

  @override
  int get schemaVersion => 1;
}

LazyDatabase _openConnection() {
  // the LazyDatabase util lets us find the right location for the file async.
  return LazyDatabase(() async {
    // put the database file, called db.sqlite here, into the documents folder
    // for your app.
    final dbFolder = await getApplicationDocumentsDirectory();
    final file = File(p.join(dbFolder.path, 'db.sqlite'));

    return NativeDatabase.createInBackground(file);
  });
}

To generate the database.g.dart file which contains the _$AppDb superclass, run dart run build_runner build on the command line.