mcpField
S
sqlx-code-review

sqlx-code-review

github.com/existential-birdsテスト・品質8593 回インストール11 週間前に更新
リポジトリ

sqlx-code-review について

sqlx-code-reviewは、sqlxを使うRustプロジェクトのコードレビュー向けスキルです。クエリ、プール、トランザクション、型対応、マイグレーションを確認し、重大度の判定前に根拠を求めます。

主な機能

  1. 01Cargo.toml と sqlx 設定の確認
  2. 02クエリ形式とバインドパラメーターのレビュー
  3. 03プールとトランザクション処理の確認
  4. 04Rust と SQL の型対応の検証
  5. 05重大度判定前の根拠確認

活用シーン

  1. 01Rust プロジェクトの sqlx クエリのレビュー
  2. 02プール設定とロールバック経路の確認
  3. 03マイグレーションの可逆性と安全性の評価
  4. 04ファイルと行番号を添えた指摘の記録

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/existential-birds/beagle --skill sqlx-code-review

インストール後、Claude Code で/sqlx-code-reviewを入力して読み込まれたか確認します。

同梱ファイルreferences/migrations.mdreferences/queries.md

詳細

sqlx コードレビュー

レビューワークフロー

  1. Cargo.toml を確認する — sqlx の機能(runtime-tokio、tls-rustls/tls-native-tls、postgres/mysql/sqlite、uuid、chrono、json、migrate)と Rust エディションを確認します(2024 エディションでは RPIT のライフタイムキャプチャが変更され、async-trait が不要になります)。
  2. クエリパターンを確認する — コンパイル時チェック(query!、query_as!)と実行時チェック(query、query_as)を確認します。
  3. プール設定を確認する — 接続数の上限、タイムアウト、アイドル設定を確認します。
  4. マイグレーションを確認する — ファイル名、可逆性、データマイグレーションの安全性を確認します。
  5. 型マッピングを確認する — Rust の型が SQL のカラム型と一致していることを確認します。

ゲート(重大度を付ける前に根拠を確認)

順番に完了してください。該当するゲートを通過するまでは、Critical/Major を割り当てないでください。

  1. スコープ — レビュー対象のクレート(Cargo.toml のパス)と、開いた .rs ファイル(またはディレクトリ)を特定します。合格条件: 確認した具体的なパスを少なくとも1つ挙げていること。
  2. sqlx/コンパイルに関する指摘 — query!/query_as!、オフラインモード、sqlx.toml、DATABASE_URL、または Cargo の機能に関する問題を指摘する前に、該当する Cargo.toml と、該当する場合は sqlx.toml または文書化された環境設定を開きます。合格条件: 指摘に行番号を示すか、それらのファイルが存在しない、またはスコープ外であることを明記していること。
  3. 指摘の参照箇所 — 報告する各問題には、出力形式に従って [FILE:LINE] を含めます。合格条件: 行番号の参照なしに Critical または Major としていないこと。
  4. プロトコル — ゲート1〜3の後、最終的な重大度ラベルを付ける前に、review-verification-protocol スキルを読み込み、完了します。合格条件: 継続して報告する各指摘について、プロトコルの手順を満たしていること。

出力形式

指摘は次の形式で報告します。

[FILE:LINE] ISSUE_TITLE
Severity: Critical | Major | Minor | Informational
Description of the issue and why it matters.

クイックリファレンス

問題の種類参照先
クエリマクロ、バインドパラメーター、結果マッピングreferences/queries.md
マイグレーション、プール設定、トランザクションパターンreferences/migrations.md

レビューチェックリスト

クエリパターン
  • 可能な場合はコンパイル時チェック付きクエリ(query!、query_as!)を使用している
  • オフラインでのコンパイル時チェック用に、sqlx.toml または DATABASE_URL を設定している
  • クエリに文字列補間を使用していない(SQL インジェクションのリスク)。バインドパラメーター($1、$2)を使用している
  • 公開 API では、query_as! が無名レコードではなく名前付き構造体にマッピングされている
  • .fetch_one()、.fetch_optional()、.fetch_all() を適切に選択している
  • 大きな結果セットには .fetch()(ストリーミング)を使用している
接続プール
  • PgPool を Arc またはフレームワークの状態を通じて共有している(リクエストごとに作成していない)
  • デプロイ環境に合わせてプールサイズを設定している(本番環境でデフォルトのままにしていない)
  • 接続取得のタイムアウトを設定している
  • アイドル接続のクリーンアップを設定している
  • 2024 エディション:静的プールのシングルトンには once_cell::sync::Lazy や lazy_static! ではなく、std::sync::LazyLock を使用してプールを初期化している
トランザクション
  • 複数ステートメントの操作には pool.begin() を使用している
  • 暗黙のロールバック(ドロップ時)に頼らず、トランザクションを明示的にコミットしている
  • トランザクション内でエラーが発生した場合、伝播する前にロールバックしている
  • 必要に応じて、ネストしたトランザクションにセーブポイント(tx.begin())を使用している
