SQL プラグインでデータベースを使う

Recipe ID: plugin-004

SQLite, MySQL, PostgreSQL などのリレーショナルデータベースをフロントエンドから直接操作するためのプラグイン tauri-plugin-sql の使い方です。ここではセットアップが最も簡単な SQLite を例にします。

1. セットアップ

インストール

まずプラグインをプロジェクトに追加します。

npm run tauri add sql

Cargo.toml の設定

npm run tauri add しただけでは、どのデータベースを使用するか(ドライバー)が決まっていません。
src-tauri/Cargo.toml を開き、tauri-plugin-sql の行に features フラグを追加してください。

[dependencies]
# ...
# features に "sqlite", "mysql", "postgres" のいずれかを指定
tauri-plugin-sql = { version = "2.0.0", features = ["sqlite"] }

Rust 側の設定 (src-tauri/src/lib.rs)

lib.rs でプラグインを初期化します。

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .plugin(tauri_plugin_sql::Builder::default().build())
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

2. 権限の設定 (Capabilities)

src-tauri/capabilities/default.json (または類似のファイル) に、使用するデータベース接続文字列へのアクセス許可を追加します。

重要: allow 配下の name に指定する文字列は、フロントエンドで Database.load() に渡す接続文字列(sqlite:test.db など)と完全に一致させる必要があります。

{
  "permissions": [
    ...,
    {
      "identifier": "sql:default",
      "allow": [{ "name": "sqlite:test.db" }]
    },
    {
      "identifier": "sql:allow-execute",
      "allow": [{ "name": "sqlite:test.db" }]
    }
  ]
}

sql:default には select (読み取り) 権限などは含まれますが、execute (書き込み/変更) 権限は含まれていないため、別途 sql:allow-execute を追加する必要があります。

3. データベース操作 (Frontend)

TypeScript からデータベースを操作します。

import Database from '@tauri-apps/plugin-sql';

// 1. データベースのロード
// 指定したファイル名(test.db)で AppData ディレクトリ等に作成されます
const db = await Database.load('sqlite:test.db');

// 2. テーブル作成
await db.execute(
  'CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)'
);

// 3. データ挿入 (プレースホルダ $1, $2... を使用)
await db.execute(
  'INSERT INTO users (name, email) VALUES ($1, $2)',
  ['Alice', 'alice@example.com']
);

// 4. データ取得
interface User {
  id: number;
  name: string;
  email: string;
}

const result = await db.select<User[]>(
  'SELECT * FROM users WHERE name = $1',
  ['Alice']
);

console.log(result);

対応している操作

メソッド説明
load(connectionString)データベースに接続します。
execute(sql, bindValues)INSERT, UPDATE, DELETE, CREATE 等のクエリを実行します。
select(sql, bindValues)SELECT クエリを実行し、結果を配列で返します。
close()データベース接続を閉じます(通常はアプリ終了まで開いたままで構いません)。

4. マイグレーション (Rust側)

アプリのバージョンアップ時にテーブル構造を変更したい場合、Rust 側でマイグレーションを定義できます。

use tauri_plugin_sql::{Migration, MigrationKind};

pub fn run() {
    let migrations = vec![
        // V1: 初期テーブル作成
        Migration {
            version: 1,
            description: "create_initial_tables",
            sql: "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT);",
            kind: MigrationKind::Up,
        },
        // V2: カラム追加
        Migration {
            version: 2,
            description: "add_email_column",
            sql: "ALTER TABLE users ADD COLUMN email TEXT;",
            kind: MigrationKind::Up,
        }
    ];

    tauri::Builder::default()
        .plugin(
            tauri_plugin_sql::Builder::default()
                // 指定したDBに対してマイグレーションを適用
                .add_migrations("sqlite:test.db", migrations)
                .build(),
        )
        // ...
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

注意点

  • セキュリティ: フロントエンドから任意の SQL を実行できるわけではありませんが、ビジネスロジックがフロントエンドに露出することになります。センシティブなデータ操作は、カスタムコマンド (Rust) 経由で行うことを推奨します。
  • ファイルパス: sqlite:test.db のように相対パスを指定すると、自動的にプラットフォームごとの適切なアプリケーションデータディレクトリに配置されます。絶対パスの指定は、権限設定と合わせて慎重に行う必要があります。