La etapa de traducci�n

La etapa de traducci�n consiste en dos partes:

Traductor

El traductor debe comprobar la cadena de caracteres de la consulta (que le llega como texto ASCII plano) para comprobar la validez de la sintaxis. Si la sintaxis es correcta, se construye un �rbol de traducci�n y se devuelve un mensaje de error en otro caso. Para la implementaci�n se han utilizado las bien conocidas herramientas de Unix lex y yacc.

El lector (lexer) se define en el fichero scan.l y es el responsable de reconocer los identificadores, las palabras clave de SQL, etc. Para cada palabra clave o identificador que encuentra, se genera y traslada al traductor traductor una se�al.

El traductor est� definido en el fichero gram.y y consiste en un conjunto de reglas de gram�tica y acciones que ser�n ejecutadas cada vez que se dispara una regla. El c�digo de las acciones (que actualmente es c�digo C) se utiliza para construir el �rbol de traducci�n.

El fichero scan.l se transforma en el fichero fuente C scan.c utilizando el programa lex u gram.y se transforma en gram.c utilizando yacc. Una vez se han realizado estas transformaciones, cualquier compilador C puede utilizarse para crear el traductor. No se deben nunca realizar cambio en los ficheros C generados, pues ser�n sobreescritos la pr�xima vez que sean llamados lex o yacc.

Nota

Las transformaciones y compilaciones mencionadas normalmente se hacen autom�ticamente utilizando los makefile vendidos con la distribuci�n de los fuentes de Postgres.

M�s adelante en este mismo documento se dar� una descripci�n detallada de yacc o de las reglas de gram�tica dadas en gram.y. Hay muchos libros y documentos relacionados con lex y yacc. Deber�a usted familiarizarse con yacc antes de empezar a estudiar la gram�tica mostrada en gram.y, pues de otro modo no entender� usted lo que est� haciendo.

Para un mejor conocimiento de las estructuras de datos utilizadas en Postgres para procesar una consulta utilizaremos un ejemplo para ilustrar los cambios hechos a estas estructuras de datos en cada etapa.

Ejemplo 1. Una SELECT sencilla

Este ejemplo contiene la siguiente consulta sencilla que ser� usada en varias descripciones y figuras a lo largo de las siguientes secciones. La consulta asume que las tablas dadas en The Supplier Database ya han sido definidas.

select s.sname, se.pno
    from supplier s, sells se
    where s.sno > 2 and s.sno = se.sno;
      

La figura \ref{parsetree} muestra el �rbol de traducci�n construido por las reglas y acciones de gram�tica dadas en gram.y para la consulta dada en Una SELECT sencillaEste ejemplo contiene la siguiente consulta sencilla que ser� usada en varias descripciones y figuras a lo largo de las siguientes secciones. La consulta asume que las tablas dadas en The Supplier Database ya han sido definidas. select s.sname, se.pno from supplier s, sells se where s.sno > 2 and s.sno = se.sno; (sin el �rbol de operador para la cl�usula WHERE que se muestra en la figura \ref{where_clause} porque no hab�a espacio suficiente para mostrar ambas estructuras de datos en una sola figura).

El nodo superior del �rbol es un nodo SelectStmt. Para cada entrada que aparece en la cl�usula FROM de la consulta de SQL se crea un nodo RangeVar que mantiene el nombre del alias y un puntero a un nodo RelExpr que mantiene el nombre de la relaci�n. Todos los nodos RangeVar est�n recogidas en una lista unida al campo fromClause del nodo SelectStmt.

Para cada entrada que aparece en la lista de la SELECT de la consulta de SQL se crea un nodo ResTarget que contiene un puntero a un nodo Attr. El nodo Attr contiene el nombre de la relaci�n de la entrada y un puntero a un nodo Value que contiene el nombre del attribute. Todos los nodos ResTarget est�n reunidos en una lista que est� conectada al campo targetList del nodo SelectStmt.

La figura \ref{where_clause} muestra el �rbol de operador construido para la clausula WHERE de la consulta de SQL dada en el ejemplo Una SELECT sencillaEste ejemplo contiene la siguiente consulta sencilla que ser� usada en varias descripciones y figuras a lo largo de las siguientes secciones. La consulta asume que las tablas dadas en The Supplier Database ya han sido definidas. select s.sname, se.pno from supplier s, sells se where s.sno > 2 and s.sno = se.sno; que est� unido al campo qual del nodo SelectStmt. El nodo superior del �rbol de operador es un nodo A_Expr representando una operaci�n AND. Este nodo tiene dos sucesores llamados lexpr y rexpr apuntando a dos sub�rboles. El sub�rbol unido a lexpr representa la cualificaci�n s.sno > 2 y el unido a rexpr representa s.sno = se.sno. Para cada atributo, se ha creado un nodo Attr que contiene el nombre de la relaci�n y un puntero a un nodo Value que contiene el nombre del atributo. Para el termino constante que aparece en la consulta, se ha creado un nodo Const que contiene el valor.

Proceso de transformaci�n

El proceso de transformaci�n toma el �rbol producido por el traductor como entrada y procede recursivamente a trav�s suyo. Si se encuentra un nodo SelectStmt, se transforma en un nodo Query que ser� el nodo superior de la nueva estructura de datos. La figura \ref{transformed} muestra la estructura de datos transformada (la parte de la cl�usula WHERE transformada se da en la figura \ref{transformed_where} porque no hay espacio suficiente para mostrarlo entero en una sola figura).

Ahora se realiza una comprobaci�n sobre si los nombres de relaciones de la cl�usula FROM son conocidas por el sistema. Para cada nombre de relaci�n que est� presente en los cat�logos del sistema, se crea un nodo RTE que contiene el nombre de la relaci�n, el nombre del alias y el identificador (id) de la relaci�n. A partir de ahora, se utilizan los identificadores de relaci�n para referirse a las relaciones dadas en la consulta. Todos los nodos RTE son recogidos en la lista de entradas de la tabla de rango que est� conectada al campo rtable del nodo Query. Si se detecta en la consulta un nombre de relaci�n desconocido para el sistema, se devuelve un error y se aborta el procesado de la consulta.

El siguiente paso es comprobar si los nombres de atributos utilizados est�n contenidos en las relaciones dadas en la consulta. Para cada atributo que se encuentra se crea un nodo TLE que contiene un puntero a un nodo Resdom (que contiene el nombre de la columna) y un puntero a un nodo VAR. Hay dos n�meros importantes en el nodo VAR. El campo varno da la posici�n de la relaci�n que contiene el atributo actual en la lista de entradas de la tabla de rango creada antes. El campo varattno da la posici�n del atributo dentro de la relaci�n. Si el nombre de un atributo no se consigue encontrar, se devuelve un error y se aborta el procesado de la consulta.