型マッピング
  • sqlx::Type の derive がデータベースのカラム型と一致している
  • Rust、serde、SQL 間で列挙型の表現に一貫性がある
  • 構造化データに文字列を使わず、Uuid、DateTime<Utc>、Decimal 型を使用している
  • NULL 許容カラムには Option<T> を使用している
  • JSONB カラムには serde_json::Value を使用している
  • エディション2024で予約語となる gen という名前の列挙型バリアントや構造体フィールドがない(#[sqlx(rename = "gen")] を付けた r#gen を使うか、別の名前を選択する)
Edition 2024 との互換性
  • -> impl Stream または -> impl Future を返す関数では、RPIT のライフタイムキャプチャの変更に対応しています(スコープ内のすべてのライフタイムがデフォルトでキャプチャされます。厳密に制御するには + use<'a> を使用してください)
  • カスタムの FromRow または Type トレイト実装では、該当する場合にトレイト内のネイティブな async fn を使用しています(#[async_trait] は不要です。Rust 1.75 で安定化されています)
  • 一部のコードパスでのみ使用されるコンパイル時クエリフィールドには、#[allow(unused)] ではなく #[expect(unused)] を優先しています(自動的に解消される lint 抑制。1.81 で安定化されています)
  • 静的プールの初期化には std::sync::LazyLock を使用しています(once_cell や lazy_static! ではなく)
マイグレーション
  • マイグレーションファイルが命名規則(YYYYMMDDHHMMSS_description.sql)に従っています
  • 破壊的なマイグレーション(DROP、ALTER DROP COLUMN)は元に戻せるか、データのバックアップ計画があります
  • データに依存するスキーマ変更とデータ変更を同じマイグレーションに含めていません
  • アプリケーションの起動時に sqlx::migrate!() を呼び出しています

重大度の基準

重大
  • SQL クエリでの文字列補間(SQL インジェクション)
  • 複数ステートメントの書き込みにトランザクションがない(エラー時に一部の書き込みが残る)
  • リクエストごとにコネクションプールを作成している(コネクション枯渇)
  • バインドパラメーターのエスケープがない
高
  • コンパイル時に正しさを検証できる箇所でランタイムクエリ(query())を使用している(query!() を使用できる)
  • エラー経路でトランザクションがロールバックされない
  • Rust とデータベースで列挙型が一致していない
  • 大きくなる可能性のあるテーブルに対して .fetch_all() に上限がない
  • r#gen のエスケープなしで gen という名前のフィールドまたはバリアントを使用している(Edition 2024 でコンパイルに失敗)
軽微
  • 本番環境でプールのデフォルト設定を調整せずに使用している
  • .fetch_optional() がなく、「見つからない」場合のエラー処理に .fetch_one() を使用している
  • 必要な列が限られているのに SELECT * の範囲が広すぎる
  • クエリ対象の列にインデックスがない(クエリパターンが明らかに遅い場合のみ指摘)
  • Edition 2024:std::sync::LazyLock が使える箇所で once_cell::sync::Lazy または lazy_static! を使用している
  • クエリフィールドに #[expect(unused)] ではなく #[allow(unused)] を使用している(自動的に解消される lint 抑制を優先)
情報
  • 型安全な結果マッピングに query_as! を使用する提案
  • Rust による検証と併せて、データベースレベルの制約を追加する提案
  • マイグレーションの構成改善

有効なパターン(指摘しないでください)

  • 動的クエリでのランタイム query() — 動的 SQL ではコンパイル時チェックは機能しません
  • sqlx::FromRow derive — 再利用可能な行型には query_as! の有効な代替手段です
  • 列挙型の保存に TEXT 列を使用する — sqlx::Type derive と併用すれば有効で、カスタム SQL 型より簡潔です
  • .execute() で行数を無視する — 冪等な操作(upsert、delete)では許容されます
  • 他言語とデータベースを共有する — 例:マイグレーションは Elixir が管理し、Rust が読み取ります。有効なアーキテクチャです。
  • #[sqlx(rename = "gen")] を伴う r#gen — データベース型の gen 列に対する、Edition 2024 での正しい回避策です
  • クエリヘルパーの戻り値型に + use<'a> を指定する — RPIT のライフタイムキャプチャを厳密に制御します(Edition 2024)
  • 静的プールの初期化に std::sync::LazyLock を使用する — once_cell/lazy_static に代わるものです(Rust 1.80 で安定化されています)
  • カスタムの FromRow/Type トレイト実装でネイティブな async fn を使用する — async-trait クレートは不要になりました(Rust 1.75 で安定化されています)

指摘事項を提出する前に

**ゲート(重大度判定前の証拠)**を完了してから、問題を報告する前に review-verification-protocol スキルを読み込み、その指示に従ってください。

コメント