Aller au contenu principal

Formater du SQL

Formateur SQL réindente une requête dans votre navigateur. Il tokenise d’abord le SQL au lieu de repérer les mots-clés avec une expression régulière — c’est ce qui distingue un formateur qui fonctionne d’un formateur qui casse dès la première chaîne littérale contenant le mot FROM.

100 % local
Dialecte
Indentation
SQL
0 B1 ligneLig. 1, Col. 1
Mis en formelecture seule
0 B1 ligne

Comment fonctionne Formater du SQL ?

On juge un formateur SQL à ce qu’il fait de la requête à laquelle il ne s’attendait pas. Quatre points séparent un outil que l’on peut faire passer sur tout un codebase d’un outil qui corrompt silencieusement une migration.

Tokenisation, pas recherche de motifs

L’implémentation évidente repère les mots-clés avec une expression régulière et insère des sauts de ligne. Cela fonctionne jusqu’à ce qu’une requête contienne 'FROM cache' comme chaîne littérale, ou un commentaire contenant une apostrophe — et l’outil produit alors quelque chose qui ne se parse plus. Ici, la requête est d’abord tokenisée — chaînes, identifiants, commentaires, nombres, opérateurs et mots-clés sont des choses distinctes — et seuls les tokens mots-clés influent sur la mise en page. La requête d’exemple ci-dessus contient une chaîne littérale avec le mot FROM pour exactement cette raison.

Les identifiants entre guillemets ne sont jamais réécrits

"User" et User sont deux objets distincts sur une base de données sensible à la casse. Un formateur qui « nettoie » les guillemets a changé la table lue par la requête. Le style de guillemets varie aussi selon le dialecte — le backtick de MySQL, les crochets de T-SQL, le guillemet double standard — le sélecteur de dialecte porte donc sur la justesse de l’analyse, pas sur le style de sortie.

Des règles de chaînes propres à chaque dialecte

L’échappement standard d’un guillemet dans une chaîne consiste à le doubler ; MySQL accepte aussi un antislash. Postgres connaît les chaînes entre dollars, dont l’auteur choisit le délimiteur — $func$ … $func$ — précisément pour qu’un corps de fonction puisse contenir n’importe quoi. Un tokenizer qui ignore ces règles terminera une chaîne trop tôt, et tout ce qui suit est mal classé.

Les commentaires gardent leur position

Un commentaire seul sur sa ligne reste seul sur sa ligne ; un commentaire en fin de ligne reste en fin de ligne. Les commentaires de bloc s’imbriquent en SQL standard, contrairement au C, donc /* a /* b */ c */ est un seul commentaire et non une erreur de syntaxe. La minification convertit un commentaire -- en commentaire de bloc, car sur une seule ligne un commentaire de ligne mettrait le reste de la requête en commentaire — un petit détail qui transforme une requête minifiée en requête cassée.

La mise en page du résultat

Les clauses commencent une ligne ; les jointures commencent une ligne ; chaque colonne a sa ligne ; les connecteurs booléens dans un WHERE ouvrent une ligne de continuation, mais seulement au premier niveau — un AND à l’intérieur de (y = 2 AND z = 3) fait partie d’une expression et reste où il est. Les virgules en tête sont disponibles parce qu’elles facilitent la réorganisation d’une liste de colonnes dans un diff — un argument solide, même si cela paraît étrange au premier abord.

Entrée

select a,b from t where x=1 and y=2

Formaté

SELECT
  a,
  b
FROM t
WHERE x = 1
  AND y = 2

Quelles options et quels cas limites Formater du SQL prend en charge ?

Référence technique et options
ParamètreTypeValeur par défautComportement et cas limites
Dialectestandard / postgres / mysql / tsqlpostgresAffecte l’analyse, pas le style : quels caractères citent un identifiant, comment une chaîne échappe un guillemet, et si le dollar-quoting et les commentaires # existent.
Mots-clés en majusculesbooléenactivéLes mots-clés uniquement. Les identifiants, les chaînes et les commentaires gardent leur casse d’origine, car sur certaines bases de données changer la casse d’un identifiant change l’objet qu’il désigne.
Une colonne par lignebooléenactivéUne colonne sélectionnée par ligne. Le diff montre alors quelle colonne a changé, et pas simplement que la ligne SELECT a changé.
Virgules en têtebooléendésactivéLa virgule avant la colonne plutôt qu’après. C’est clivant, mais c’est réellement plus facile à réordonner : ajouter une colonne à la fin ne touche pas la ligne précédente.
Littéraux de chaîneconservésoctet par octetY compris les espaces qu’elles contiennent. Une chaîne est une donnée, et reformater une donnée, ce n’est pas du formatage.
Identifiants entre guillemetsconservés—"User" n’est pas User sur une base de données sensible à la casse. Les guillemets ne sont jamais ajoutés ni retirés.
Commentaires de blocimbriqués—Le SQL standard les imbrique, contrairement au C. /* a /* b */ c */ est un seul commentaire, et un tokeniseur qui s’arrête au premier */ lit de travers le reste de la requête.
Minifierune ligne—Condense les espaces et convertit les commentaires de ligne en commentaires de bloc, car un commentaire -- sur une seule ligne met tout ce qui suit en commentaire.

Questions fréquentes

Pourquoi la requête d’exemple contient-elle 'FROM cache' ?

Pour montrer la différence entre un formateur qui tokenise et un formateur à base de regex. Celui qui repère les mots-clés par motif voit le FROM à l’intérieur de cette chaîne littérale, y insère un saut de ligne et produit une requête qui ne se parse plus. Tokeniser d’abord, c’est garantir qu’une chaîne reste une chaîne quel que soit son contenu.

Va-t-il changer mes noms de tables ou de colonnes ?

Non. Seuls les tokens mots-clés sont recasés, et les identifiants entre guillemets passent octet pour octet, guillemets compris. C’est plus important qu’il n’y paraît : sur Postgres, "User" et User désignent des tables différentes, donc un formateur qui supprime les guillemets change le sens de la requête et non seulement son apparence.

Quel dialecte choisir ?

Celui de votre base de données réelle, car ce réglage concerne l’analyse et non le style. MySQL utilise des backticks pour les identifiants et accepte les échappements par antislash dans les chaînes ; T-SQL utilise des crochets ; Postgres a les chaînes entre dollars. Se tromper signifie qu’une chaîne ou un identifiant se termine au mauvais endroit et que tout ce qui suit est mal classé.

Virgules en tête — mais pourquoi ?

Parce qu’ajouter ou retirer la dernière colonne d’une liste ne touche qu’une ligne au lieu de deux. Avec des virgules en fin, ajouter une colonne oblige à modifier la ligne précédente pour y placer la virgule : le diff montre alors deux lignes changées et le relecteur doit vérifier les deux. Cela paraît étrange pendant une journée environ, puis on n’y pense plus.

Minifier une requête la rend-elle plus rapide ?

Non. La base de données analyse la requête avant de la planifier, et les espaces sont écartés à ce stade ; une requête minifiée et une requête formatée produisent des plans identiques. Minifier sert à faire tenir une requête sur une ligne — dans un log, un fichier de configuration, une commande shell — pas à gagner en performance.

Ma requête est-elle envoyée ?

Non. La tokenisation et le formatage s’exécutent dans l’onglet déjà ouvert. C’est important ici parce que les requêtes transportent des choses que personne ne collerait n’importe où : des noms de tables et de colonnes qui décrivent une activité, et souvent des valeurs littérales qui sont de vraies données clients.