Pular para o conteúdo principal

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.

Só local
Dialeto
Recuo
SQL
0 B1 linhaLin. 1, Col. 1
Formatadosomente leitura
0 B1 linha

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?

Referência técnica e opções
ParâmetroTipoPadrãoComportamento e casos-limite
Dialetostandard / postgres / mysql / tsqlpostgresAfeta 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úsculasbooleanoativadoSomente 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 linhabooleanoativadoUma 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íciobooleanodesativadoA 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 stringpreservadosbyte a byteIncluindo o espaço em branco dentro delas. Uma string é dado, e reformatar dado não é formatação.
Identificadores entre aspaspreservados—"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 blocoaninhados—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.
Minificaruma 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.