Formatear SQL
El formateador de SQL reindenta una consulta en tu navegador. Tokeniza el SQL antes de nada en lugar de buscar palabras clave con una expresión regular, y ahí está la diferencia entre un formateador que funciona y uno que se rompe con la primera cadena de texto que contiene la palabra FROM.
¿Cómo funciona Formatear SQL?
Un formateador de SQL se juzga por lo que hace con la consulta que no esperaba. Cuatro cosas separan uno que es seguro aplicar sobre una base de código de otro que corrompe una migración en silencio.
Tokenizar, no buscar patrones
La implementación obvia busca palabras clave con una expresión regular e inserta saltos de línea. Funciona hasta que una consulta contiene 'FROM cache' como literal de cadena, o un comentario con un apóstrofe, y entonces produce algo que ya no se puede analizar. Aquí la consulta se tokeniza primero —cadenas, identificadores, comentarios, números, operadores y palabras clave son cosas distintas— y solo los tokens de palabras clave afectan a la distribución. La consulta de ejemplo de arriba contiene un literal de cadena con la palabra FROM dentro por exactamente esta razón.
Los identificadores entrecomillados nunca se reescriben
"User" y User son objetos distintos en una base de datos sensible a mayúsculas y minúsculas. Un formateador que “arregla” las comillas quitándolas ya ha cambiado la tabla que lee la consulta. El estilo de entrecomillado también varía según el dialecto —las comillas invertidas de MySQL, los corchetes de T-SQL, las comillas dobles del estándar—, así que el selector de dialecto va de analizar correctamente, no del estilo de la salida.
Reglas de cadenas propias de cada dialecto
La forma estándar de escapar una comilla dentro de una cadena es duplicarla; MySQL también acepta la barra invertida. Postgres tiene cadenas delimitadas por dólar cuyo delimitador elige quien las escribe —$func$ … $func$—, que existen precisamente para que el cuerpo de una función pueda contener cualquier cosa. Un tokenizador que no conozca estas reglas cerrará una cadena antes de tiempo y todo lo que venga después queda mal clasificado.
Los comentarios conservan su posición
Un comentario en su propia línea sigue en su propia línea; un comentario al final de línea sigue al final. Los comentarios de bloque se anidan en SQL estándar, a diferencia de C, así que /* a /* b */ c */ es un solo comentario y no un error de sintaxis. Al minificar, un comentario -- se convierte en comentario de bloque, porque en una sola línea un comentario de línea dejaría comentado el resto de la consulta —un detalle pequeño que convierte una consulta minificada en una rota.
La distribución que usa la salida
Las cláusulas empiezan línea; los joins empiezan línea; cada columna tiene su propia línea; los conectores booleanos de un WHERE abren una línea de continuación, pero solo en el nivel superior —un AND dentro de (y = 2 AND z = 3) es parte de una expresión y se queda donde está. Las comas al inicio están disponibles porque hacen que una lista de columnas sea más fácil de reordenar en un diff, un argumento de peso aunque a primera vista parezca extraño.
Entrada
select a,b from t where x=1 and y=2
Formateado
SELECT a, b FROM t WHERE x = 1 AND y = 2
¿Qué opciones y casos límite admite Formatear SQL?
| Parámetro | Tipo | Valor predeterminado | Comportamiento y casos límite |
|---|---|---|---|
| Dialecto | standard / postgres / mysql / tsql | postgres | Afecta al análisis, no al estilo: qué caracteres delimitan un identificador, cómo escapa una cadena una comilla y si existen el dollar-quoting y los comentarios con #. |
| Palabras clave en mayúsculas | booleano | activado | Solo las palabras clave. Identificadores, cadenas y comentarios conservan sus mayúsculas y minúsculas originales, porque en algunas bases de datos cambiarlas en un identificador cambia el objeto al que se refiere. |
| Una columna por línea | booleano | activado | Una columna seleccionada por línea. Así un diff muestra qué columna cambió y no que la línea del SELECT cambió. |
| Comas al inicio de línea | booleano | desactivado | La coma antes de la columna, no después. Da para discusión, pero reordenar es genuinamente más fácil: añadir una columna al final no toca la línea anterior. |
| Cadenas literales | se conservan | byte a byte | Incluido el espacio en blanco que contengan. Una cadena es datos, y reformatear datos no es formatear. |
| Identificadores entrecomillados | se conservan | — | "User" no es User en una base de datos sensible a mayúsculas. Las comillas nunca se añaden ni se quitan. |
| Comentarios de bloque | anidados | — | El SQL estándar los anida, a diferencia de C. /* a /* b */ c */ es un solo comentario, y un tokenizador que se detiene en el primer */ interpreta mal el resto de la consulta. |
| Minificar | una línea | — | Reduce todo el espacio en blanco y convierte los comentarios de línea en comentarios de bloque, porque un comentario -- en una sola línea comenta todo lo que viene después. |
Preguntas frecuentes
¿Por qué la consulta de ejemplo contiene 'FROM cache'?
Para demostrar la diferencia entre un formateador que tokeniza y uno que usa expresiones regulares. Un formateador que busca palabras clave por patrón ve el FROM dentro de ese literal de cadena, inserta un salto de línea en medio de él y produce una consulta que ya no se puede analizar. Tokenizar primero significa que una cadena es una cadena, sin importar lo que contenga.
¿Cambiará los nombres de mis tablas o columnas?
No. Solo se cambia la capitalización de los tokens de palabras clave, y los identificadores entrecomillados se copian byte a byte, comillas incluidas. Esto importa más de lo que parece: en Postgres, "User" y User nombran tablas distintas, así que un formateador que quita comillas cambia el significado de la consulta, no su apariencia.
¿Qué dialecto debo elegir?
El que sea realmente tu base de datos, porque la opción va de analizar bien, no de estilo. MySQL usa comillas invertidas para los identificadores y acepta escapes con barra invertida en las cadenas; T-SQL usa corchetes; Postgres tiene cadenas delimitadas por dólar. Elegir el equivocado hace que una cadena o un identificador termine donde no debe y que todo lo que venga después quede mal clasificado.
Comas al inicio, ¿quién las querría?
Porque añadir o quitar la última columna de una lista toca una sola línea en lugar de dos. Con comas al final, añadir una columna obliga a editar la línea anterior para agregarle una coma, así que el diff muestra dos líneas cambiadas y quien revisa tiene que comprobar las dos. Resulta extraño durante un día aproximadamente y después deja de importar.
¿Minificar una consulta la hace más rápida?
No. La base de datos analiza la consulta antes de planificarla, y los espacios en blanco se descartan en esa fase; una consulta minificada y una formateada producen planes idénticos. Minificar sirve para meter una consulta en una sola línea —en un log, un archivo de configuración, un comando de shell—, no para mejorar el rendimiento.
¿Se sube mi consulta?
No. Tokenizar y formatear se ejecutan en la pestaña que ya tienes abierta. Aquí importa porque las consultas llevan cosas que nadie pegaría en cualquier parte: nombres de tablas y columnas que describen un negocio, y a menudo valores literales que son datos reales de clientes.