PostgreSQL SQL フォーマッター

Postgres のクエリを貼り付ければ、きれいで一貫したインデントの SQL が得られます。プリペアドステートメントの番号付きプレースホルダー $1 が検出されるので値を入力でき、JSONB 演算子、キャスト、ドル引用符で囲まれた関数本体といった Postgres 固有の構文も保持されます。

PostgreSQL のクエリ、整形前と整形後

下の未整形のクエリは、上のエディタに読み込まれているサンプルそのものです。出力はデフォルト設定でこのフォーマッターが返す内容そのままで、手作業で整えた箇所はありません。

貼り付けた内容
WITH recent AS (SELECT user_id, count(*) AS n, max(created_at) AS last_seen FROM events WHERE created_at >= $1 AND payload->>'type' = $2 GROUP BY user_id) SELECT u.id, u.email, r.n, row_number() OVER (ORDER BY r.n DESC) AS rank FROM users u JOIN recent r ON r.user_id = u.id WHERE u.status = 'active' AND u.created_at::date BETWEEN $3 AND $4 ORDER BY r.n DESC LIMIT 50
整形後の出力
WITH
  recent AS (
    SELECT
      user_id,
      count(*) AS n,
      max(created_at) AS last_seen
    FROM
      events
    WHERE
      created_at >= $1
      AND payload ->> 'type' = $2
    GROUP BY
      user_id
  )
SELECT
  u.id,
  u.email,
  r.n,
  row_number() OVER (
    ORDER BY
      r.n DESC
  ) AS rank
FROM
  users u
  JOIN recent r ON r.user_id = u.id
WHERE
  u.status = 'active'
  AND u.created_at::date BETWEEN $3 AND $4
ORDER BY
  r.n DESC
LIMIT
  50

対応している PostgreSQL の構文

汎用のフォーマッターは方言固有の構文を壊すか、そもそも受け付けません。ここに挙げるのは、このフォーマッターがテストで確認している PostgreSQL の構文です。

$1, $2

プリペアドステートメントの番号付きプレースホルダーが検出され、値を入力して実行可能なクエリを作れます。

payload->>'key'

JSON および JSONB 演算子は書かれたとおりに保たれます。

value::type

キャストの構文が :name パラメーターと取り違えられることはありません。

$$ ... $$

ドル引用符で囲まれた関数本体はリテラルとして扱われるため、その中のキーワードが再整形されることはありません。

WITH ... AS

各 CTE の WHERE 句が個別に一覧され、それぞれ単独で編集できます。

OVER (PARTITION BY ...)

ウィンドウ関数とそのフレームは、句を分断することなく整形されます。

PostgreSQL フォーマッターのよくある質問

プリペアドステートメントの $1 プレースホルダーに対応していますか?

はい。Postgres の番号付きプレースホルダーは検出され、パラメーターパネルに一覧されます。それぞれ入力して出力を値入り SQL に切り替えれば、psql にそのまま貼り付けられるクエリが得られます。

::キャストや JSONB 演算子が壊れませんか?

壊れません。キャストは :name パラメーターと区別され、-> や ->> といった JSON/JSONB 演算子はそのまま通過します。

複数の CTE を含むクエリを整形し、そのうち 1 つだけを編集できますか?

はい。すべての WHERE 句が所属する CTE ごとに一覧表示されるので、WITH ブロックを連ねたクエリではブロックごとに 1 項目が並びます。1 つを選んで AND/OR ツリーまたはノードグラフとして編集すると、変更はその句だけに差し戻され、クエリの残りはバイト単位でそのまま残ります。

不完全なクエリや WHERE 句だけでも整形できますか?

はい。ここでは完全で妥当な解析結果に依存する処理がないため、ログ行や ORM のデバッグ出力から取り出した断片を貼っても、WHERE created_at >= $1 AND status = $2 だけでも、整形されビジュアル編集もできます。

ドル引用の中の PL/pgSQL 本体はそのまま保たれますか?

はい。ドル引用された本体は 1 つのリテラルとして扱われるため、中のキーワードが外側の文の一部であるかのようにインデントし直されることはありません。開始タグは対応する終了タグとだけ対応付けられ、次に見つかったドル記号とは結び付きません。

Postgres のクエリを 1 行に最小化できますか?

はい。整形と最小化のどちらも使えます。最小化は一括の正規表現ではなく実際の空白を見て処理するため、文字列リテラル内の空白はそのまま保たれ、最小化後のクエリも元とまったく同じ行を返します。