L'étape d'analyse est constituée de deux parties :
l'analyseur, défini dans
gram.y
et scan.l
, est construit
en utilisant les outils Unix bison et
flex ;
le processus de transformation fait des modifications et des ajouts aux structures de données renvoyées par l'analyseur.
L'analyseur doit vérifier que la syntaxe de la chaîne de la requête (arrivant comme un texte) est valide. Si la syntaxe est correcte, un arbre d'analyse est construit et renvoyé, sinon une erreur est retournée. Les analyseur et vérificateur syntaxiques sont développés à l'aide des outils Unix bien connus bison et flex.
L'analyseur lexical, défini dans le fichier
scan.l
, est responsable de la reconnaissance des
identificateurs, des mots clés
SQL, etc. Pour chaque mot clé ou identificateur trouvé, un
jeton est engendré et renvoyé à l'analyseur.
L'analyseur est défini dans le fichier gram.y
et
consiste en un ensemble de règles de grammaire et
en des actions à exécuter lorsqu'une règle est
découverte. Le code des actions (qui est en langage C) est utilisé pour
construire l'arbre d'analyse.
Le fichier scan.l
est transformé en fichier source C
scan.c
en utilisant le programme
flex et gram.y
est
transformé en gram.c
en utilisant
bison. Après avoir réalisé ces transformations,
un compilateur C normal peut être utilisé pour créer l'analyseur. Il
est inutile de modifier les fichiers C engendrés car ils sont écrasés
à l'appel suivant de flex ou
bison.
Les transformations et compilations mentionnées sont normalement réalisées automatiquement en utilisant les makefile distribués avec les sources de PostgreSQL.
La description détaillée de bison ou des règles
de grammaire données dans gram.y
dépasse le cadre
de ce manuel. Il existe de nombreux livres et documentations en
relation avec flex et
bison. Il est préférable d'être familier avec
bison avant de commencer à étudier la grammaire
donnée dans gram.y
, au risque de ne rien y
comprendre.
L'étape d'analyse crée un arbre d'analyse qui n'utilise que les règles fixes de la structure syntaxique de SQL. Il ne fait aucune recherche dans les catalogues système. Il n'y a donc aucune possibilité de comprendre la sémantique détaillée des opérations demandées. Lorsque l'analyseur a fini, le processus de transformation prend en entrée l'arbre résultant de l'analyseur et réalise l'interprétation sémantique nécessaire pour connaître les tables, fonctions et opérateurs référencés par la requête. La structure de données construite pour représenter cette information est appelée l'arbre de requête.
La séparation de l'analyse brute et de l'analyse sémantique
résulte du fait que les recherches des catalogues système ne peuvent
se dérouler qu'à l'intérieur d'une transaction. Or, il n'est pas
nécessaire de commencer une transaction dès la réception d'une requête.
L'analyse brute est suffisante pour identifier les commandes de contrôle
des transactions (BEGIN
, ROLLBACK
,
etc.). Elles peuvent de plus être correctement exécutées sans
analyse complémentaire. Lorsqu'il est établi qu'une vraie requête doit
être gérée (telle que SELECT
ou
UPDATE
), une nouvelle transaction est démarrée si
aucune n'est déjà en cours. Ce n'est qu'à ce moment-là que le processus
de transformation peut être invoqué.
La plupart du temps, l'arbre d'une requête créé par le processus de
transformation a une structure similaire à l'arbre d'analyse brute
mais, dans le détail, de nombreuses différences existent.
Par exemple, un nœud
FuncCall
dans l'arbre d'analyse représente quelque chose qui
ressemble syntaxiquement à l'appel d'une fonction. Il peut être transformé
soit en nœud FuncExpr
, soit en nœud
Aggref
, selon que le nom référencé est une fonction
ordinaire ou une fonction d'agrégat. De même, des informations sur les
types de données réels des colonnes et des résultats sont ajoutées à
l'arbre de la requête.