Formateador de SQL para PostgreSQL

Pega una consulta de Postgres y obtén SQL limpio y con indentación consistente. Los marcadores numerados $1 de las sentencias preparadas se detectan para que puedas rellenarlos, y la sintaxis propia de Postgres —operadores JSONB, casts y cuerpos de función entre signos de dólar— se conserva.

Una consulta PostgreSQL, antes y después

La consulta sin formato de abajo es el ejemplo cargado en el editor de arriba, y la salida es exactamente lo que devuelve este formateador con las opciones por defecto. No se ha retocado nada a mano.

Pegado
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
Salida formateada
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

Sintaxis de PostgreSQL que soporta

Un formateador genérico destroza la sintaxis propia del dialecto o la rechaza directamente. Estas son las construcciones de PostgreSQL contra las que se prueba este formateador.

$1, $2

Los marcadores numerados de las sentencias preparadas se detectan y se pueden rellenar para producir una consulta ejecutable.

payload->>'key'

Los operadores JSON y JSONB se dejan exactamente como estaban escritos.

value::type

La sintaxis de cast nunca se confunde con un parámetro :name.

$$ ... $$

Los cuerpos de función entre signos de dólar se tratan como literales, así que las palabras clave que contienen no se reformatean.

WITH ... AS

La cláusula WHERE de cada CTE se lista por separado y se puede editar de forma independiente.

OVER (PARTITION BY ...)

Las funciones de ventana y sus marcos se formatean sin romper la cláusula.

Preguntas frecuentes del formateador de PostgreSQL

¿Maneja los marcadores $1 de las sentencias preparadas?

Sí. Los marcadores numerados de Postgres se detectan y aparecen en el panel de Parámetros. Rellena cada uno y cambia la salida a SQL con valores para obtener una consulta que puedes pegar directamente en psql.

¿Va a romper mis ::casts o mis operadores JSONB?

No. Los casts se distinguen de los parámetros :name, y los operadores JSON/JSONB como -> y ->> pasan sin cambios.

¿Puede formatear una consulta con varias CTE y editar solo una de ellas?

Sí. Cada cláusula WHERE aparece listada por la CTE a la que pertenece, así que una consulta hecha con una cadena de bloques WITH te da una entrada por bloque. Eliges uno, lo editas como árbol AND/OR o como grafo de nodos, y el cambio se inserta exactamente en esa cláusula mientras el resto de la consulta queda intacto byte a byte.

¿Formatea una consulta incompleta o una cláusula WHERE suelta?

Sí. Aquí nada depende de un análisis completo y válido, así que puedes pegar un fragmento sacado de un log o del volcado de depuración de un ORM —incluso un WHERE created_at >= $1 AND status = $2 solo— y seguirá formateándose y siendo editable visualmente.

¿Mantiene intactos los cuerpos PL/pgSQL entre comillas de dólar?

Sí. Un cuerpo entre dólares se trata como un único literal, de modo que las palabras clave de dentro no se reindentan como si formaran parte de la sentencia exterior, y una etiqueta de apertura solo se empareja con su propia etiqueta de cierre y no con el siguiente signo de dólar que encuentre.

¿Puede minificar una consulta de Postgres a una sola línea?

Sí: embellecer y minificar están disponibles. La minificación tiene en cuenta los espacios reales en lugar de aplicar una expresión regular indiscriminada, así que el espaciado dentro de los literales de cadena se conserva y la consulta minificada sigue devolviendo exactamente las mismas filas que la original.