Formatar SQL
O Formatador de SQL reindenta uma consulta no seu navegador. Ele tokeniza o SQL primeiro, em vez de casar palavras-chave com uma expressão regular — a diferença entre um formatador que funciona e um que quebra na primeira string literal contendo a palavra FROM.
Como funciona o Formatar SQL?
Um formatador de SQL é julgado pelo que faz com a consulta que não esperava. Quatro coisas separam um que é seguro rodar sobre uma base de código de um que corrompe silenciosamente uma migração.
Tokenização, não casamento de padrões
A implementação óbvia encontra palavras-chave com uma expressão regular e insere quebras de linha. Funciona até uma consulta conter 'FROM cache' como string literal, ou um comentário contendo um apóstrofo, e então produz algo que não é mais analisável. Aqui a consulta é tokenizada primeiro — strings, identificadores, comentários, números, operadores e palavras-chave são coisas separadas —, e só os tokens de palavra-chave afetam o layout. A consulta de exemplo acima contém uma string literal com a palavra FROM por exatamente este motivo.
Identificadores entre aspas nunca são reescritos
"User" e User são objetos diferentes em um banco de dados sensível a maiúsculas e minúsculas. Um formatador que “arruma” as aspas mudou de qual tabela a consulta lê. O estilo de aspas também difere por dialeto — a crase do MySQL, os colchetes do T-SQL, as aspas duplas do padrão —, então o seletor de dialeto é sobre correção da análise, e não sobre estilo de saída.
Regras de string específicas de cada dialeto
O escape padrão para uma aspa dentro de uma string é duplicá-la; o MySQL também respeita uma barra invertida. O Postgres tem strings delimitadas por cifrão, cujo delimitador é escolhido pelo autor — $func$ … $func$ —, o que existe justamente para que um corpo de função possa conter qualquer coisa. Um tokenizador que não conhece isso encerrará uma string cedo demais, e tudo o que vier depois dela é classificado errado.
Comentários mantêm sua posição
Um comentário em linha própria continua em linha própria; um comentário à direita continua à direita. Comentários de bloco se aninham no SQL padrão, ao contrário do C, então /* a /* b */ c */ é um comentário e não um erro de sintaxe. Minificar converte um comentário -- em um comentário de bloco, porque em uma linha só um comentário de linha comentaria o resto da consulta — um detalhe pequeno que transforma uma consulta minificada em uma quebrada.
O layout que a saída usa
Cláusulas começam linhas; joins começam linhas; colunas ganham uma linha cada; conectivos booleanos em um WHERE começam uma linha de continuação, mas só no nível mais alto — um AND dentro de (y = 2 AND z = 3) é parte de uma expressão e fica onde está. Vírgulas à esquerda estão disponíveis porque tornam uma lista de colunas mais fácil de reordenar em um diff, o que é um argumento real mesmo que pareça estranho a princípio.
Entrada
select a,b from t where x=1 and y=2
Formatado
SELECT a, b FROM t WHERE x = 1 AND y = 2
Quais opções e casos-limite o Formatar SQL suporta?
| Parâmetro | Tipo | Padrão | Comportamento e casos-limite |
|---|---|---|---|
| Dialeto | standard / postgres / mysql / tsql | postgres | Afeta a análise, não o estilo: quais caracteres delimitam um identificador, como uma string escapa uma aspa e se existem dollar-quoting e comentários com #. |
| Palavras-chave em maiúsculas | booleano | ativado | Somente as palavras-chave. Identificadores, strings e comentários mantêm as maiúsculas e minúsculas originais, porque em alguns bancos de dados mudar a caixa de um identificador muda o objeto que ele nomeia. |
| Uma coluna por linha | booleano | ativado | Uma coluna selecionada por linha. Faz o diff mostrar qual coluna mudou, em vez de mostrar apenas que a linha do SELECT mudou. |
| Vírgulas no início | booleano | desativado | A vírgula antes da coluna, não depois. É um tema divisivo, e reordenar fica genuinamente mais fácil: adicionar uma coluna no fim não toca na linha anterior. |
| Literais de string | preservados | byte a byte | Incluindo o espaço em branco dentro delas. Uma string é dado, e reformatar dado não é formatação. |
| Identificadores entre aspas | preservados | — | "User" não é User em um banco de dados sensível a maiúsculas e minúsculas. As aspas nunca são adicionadas nem removidas. |
| Comentários de bloco | aninhados | — | O SQL padrão os aninha, ao contrário do C. /* a /* b */ c */ é um único comentário, e um tokenizador que para no primeiro */ interpreta mal o resto da consulta. |
| Minificar | uma linha | — | Condensa o espaço em branco e converte comentários de linha em comentários de bloco, porque um comentário -- em uma linha comenta tudo o que vem depois. |
Perguntas frequentes
Por que a consulta de exemplo tem 'FROM cache' nela?
Para demonstrar a diferença entre um formatador que tokeniza e um baseado em regex. Um formatador que encontra palavras-chave por padrão vê o FROM dentro dessa string literal, insere uma quebra de linha no meio dela e produz uma consulta que não é mais analisável. Tokenizar primeiro significa que uma string é uma string, contenha o que contiver.
Ele vai mudar os nomes das minhas tabelas ou colunas?
Não. Só os tokens de palavra-chave têm a capitalização alterada, e identificadores entre aspas passam byte a byte, incluindo suas aspas. Isso importa mais do que parece: no Postgres, "User" e User nomeiam tabelas diferentes, então um formatador que remove aspas muda o significado da consulta, e não a aparência.
Qual dialeto devo escolher?
O que o seu banco de dados realmente é, porque a configuração é sobre análise, e não estilo. O MySQL usa crases para identificadores e respeita escapes com barra invertida em strings; o T-SQL usa colchetes; o Postgres tem strings delimitadas por cifrão. Escolher o errado significa que uma string ou identificador termina no lugar errado, e tudo o que vier depois é classificado errado.
Vírgulas à esquerda — por que alguém as usaria?
Porque adicionar ou remover a última coluna de uma lista mexe em uma linha, em vez de duas. Com vírgulas à direita, acrescentar uma coluna significa editar a linha anterior para adicionar uma vírgula, então o diff mostra duas linhas alteradas e quem revisa precisa conferir as duas. Parece estranho por cerca de um dia e depois deixa de importar.
Minificar uma consulta a torna mais rápida?
Não. O banco de dados analisa a consulta antes de planejá-la, e o espaço em branco é descartado nessa etapa; uma consulta minificada e uma formatada produzem planos idênticos. Minificar serve para colocar uma consulta em uma linha — em um log, um arquivo de configuração, um comando de shell —, não para desempenho.
Minha consulta é enviada?
Não. A tokenização e a formatação rodam na aba que você já tem aberta. Isso importa aqui porque consultas carregam coisas que as pessoas não colariam em lugar nenhum: nomes de tabelas e colunas que descrevem um negócio e, com frequência, valores literais que são dados reais de clientes.