👋

【Flutter】SQLiteでのDebugのTips

2025/02/15に公開

使用するライブラリ

https://pub.dev/packages/sqflite

sqflite を使用したデバッグ方法の解説

sqflite を使用した開発では、問題が発生した時のデバッグが重要です。この記事では、sqflite のデバッグ方法について、具体的な実装例を交えながら解説していきます。

デバッグログの実装方法

SQLite のデバッグで最も効果的な方法の一つが、SqfliteDatabaseFactoryLoggerを使用したログ出力です。

debug_example.dart
// データベースの操作をログ出力するための実装例

  // ロガーの設定とデータベースの初期化
  var factoryWithLogs = SqfliteDatabaseFactoryLogger(databaseFactory,
      options:
          SqfliteLoggerOptions(type: SqfliteDatabaseFactoryLoggerType.all));

  // データベースの作成とテーブル定義
  var db = await factoryWithLogs.openDatabase(
    join(await getDatabasesPath(), 'todo_database.db'),
    options: OpenDatabaseOptions(
      version: 1,
      onCreate: (db, version) {
        return db.execute(
          'CREATE TABLE todos(id INTEGER PRIMARY KEY, title TEXT, done INTEGER)',
        );
      },
    ),
  );

このコードを実行すると、以下のような詳細なログが出力されます:

flutter: openDatabase:({path: /Users/省略/Library/Developer/CoreSimulator/Devices/59A21D49-BCBD-493D-B172-66CBB63A44D2/data/Containers/Data/Application/88204291-0ACE-41A1-92DA-269D2F94076B/Documents/todo_database.db, options: {readOnly: false, singleInstance
flutter: query(query:({db: 1, sql: PRAGMA user_version, result: [{user_version: 0}], sw: 0:00:00.008604}))
flutter: execute(execute:({db: 1, sql: BEGIN EXCLUSIVE, result: {transactionId: 1}, sw: 0:00:00.001032}))
flutter: query(query:({db: 1, txn: 1, sql: PRAGMA user_version, result: [{user_version: 0}], sw: 0:00:00.000144}))
flutter: execute(execute:({db: 1, txn: 1, sql: CREATE TABLE todos(id INTEGER PRIMARY KEY, title TEXT, done INTEGER), sw: 0:00:00.000218}))
flutter: execute(execute:({db: 1, txn: 1, sql: PRAGMA user_version = 1, sw: 0:00:00.000128}))
flutter: execute(execute:({db: 1, txn: 1, sql: COMMIT, sw: 0:00:00.000478}))
flutter: query(query:({db: 1, sql: SELECT * FROM todos, result: [], sw: 0:00:00.273168}))
ログの詳細内容

1. データベースのオープン

// データベースファイルのパスを指定してデータベースをオープン
openDatabase:({
  path: '/Users/.../todo_database.db',
  options: {readOnly: false, singleInstance}
})

指定されたパスに Todo アプリケーション用の SQLite データベースを作成し、読み書き可能な状態でオープンしています。

2. データベースのバージョン確認

// データベースのユーザーバージョンを確認
PRAGMA user_version
// 結果: {user_version: 0}

新規作成されたデータベースのため、バージョンは 0 となっています。
PRAGMA(プラグマ)とは、SQLite の設定を変更・確認するための特別なコマンドです。

3. トランザクションの開始

// 排他的なトランザクションを開始
BEGIN EXCLUSIVE

データベースの一貫性を保つため、排他的なトランザクションを開始しています。
BEGIN EXCLUSIVE(排他的トランザクション開始)とは、他のプロセスがデータベースに書き込めないようにロックする

4. テーブルの作成

// Todosテーブルの作成
CREATE TABLE todos(
  id INTEGER PRIMARY KEY,  // 一意のID
  title TEXT,             // Todoのタイトル
  done INTEGER           // 完了状態(0:未完了, 1:完了)
)

5. バージョン管理

// データベースのバージョンを1に更新
PRAGMA user_version = 1

テーブル作成後、データベースのバージョンを 1 に更新しています。

6. トランザクションの確定

// トランザクションをコミット
COMMIT

すべての変更を確定させています。

7. データの取得

// todosテーブルから全データを取得
SELECT * FROM todos
// 結果: [] (新規作成のため、データは空)

実行時間の分析

各操作の実行時間(sw: ソフトウェアタイマー)を見ると:

  • バージョン確認: 0.008604 秒
  • トランザクション開始: 0.001032 秒
  • テーブル作成: 0.000218 秒
  • データ取得: 0.273168 秒

今回作成したアプリで hogehoge を入力して、insert query を実行すると、

flutter: insert(insert:({db: 1, sql: INSERT OR REPLACE INTO todos (title, done) VALUES (?, ?), arguments: [hogehoge, 0], result: 1, sw: 0:00:00.003601}))
flutter: query(query:({db: 1, sql: SELECT * FROM todos, result: [{id: 1, title: hogehoge, done: 0}], sw: 0:00:00.000425}))

と出力され、どのような CRUD 処理を実行したか、処理後にどんな結果が得られたかがログで出力されます。

データベースの内容確認

テーブル構造の確認

データベースの状態を確認したい場合、以下のコードで既存のテーブル情報を取得できます:

table_check.dart
// sqlite_masterテーブルの確認
print(await db.query("sqlite_master"));

ログ

[{type: table, name: todos, tbl_name: todos, rootpage: 2, sal: CREATE TABLE todos(id INTEGER PRIMARY KEY, title TEXT, done
INTEGER)}]

テーブルの内容確認

特定のテーブルの中身を確認したい場合は、以下のように実装します:

content_check.dart
// テーブルの内容を出力
print(await db.query("todos"));

ログ

雑に入力した TODO リストが出力されました。

[id: 1, title: ちいかわかわいい, done: 1}, {id: 2, title: ちいかわかわいい, done: 1}, {id: 3, title: ちいかわかわいい, done: 1}, {id: 4, title: ちいかわかわいい, done: 1}, {id: 5, title: ちいかわかわいい, done: 1}]

まとめ

SQLite のデバッグでは、ログ出力とデータベースの状態確認が重要です。この記事で紹介した手法を組み合わせることで、効率的なデバッグが可能になります。

以下は、今回作成したサンプルコードです。

https://github.com/muranakar/sqflite_debug

参照

https://github.com/tekartik/sqflite/blob/master/sqflite/doc/dev_tips.md

Discussion