El Sistema de reglas de Postgres

Los sistemas de reglas de producción son conceptualmente simples, pero hay muchos puntos sutiles implicados en el uso actual de ellos. Algunos de estos puntos y los fundamentos teóricos del sistema de reglas de Postgres se pueden encontrar en [Stonebraker et al, ACM, 1990].

Algunos otros sistemas de base de datos definen reglas de base de datos activas. Éstas son habitualmente procedimientos y disparadores (a partir de aquí utilizaré el término más habitual de "trigger") almacenados y se implementan en Postgres como funciones y triggers.

El sistema de reglas de reescritura de queries (el "sistema de reglas" a partir de ahora) es totalmente diferente a los procedimientos almacenados y los triggers. Él modifica las queries para tomar en consideración las reglas y entonces pasa la query modificada al optimizador para su ejecución. Es muy poderoso, y puede utilizarse de muchas formas, tales como procedimientos, vistas y versiones del lenguaje de query. El poder de este sistema de reglas se discute en [Ong and Goh, 1990] y en [Stonebraker et al, ACM, 1990].

¿Qué es un árbol de query?

Para comprender como trabaja el sistema de reglas, es necesario conocer cuándo se invoca y cuáles son sus inputs y sus resultados.

El sistema de reglas se situa entre el traductor de la query y el optimizador. Toma la salida del traductor, un árbol de la query, y las reglas de reescritura del catálogo pg_rewrite, los cuales son también árboles de queries con alguna información extra, y crea cero o muchos árboles de query como resultado. De este modo, su input y su output son siempre tales como el traductor mismo podría haberlos producido y, de este modo, todo aparece básicamente repesentable como una instrucción SQL.

Ahora, ¿qué es un árbol de query? Es una representación interna de una instrucción SQL donde se almacenan de modo separado las partes menores que la componen. Estos árboles de query son visibles cuando arrancamos el motor de Postgres con nivel de debug 4 y tecleamos queries en el interface de usuario interactivo. Las acciones de las reglas almacenadas en el catalgo de sistema pg_rewrite están almacenadas también como árboles de queries. No están formateadas como la salida del debug, pero contienen exactamente la misma información.

Leer un árbol de query requiere experiencia y era bastante duro cuando empecé a trabajar en el sistema de reglas. Puedo recordar que mientras estaba esperando en la máquina de café asimilaba el vaso a una lista de objetivos, el agua y el polvo del café a una tabla de rangos, y todos los botones a expresiones de cualificación. Puesto que las representaciones de SQL de árboles de queries son suficientes para entender el sistema de reglas, este documento no le enseñará como leerlo. Él debería ayudarle a aprenderlo, con las convenciones de nombres requeridas en las descripciones que siguen más adelante.

Las partes de un árbol de query

Cuando se leen las representaciones de SQL de los árboles de queries en este documento, es necesario ser capaz de identificar las partes de la instrucción que se ha roto en ella, y que está en la estructura del árbol de query. Las partes de un árbol de query son:

El tipo de commando (commandtype)

Este es un valor sencillo que nos dice el comando que produjo el arbol de traducción (SELECT, INSERT, UPDATE, DELETE).

La tabla de rango (rangetable)

La tabla de rango es una lista de las relaciones que se utilizan en la query. En una instrucción SELECT, son las relaciones dadas tras la palabra clave FROM.

Toda entrada en la tabla del rango identifica una tabla o vista, y nos dice el nombre por el que se la identifica en las otras partes de la query. En un árbol de query, las entradas de la tabla de rango se indican por un índice en lugar de por su nombre como estarían en una instrucción SQL. Esto puede ocurrir cuando se han mezclado las tablas de rangos de reglas. Los ejemplos de este documento no muestran esa situación.

La relación-resultado (resultrelation).

Un índice a la tabla de rango que identifica la relación donde irán los resultados de la query.

Las queries SELECT normalmente no tienen una relación resultado. El caso especial de una SELECT INTO es principalmente identica a una secuencia CREATE TABLE, INSERT ... SELECT y no se discute aquí por separado.

En las queries INSERT, UPDATE y DELETE, la relación resultado es la tabla (¡o vista!) donde tendrán efecto los cambios.

La lista objetivo (targetlist).

La lista objetivo es una lista de expresiones que definen el resultado de la query. En el caso de una SELECT, las expresiones son las que construyen la salida final de la query. Son las expresiones entre las palabras clave SELECT y FROM (* es sólo una abreviatura de todos los nombres de atributos de una relación).

Las queries DELETE no necesitan una lista objetivo porque no producen ningún resultado. De hecho, el optimizador añadirá una entrada especial para una lista objetivo vacía. Pero esto ocurre tras el sistema de reglas y lo comentaremos más tarde. Para el sistema de reglas, la lista objetivo está vacía.

En queries INSERT la lista objetivo describe las nuevas filas que irán a la relación resultado. Las columnas que no aparecen en la relación resultado serán añadidas por el optimizador con una expresión constante NULL. Son las expresiones de la clausula VALUES y las de la clausula SELECT en una INSERT .... SELECT.

En queries UPDATE, describe las nuevas filas que reemplazarán a otras viejas. Ahora el optimizador añadirá las columnas que no aparecen insertando expresiones que recuperan los valores de las filas viejas en las nuevas. Y añadirá una entrada especial como lo hace DELETE. Es la parte de la query que recoge las expresiones del atributo SET atributo = expresión.

Cada entrada de la lista objetivo contiene una expresion que puede ser un valor constante, una variable apuntando a un atributo de una de las relaciones en la tabla de rango, un parámetro o un arbol de expresiones hecho de llamadas a funciones, constantes, variables, operadores, etc.

La cualificación.

La cualificación de las queries es una expresión muy similar a otra de las contenidas en las entradas de la lista objetivo. El valor resultado de esta expresión e un booleano que dice si la operación (INSERT, UPDATE, DELETE o SELECT) para las filas del resultado final deberá ser ejecutada o no. Es la clausula WHERE de una instrucción SQL.

the others

Las otras partes de un arbol de query, como la clausula ORDER BY, no tienen interés aquí. El sistema de reglas sustituye las entradas aquí presentes mientras está aplicando las reglas, pero aquellas no tiene mucho que hacer con los fundamentos del sistema de reglas. GROUP BY es una forma especial en la que aparece una definición de una vista, y aún necesita ser documentado.