Skip to main content
sqlx は、接続poolと移行機能を標準で備えた、純粋な Rust 実装の非同期 SQL ツールキットです。このガイドでは、sqlx-cli の移行を使って todos テーブルを作成し、小さな axum サーバーで作成・読み取り・更新・削除のクエリを処理します。すべての接続で、証明書を完全に検証する TLS を使用します。

前提条件

  • Rust 1.94 以降。本ガイドは Rust 1.98.1、sqlx 0.9.0、sqlx-cli 0.9.0、axum 0.8.9 で動作確認しています。
  • ClickHouse Cloud アカウント
  • データベース作成用の psql。CREATE DATABASE ステートメントは SQL コンソール で実行することもできます。

ClickHouse Managed Postgres サービスを作成する

ClickHouse Cloud コンソールで New service をクリックし、Postgres を選択します。インスタンスは数分で利用可能になります。詳しい手順については、クイックスタートを参照してください。

接続情報を取得する

サービスの左サイドバーにある Connect をクリックします。Directly は選択したままにして、Use SSL をオンにします。これで、url タブに表示される接続 URL の末尾が sslmode=verify-full&sslrootcert=<service-name>-ca-certificate.pem になり、ポートは 5432 になります。 Download CA certificate をクリックします。証明書は後から Settings → CA Certificate でダウンロードすることもできます。この証明書はインスタンスごとに固有のものなので、ドライバーはこれを使って、接続先が自分のサーバーであることを検証できます。 このガイドでは、アプリと sqlx-cli のどちらも、ポート 5432 で Postgres に直接接続します。axum サーバーは長時間稼働するプロセスであり、PgPool が独自の接続 pool を保持するため、Postgres の前段に別途プーラーを置く必要はありません。移行には必ず直接接続を使用してください。多数のアプリインスタンスを実行する場合は、PgBouncer を使用するを参照してください。

プロジェクトをセットアップする

プロジェクトを作成し、Postgres ドライバー、Tokio ランタイム、rustls TLS バックエンドを有効にした sqlx を追加します。あわせて、axum といくつかの補助クレートも追加します。
同じ TLS バックエンドを指定して sqlx-cli をインストールします。
macOS では native-tls ではなく rustls を使用してくださいClickHouse Managed Postgres は TLS 1.3 のみをサポートしています。macOS では、native-tls バックエンドがシステムの Secure Transport ライブラリを使用しますが、このライブラリは TLS 1.3 に対応していません。オプションを指定せずに cargo install sqlx-cli を実行すると native-tls が使用され、すべてのコマンドが error occurred while attempting to establish a TLS connection: One or more parameters passed to a function were not valid.(または bad protocol version)というエラーで失敗します。tls-native-tls フィーチャーを有効にしてビルドしたアプリも同様です。Linux では native-tls が OpenSSL を使用するため接続自体は可能ですが、ca-certificate.pem に含まれる最初の証明書しか読み込みません。rustls はすべてのプラットフォームで TLS 1.3 をサポートし、ファイル内のすべての証明書を読み込みます。
既存のアプリに追加する場合cargo new は不要です。プロジェクト内で上記の cargo add および cargo install コマンドを実行し、接続を設定するに進んでください。アプリで sqlx を SQLite と組み合わせて使用している場合は、次の変更を行います。
  • Cargo.toml の sqlx フィーチャーから sqlite を削除し、SqlitePool を PgPool に置き換えます。
  • ? プレースホルダーを $1、$2 などに変更します。
  • 移行を Postgres の構文で書き直します。たとえば、INTEGER PRIMARY KEY AUTOINCREMENT の代わりに bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY を使用します。

接続を設定する

ダウンロードした CA 証明書をプロジェクトディレクトリに移動し、ファイル名を ca-certificate.pem にリネームします。 アプリ用のデータベースを作成します。<PASSWORD> とホストは、Connect モーダルに表示される値に置き換えてください。
プロジェクトのルートに .env ファイルを作成するか、既存の .env ファイル内の DATABASE_URL を更新して、guide_rust データベースを参照するように設定します。アプリと sqlx-cli はどちらも、このファイルから DATABASE_URL を読み込みます。
.env
sqlx は URL から sslmode と sslrootcert を読み取ります。verify-full を指定すると、サーバー証明書がインスタンスの CA によって署名されていること、および証明書がホスト名と一致することが検証されます。sslrootcert のパスは、コマンドを実行するディレクトリを基準とした相対パスとして解決されます。.env はバージョン管理の対象から除外してください。また、パスワードに @、/、# などの文字が含まれる場合は、パーセントエンコードしてください。
必ず sslmode=verify-full を設定してくださいsslmode を指定しない場合、sqlx は prefer を使用します。この場合、接続は暗号化されますが、sslrootcert を設定していてもあらゆる証明書を受け入れてしまいます。verify-full を指定した場合、CA 証明書が存在しないか誤っていると UnknownIssuer で失敗し、IP アドレスなど証明書と一致しないホストを指定すると NotValidForNameContext (sqlx-cli では certificate not valid for name) で失敗します。sslrootcert のパスが誤っている場合は No such file or directory で失敗します。

移行でテーブルを作成する

