Para entender cómo funciona el sistema de reglas es necesario saber cuándo se invoca y cuáles son sus entradas y resultados.
El sistema de reglas se ubica entre el analizador (parser) y el planificador. Toma la salida del analizador (parser), un árbol de consulta, y las reglas de reescritura definidas por el usuario, que también son árboles de consulta con alguna información adicional, y genera cero o más árboles de consulta como resultado. Por lo tanto, su entrada y salida son siempre cosas que el propio analizador (parser) podría haber producido y, por ende, cualquier cosa que vea es básicamente representable como una sentencia SQL.
Ahora bien, ¿qué es un árbol de consulta? Es una representación interna de una
sentencia SQL donde se almacenan por separado las partes individuales
que la componen. Estos árboles de consulta se pueden mostrar
en el registro del servidor si estableces los parámetros de configuración
debug_print_parse,
debug_print_rewritten o
debug_print_plan. Las acciones de las reglas también se
almacenan como árboles de consulta en el catálogo del sistema
pg_rewrite. No tienen el mismo formato que
la salida del registro, pero contienen exactamente la misma información.
Leer un árbol de consulta sin procesar requiere cierta experiencia. Pero dado que las representaciones SQL de los árboles de consulta son suficientes para entender el sistema de reglas, este capítulo no te enseñará cómo leerlos.
Al leer las representaciones SQL de los árboles de consulta en este capítulo, es necesario poder identificar las partes en las que se divide la sentencia cuando se encuentra en la estructura del árbol de consulta. Las partes de un árbol de consulta son:
Este es un valor simple que indica qué comando
(SELECT, INSERT,
UPDATE, DELETE) produjo
el árbol de consulta.
La tabla de rangos es una lista de relaciones que se utilizan en la consulta.
En una sentencia SELECT, estas son las relaciones especificadas después
de la palabra clave FROM.
Cada entrada de la tabla de rangos identifica una tabla o vista e indica con qué nombre se la llama en las otras partes de la consulta. En el árbol de consulta, las entradas de la tabla de rangos se referencian por número en lugar de por nombre, por lo que aquí no importa si hay nombres duplicados como ocurriría en una sentencia SQL. Esto puede suceder después de haber fusionado las tablas de rangos de las reglas. Los ejemplos de este capítulo no presentarán esta situación.
Este es un índice en la tabla de rangos que identifica la relación a donde van los resultados de la consulta.
Las consultas SELECT no tienen una relación de
resultado. (El caso especial de SELECT INTO es
casi idéntico a CREATE TABLE seguido de
INSERT ... SELECT, y no se analiza
por separado aquí).
Para los comandos INSERT, UPDATE y
DELETE, la relación de resultado es la tabla
(¡o vista!) donde surtirán efecto los cambios.
La lista de objetivos es una lista de expresiones que definen el
resultado de la consulta. En el caso de un
SELECT, estas expresiones son las que
construyen la salida final de la consulta. Corresponden a las
expresiones entre las palabras clave SELECT
y FROM. (* es solo una
abreviatura para todos los nombres de columna de una relación. El
analizador (parser) la expande en las columnas individuales, por lo que el
sistema de reglas nunca la ve).
Los comandos DELETE no necesitan una lista de objetivos normal
porque no producen ningún resultado. En su lugar, el planificador
añade una entrada CTID especial a la lista de objetivos vacía,
para permitir que el ejecutor encuentre la fila a eliminar.
(CTID se añade cuando la relación de resultado es una
tabla ordinaria. Si es una vista, en su lugar se añade una variable de fila completa
por el sistema de reglas, como se describe en Section 39.2.4).
Para los comandos INSERT, la lista de objetivos describe
las nuevas filas que deben ir en la relación de resultado. Consiste en las
expresiones de la cláusula VALUES o las de la
cláusula SELECT en INSERT
... SELECT. El primer paso del proceso de reescritura añade
entradas a la lista de objetivos para cualquier columna que no haya sido asignada por
el comando original pero que tenga valores predeterminados (defaults). Cualquier columna restante (sin
valor dado ni valor predeterminado) será rellenada por el
planificador con una expresión constante nula.
Para los comandos UPDATE, la lista de objetivos
describe las nuevas filas que deben reemplazar a las antiguas. En el
sistema de reglas, contiene simplemente las expresiones de la parte SET
columna = expresión del comando. El planificador manejará
las columnas faltantes insertando expresiones que copian los valores
de la fila antigua en la nueva. Al igual que para DELETE,
se añade un CTID o una variable de fila completa para que
el ejecutor pueda identificar la fila antigua que se va a actualizar.
Cada entrada en la lista de objetivos contiene una expresión que puede ser un valor constante, una variable que apunta a una columna de una de las relaciones en la tabla de rangos, un parámetro o un árbol de expresiones compuesto por llamadas a funciones, constantes, variables, operadores, etc.
La condición (qualification) de la consulta es una expresión muy parecida a una de
las contenidas en las entradas de la lista de objetivos. El valor del resultado de
esta expresión es un booleano que indica si la operación
(INSERT, UPDATE,
DELETE o SELECT) para la
fila del resultado final se debe ejecutar o no. Corresponde a la cláusula WHERE
de una sentencia SQL.
El árbol de unión (join tree) de la consulta muestra la estructura de la cláusula FROM.
Para una consulta simple como SELECT ... FROM a, b, c, el árbol de unión es solo
una lista de los elementos de FROM, porque se nos permite unirlos en
cualquier orden. Pero cuando se utilizan expresiones JOIN, particularmente uniones externas (outer joins),
tenemos que unir en el orden indicado por las uniones.
En ese caso, el árbol de unión muestra la estructura de las expresiones JOIN. Las
restricciones asociadas con cláusulas JOIN particulares (de expresiones ON o
USING expresiones) se almacenan como expresiones de condición adjuntas
a esos nodos del árbol de unión. También resulta conveniente almacenar
la expresión WHERE de nivel superior como una condición adjunta al
elementos del árbol de unión de nivel superior. Así que, en realidad, el árbol de unión representa
tanto la cláusula FROM como la WHERE de un SELECT.
Las otras partes del árbol de consulta, como la cláusula ORDER BY,
no son de interés aquí. El sistema de reglas
sustituye algunas entradas allí al aplicar las reglas, pero eso
no tiene mucho que ver con los fundamentos del sistema de
reglas.