“This is the 22nd day of my participation in the November Gwen Challenge. See details of the event: The Last Gwen Challenge 2021”.

This article was translated from the official documentation Dart Tables (Simonbinder.eu) for Drift.

Meat turn more deficiencies, generous advice.


Important notice: MOOR has been renamed drift. More information [英 文].

The Dart table

Higher-order content of the Dart table.

Prefer SQL? If you prefer SQL, you can also declare tables using the CREATE TABLE statement. Drift’s SQL analyzer generates matching Dart code. Details (Chinese version)

Dart can be used to write SQL tables, as described in the Start Guide.

class Todos extends Table {
  IntColumn get id => integer().autoIncrement()();
  TextColumn get title => text().withLength(min: 6, max: 32) (); TextColumnget content => text().named('body') (); IntColumnget category => integer().nullable()();
}
Copy the code

This article covers the advanced features of the syntax.

named

Drift is named in the database by default using the snakelike name of the getter value in Dart (underlined with lowercase words).

The following table:

class EnabledCategories extends Table {
    IntColumn get parentCategory => integer()();
    // ..
}
Copy the code

SQL statements are generated: CREATE TABLE enabled_categories (parent_category INTEGER NOT NULL).

If you want to override the tableName, you simply override the getter for tableName. An explicit column name can be specified using the named method.

class EnabledCategories extends Table {
    String get tableName => 'categories';

    IntColumn get parentCategory => integer().named('parent') (); }Copy the code

The updated class generates SQL statements: CREATE TABLE Categories (Parent INTEGER NOT NULL).

To change the column name when serializing data to JSON, add @jsonKey to the getter.

You can also change the class name of the generated table class. By default, drift drops the S at the end of the table name (for example, the Users table generates the User data class). This is not true in all cases. For example, the EnabeldCategories table above yields (by default) the data class EnabeldCategorie. In this case, the @dataclassName annotation can be used to set the desired table name.

Can be empty (Null)

By default, data columns may not contain NULL values. If you forget to set the value when inserting, an exception will be thrown. When using SQL, Drift also gives warnings at compile time.

If you want to make a data column nullable, use nullable() :

class Items {
    IntColumn get category => integer().nullable()();
    // ...
}
Copy the code

The default value

You can set a default value for a data column. When inserting a new row of data, the default value is set if no value is specified.

To set a constant default value, use the withDefault method:

class Preferences extends Table {
  TextColumn get name => text()();
  BoolColumn get enabled => boolean().withDefault(const Constant(false())); }Copy the code

If after using into (preferences). Insert (PreferencesCompanion. ForInsert (name: ‘foo’), the enabled column of the new data row (the column in the code above) is set to false (not null, which is what we think is normal). Note that columns with a default value (using autoIncrement or using a default value) will still be marked @required in the generated data class. This is because they represent all rows of data, and each column has its own value. If you want to represent partial branches, such as inserts and updates, you can use Companion versions of data rows.

Of course, constants can only be used for static values. But what if you want to generate dynamic defaults for data columns (per row)? You can use clientDefault, which takes a function that returns the desired default value. This function is called for each row of data inserted. For example: Here is an example using the UUID package to generate a random UUID:

final _uuid = Uuid();

class Users extends Table {
    TextColumn get id => text().clientDefault(() => _uuid.v4())();
    // ...
}
Copy the code

Don’t know when to use which method? If the default is constant, use withDefault, a simple value like currentDate. More complex cases, such as randomly generated values, require clientDefault. Internally, withDefault writes the default value to the CREATE TABLE statement. This is more efficient, but dynamic values are not supported.

A primary key

If the table has an IntColumn column with an autoIncrement() constraint, Drift recognizes it as the default primary key. If you want to specify a custom primary key for a table, you can override the getter for primariKey in the table’s class.

Note that the primary key must be fundamentally fixed for the generator to recognize. This means:

  • You must use thesyntaxFunction body is not supported.
  • You must return a collection that does not contain iterable (such as if/for/ extension operators) elements.

Supported column types

Drift itself supports a variety of column types. You can use type converters to store custom classes in columns.

The Dart type column The corresponding SQLite type
int integer() INTEGER
double real() REAL
boolean boolean() INTEGER, which a CHECK to only allow 0 or 1
String text() TEXT
DateTime dateTime() INTEGER (Unix timestamp in seconds)
Uint8List blob() BLOB

Note that Boolean, dateTime mapping, and type converters only apply to storing data records in a database. They have no effect on JSON serialization. For example: Boolean values are expected to be true or false in the fromJson factory method, even though they are stored as 0 or 1 in the database. If you want a custom JSON map, you need to provide a proprietary ValueSerializer.

Custom constraints

Some column and table constraints are not supported in drift’s DART API. This includes the REFERENCES clause on the column, which can be set with customConstraint:

class GroupMemberships extends Table {
  IntColumn get group => integer().customConstraint('NOT NULL REFERENCES groups (id)') (); IntColumnget user => integer().customConstraint('NOT NULL REFERENCES users (id)') ();@override
  Set<Column> get primaryKey => {group, user};
}
Copy the code

Using customConstraint overrides all the other constraints (included by default), which means you need to include the NOT NULL constraint as well. You can also add table-level constraints by overwriting the getter for customConstraints in the table.