移行ファイルを作成します:
migrations ディレクトリ内に作成された新しいファイルを開き、テーブル定義を追加します。
migrations/<timestamp>_create_todos.sql
次のコマンドで適用します:
sqlx migrate run は適用済みの移行を _sqlx_migrations テーブルに記録し、以降の実行では未適用の移行のみを実行します。migrations ディレクトリはコードと一緒にコミットしてください。アプリの起動時に移行を適用したい場合は、代わりに main 内で sqlx::migrate!().run(&pool).await? を呼び出します。ただし、pool が直接接続を使用している必要があります。

API を構築する

src/main.rs を、ルートごとに 1 つのクエリを実行する小さな axum サーバーに置き換えます。既存のアプリケーションに組み込む場合は、main と同じ方法で pool を作成し、Todo 構造体、ハンドラー、ルートをお使いのルーターに追加してください。
src/main.rs
値は常に .bind を使ってパラメータ ($1) として渡され、SQL 文字列に直接埋め込まれることはありません。個々の SQL 文字列は接続ごとに一度だけプリペアされ、最大 100 個のステートメントを保持するステートメントキャッシュに格納されます。キャッシュから追い出されたステートメントは、sqlx によってクローズされます。
コンパイル時にチェックされるクエリこのガイドでは query_as 関数を使用します。この関数は実行時に SQL をチェックするため、cargo build の実行時にデータベースは必要ありません。一方、query! および query_as! マクロは、コンパイル時にデータベースに照らして SQL とカラム型をチェックします。これらのマクロはビルド時に .env から DATABASE_URL を読み込むため、この値は直接接続の設定のままにしておいてください。CI などデータベースのない環境でビルドするには、cargo sqlx prepare を実行し、生成された .sqlx ディレクトリをコミットしたうえで、SQLX_OFFLINE=true を設定してください。

実行と動作確認

サーバーを起動します。
1行目は pg_stat_ssl からの出力で、session が暗号化されていることを示しています。別の端末を開いて todo を2件作成し、1件目を完了にしてから、2件目を削除します。
各リクエストは、影響を受けた行を返します。-w '\n' オプションは、各レスポンスの後に改行を追加するためだけのものです。
ブラウザで http://localhost:3117/todos を開くと、残りの todo を一覧表示できます。
コンソールでデータを確認するには、サービスの左サイドバーで SQL コンソール を開き、guide_rust、public の順に展開して、todos テーブルをクリックします。その隣にある _sqlx_migrations テーブルには、移行履歴が格納されています。todos テーブルには、残っている行が格納されています。

PgBouncer を使用する

同梱の PgBouncer 経由でアプリを接続するには、Connect モーダルで via PgBouncer を選択し、アプリの DATABASE_URL でポート 6432 を指定します。CA 証明書は同じものをそのまま使用できます。たとえば、sqlx-cli 用の .env は直接接続の設定のままにしておき、アプリの起動時に変数を設定します。
PgBouncer を経由する場合、pg_stat_ssl が報告するのは PgBouncer 自身から Postgres への接続であるため、このチェックでは none が出力されます。ただし、アプリケーションから PgBouncer への接続は引き続き検証されます。誤った CA 証明書を使用した場合は、同様に UnknownIssuer で失敗します。 PgBouncer はトランザクションプーリングモードで動作するため、トランザクションごとに異なる Postgres 接続上で実行される可能性があります。sqlx を使用する場合は、次の点に注意してください。
  • 接続 するには、main.rs と同様に .extra_float_digits(None) を指定する必要があります。sqlx はデフォルトで extra_float_digits を起動パラメータとして送信しますが、PgBouncer は unsupported startup parameter: extra_float_digits を返して接続を拒否します。同じ理由で、PgConnectOptions::options も unsupported startup parameter in options で失敗します。
  • プリペアドステートメント はデフォルト設定のままで動作します。sqlx はキャッシュから追い出したステートメントをプロトコルレベルの Close メッセージで解放し、PgBouncer はトランザクション内であってもこれを処理します。statement_cache_capacity(0) は設定しないでください。この設定は不要なうえ、キャッシュを無効にしても sqlx は名前付きステートメントを準備し続け、それらを一切クローズしなくなります。
  • トランザクション外で実行するクエリには .persistent(false) を使用しないでください。この場合、sqlx は名前なしステートメントを準備してから 2 回目のラウンドトリップで実行しますが、PgBouncer がこれを別の Postgres 接続に送信する可能性があります。その結果、クエリが unnamed prepared statement does not exist で失敗したり、別のクライアントのステートメントが気付かないうちに実行されて誤った結果が返されたりすることがあります。
  • SET で変更した セッション設定 は、poolの after_connect フック内で変更したものも含め、自身の接続に保持されず、他のクライアントに影響が及ぶ可能性があります。代わりに、トランザクション内で SET LOCAL を使用してください。
  • 移行 には直接接続を使用する必要があります。sqlx-cli と query! マクロは常に extra_float_digits を送信するため、PgBouncer 経由では接続できません。また、sqlx::migrate! はセッションレベルのアドバイザリロック (pg_advisory_lock) を取得しますが、PgBouncer 経由ではロック解除が別の Postgres 接続に送られる可能性があります。その場合、ロックはpool内の接続で保持されたままとなり、以降の移行は直接接続によるものも含め、PgBouncer がその接続を閉じるまでハングします。

次のステップ

  • 接続: 接続文字列、PgBouncer、TLS
  • 設定: max_connections などの Postgres および PgBouncer のパラメータ
  • 読み取りレプリカ: 2 つ目の PgPool を使用して読み取り専用クエリをレプリカに送信
  • セキュリティ: IP アクセスリストとプライベートネットワーキング
最終更新日 2026年10月14日