Dartテーブル
リレーショナルデータベースでは、テーブルを使用して行の構造を記述します。 事前に定義されたスキーマに従うことで、Driftはデータベースに対して型安全なコードを生成できます。 セットアップページですでに示したように、DriftはDartでテーブルを宣言するためのAPIを提供します:
class TodoItems extends Table {
IntColumn get id => integer().autoIncrement()();
TextColumn get title => text().withLength(min: 6, max: 32)();
TextColumn get content => text().named('body')();
IntColumn get category => integer().nullable()();
}
このページでは、テーブルのDSLについて詳しく説明します。
カラム
各テーブルでじゃ、カラムの型、Dartでの名前、SQLにマッピングされた定義で始まるゲッターを宣言することでカラムを定義します。
上の例では、IntColumn get category => integer().nullable()();で、categoryというう名前のnullableな整数値を保持するカラムを定義しています。
このセクションでは、カラムを宣言する際に使用できるすべてのオプションについて説明します。
サポートされているカラムの型
Driftはさまざまなカラムの型をサポートしています。型変換を使用することで、独自の型をカラムに格納することもできます。
| Dartの型 | カラム | 対応するSQLiteの型 |
|---|---|---|
int | integer() | INTEGER |
BigInt | int64() | INTEGER (ウェブ上での大きな値に便利) |
double | real() | REAL |
boolean | boolean() | INTEGER, 0または1のみを許可するCHECKが必要 |
String | text() | TEXT |
DateTime | dateTime() | オプションによってはINTEGER(デフォルト)またはTEXT |
Uint8List | blob() | BLOB |
Enum | intEnum() | INTEGER (詳細はこちら) |
Enum | textEnum() | TEXT (詳細はこちら) |
boolean、dateTime、型変換のマッピングは、レコードをデータベースに格納する際にのみ適用されることに注意してください。
これらはJSON Serializationには全く影響しません。
例えば、boolean値はデータベース内では0または1として保存されますが、fromJsonファクトリではtrueまたはfalseとして期待されます。
JSON用のカスタムリマッピングをしたい場合は、独自のValueSerializerを提供する必要があります。
独自のカラム型
SQLite3がサポートする型には制約がありますが、任意のDart型をSQLに格納するための型変換をサポート しています。
class Users extends Table {
IntColumn get id => integer().autoIncrement()();
TextColumn get name => text()();
TextColumn get preferences =>
text().map(const PreferenceConverter()).nullable()();
}
型変換の詳細については、このドキュメントの型変換のページを参照してください。
BigIntサポート
Driftはint64()カラムをサポートし、カラムが大きな整数を格納し、BigIntとしてDartにマッピングされることを示します。
これは主にDartアプリがJavaScriptにコンパイルされた場合に役立ちます。
ここではintは情報を失うことなく大きな整数を格納できないdoubleです。
この場合、整数をBigIntとして表現し(それを基盤となるデータベース実装にわたすことで)、精度の損失なしに大きな整数を格納することができます。
BigIntはIntよりもオーバーヘッドが高いことに注意してください。
したがって、以下の必要があるカラムにのみint64()の使用を推奨します:
SQLite3では、INTEGERカラムは64ビット整数として格納されます。
ウェブ以外のすべてで動作するDart VMでアプリを実行している場合、Dart内のint型は64bit整数であるため、完璧に一致します。
これらのアプリに対しては、通常のinteger()カラムの使用を推奨します。
基本的に、以下の両方が真である場合にint64()を使用すべきです:
- ウェブ上で機能するアプリを駆逐している場合
- 該当するカラムが より大きな値を格納する可能性がある場合
その他のすべてのケースでは、通常のinteger()カラムを使用するのが効率的です。
BigIntをDriftで使用する際のポイントをいくつか紹介します:
- SQLite3では、
integer()とint64()は同じ列タイプなので、スキーマ移行を書かずに2つの間で切り替えることができます。 - 大きなカラムだけでなく、
BigIntとして表現したほうが良い複雑な式がSelect文に含まれている可能性もあります。 これにはdartCast()を使用できます。(table.columnA * table.columnB).dartCast<BigInt>()に対して、DriftはcolumnAとcolumnBが通常の整数として定義されていたとしても、結果の値をBigIntとして報告します。 BigIntは現在、moor_flutterおよびdrift_sqfliteには対応していません。- WebDatabaseで
BigIntサポートを使用するには、インスタンス化する際にreadIntsAsBigInt: trueフラグを設定します。 NativeDatabaseとWasmDatabaseの両方にはBigIntのサポートが組み込まれています。
DataTimeオプション
DriftはSQLにDataTime値を格納する2つのアプローチをサポートしています:
-
UNIXタイムスタンプ(デフォルト): このモードでは、DriftはUNIXタイムスタンプ(秒単位)を含むSQL
INTEGERとして日付時刻の値を格納します。 SQLからDartに日付時刻がマッピングされると、Driftは常にUTCでない値を返します。そのため、UTCの日付時刻が格納されている場合でも、行を取得する際にこの情報は失われます。 -
ISO 8601文字列: このモードでは、
DataTime.toIso8601String()に基づくテキスト形式で日付時刻の値が格納されます。 UTC値は変更されずに保存され(例えば2022-07-25 09:28:42.015Z)、ローカル値にはUTCオフセットが付加されます(例えば2022-07-25T11:28:42.015 +02:00)。 SQLite3の日付と時刻関数のほとんどはUTC値を操作しますが、SQLで日付時刻を構文解析すると、UTCオフセットが値に追加されることを尊重します。
データベースから値を読み戻すとき、DriftはDateTime.parseを以下の ように使用します:- テキスト値の末尾が
Zの場合、DriftはDateTime.parseを直接使用します。接尾辞Zが認識され、UTC値が返されます。 - テキスト値の末尾がUTCオフセット(
+02:00など)である場合、DriftはまずDateTime.parseを使用し、修飾子を尊重しながらUTC日時を返します。その後、Driftはこの中間結果に対してtoLocal()を呼び出し、ローカル値を返します。
この動作は、SQLite3の日付関数とうまく連動し、保存された値の "UTCらしさ"も保つことができます。
- テキスト値の末尾が
このモードはstore_date_time_values_as_textビルドオプションで変更できます。
使用するオプションに関係なく、Driftの組み込みの日付・時刻関数のサポートは同等の値を返します。
Driftは日付関数を動作させるためにUNIXタイムスタンプを使用する場合、内部的にunixepoch修飾子を挿入します。
テキストとして保存された日付を比較する場合、Driftはjuliandayの値を裏で比較します。
2つのモード間のマイグレーション
Dartで日付時刻モードを変更するのは、ビルドオプションを変えるだけで簡単ですが、この挙動を切り替えることは既存のデータベーススキーマと互換性がありません:
-
ビルドオプションによって、Driftは日付時刻値に文字列または整数を期待します。そのため、オプションを変更する際には、保存されている列を新しい形式に移行する必要があります。
-
.driftファイルで定義されたSQL文を使用している場合、ランタイムでカスタムSQLを使用するか、高レベルの日付時刻APIを使用する代わりに、直接FunctionCallExpressionで日付時刻式を手動で呼び出す必要がある場合、これらの使用法を適応させる必要があります。例えば、比較演算子
<はUNIXタイムスタンプに対して機能しますが、テキスト形式の日付時刻値を辞書順に比較します。したがって、使用しているモードに応じて、値をunixepochやjuliandayでラップして比較可能にする必要があります。
2番目のポイントはアプリケーションの使用法に特有のものなので、このドキュメントでは保存された列を形式間で移行する方法のみを説明します:
デフォルトで生成されるJSONシリアライゼーションは選択した日付時刻モードに影響されません。デフォルトでは、DriftはDateTime値をミリ秒単位のUNIXタイムスタンプにシリアライズします。
これを変更するには、ValueSerializer.defaults(serializeDateTimeValueAsString: true)を作成し、それをdriftRuntimeOptiuons.defaultSerializerに割り当てます。