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
に割り当てます。