コンパイル時に検査されるクエリ
型安全なSQL
「コンパイル時に検査されるクエリ」はCoddyKit上の無料Learn Rust Codingレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはLearn Rust Coding学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Learn Rust Codingコースには全4レッスンが含まれています。
決め手となる機能
sqlxは実際のデータベーススキーマに対して、SQLをコンパイル時に検証できます。タイプミス、誤ったカラム名、型の不一致をビルドエラーとして検出できます。
query!ファミリーのマクロを使用します- 実行時より前にバグを検出できます
query!とqueryの違い
query()関数は実行時にチェックされます。query!マクロは、ビルド中にデータベースへ接続することでコンパイル時にチェックされます。
use sqlx::{Pool, Postgres};
async fn run(pool: &Pool<Postgres>) {
let rec = sqlx::query!("SELECT id, name FROM users WHERE id = $1", 1i32)
.fetch_one(pool)
.await
.unwrap();
}型付きの結果フィールド
query!マクロは、選択したカラムに対応するフィールドを持つ匿名構造体を生成し、スキーマから正しいRustの型を推論します。
use sqlx::{Pool, Postgres};
async fn name_of(pool: &Pool<Postgres>, id: i32) -> String {
let rec = sqlx::query!("SELECT name FROM users WHERE id = $1", id)
.fetch_one(pool)
.await
.unwrap();
rec.name
}チェックの仕組み
ビルド時にsqlxは、稼働中のDATABASE_URLまたはキャッシュ済みの.sqlxディレクトリを必要とします。クエリをDBに送信し、パラメーターと結果の型を確認します。
cargo sqlx prepareによるオフラインモード
データベースを利用できないCIでは、cargo sqlx prepareを実行してクエリのメタデータを.sqlx/に保存します。その後のビルドではキャッシュが使われます。
cargo sqlx preparequery_as!で構造体に変換する
query_as!を使うと、行を定義した構造体へ直接マッピングできます。チェックも完全に行われます。
use sqlx::{Pool, Postgres};
struct User { id: i32, name: String }
async fn get(pool: &Pool<Postgres>) -> User {
sqlx::query_as!(User, "SELECT id, name FROM users WHERE id = $1", 1i32)
.fetch_one(pool)
.await
.unwrap()
}NULL可能なカラムはOptionになる
カラムがNULLになる可能性がある場合、sqlxはフィールドをOptionにします。name as "name!"のような型アノテーションで推論を上書きできます。
use sqlx::{Pool, Postgres};
async fn maybe_email(pool: &Pool<Postgres>) -> Option<String> {
let rec = sqlx::query!("SELECT email FROM users WHERE id = $1", 1i32)
.fetch_one(pool)
.await
.unwrap();
rec.email
}型推論のモデル化
コンパイル時チェックでは、SQLの型をRustの型に対応付けます。この実行可能な例では、その対応付けの判断をモデル化しています。
fn rust_type(sql: &str, nullable: bool) -> String {
let base = match sql {
"int4" => "i32",
"text" => "String",
"bool" => "bool",
_ => "unknown",
};
if nullable { format!("Option<{}>", base) } else { base.to_string() }
}
fn main() {
println!("{}", rust_type("int4", false));
println!("{}", rust_type("text", true));
}表示されるコンパイルエラー
存在しないカラムを参照すると、sqlxは明確なメッセージを表示してビルドに失敗します。この安全性こそがマクロを使う目的です。
- 誤ったカラム名 → コンパイル時エラー
- 型の不一致 → コンパイル時エラー
バインドパラメーターは位置指定
Postgresでは$1、$2のプレースホルダーを使います。sqlxは、バインドする各引数の型をスキーマと照合します。
use sqlx::{Pool, Postgres};
async fn search(pool: &Pool<Postgres>, name: &str, min_age: i32) {
let _ = sqlx::query!(
"SELECT id FROM users WHERE name = $1 AND age >= $2",
name, min_age
).fetch_all(pool).await.unwrap();
}マクロを使わない形式を使用する場合
実行時に構築する動的SQL(事前にカラムが分からない場合)には、query() / query_as()を使います。柔軟性を得る代わりに、コンパイル時チェックを失います。
use sqlx::{Pool, Postgres};
async fn dynamic(pool: &Pool<Postgres>, sql: &str) {
let _ = sqlx::query(sql).execute(pool).await.unwrap();
}理解度チェック
コンパイル時チェックについての理解度を確認しましょう。
まとめ
コンパイル時にチェックされるクエリについて学びました。
query!とquery_as!は、ビルド時にスキーマに対してSQLを検証します- 結果のフィールドと型は自動的に推論されます
- NULL可能なカラムは
Optionになります cargo sqlx prepareでオフラインビルドが可能になります- 動的SQLにはマクロを使わない
query()を使用します
次はCRUD操作です。
よくある質問
「コンパイル時に検査されるクエリ」レッスンは無料ですか?
はい。「コンパイル時に検査されるクエリ」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Learn Rust Codingコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Learn Rust Codingコースには全4レッスンが含まれています。
「コンパイル時に検査されるクエリ」で何を学びますか?
型安全なSQL ブラウザで直接実行するハンズオンコードでLearn Rust Codingを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Learn Rust Codingを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのLearn Rust Codingは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「コンパイル時に検査されるクエリ」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このLearn Rust Codingレッスンでコードを書いて実行できますか?
はい。すべてのLearn Rust Codingレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- データベースへの接続
- コンパイル時に検査されるクエリ
- CRUD操作
- マイグレーション