41.1. Дерево запроса #
Чтобы понять, как работает система правил, нужно знать, когда она вызывается, что принимает на вход и какой результат выдаёт.
Система правил внедрена между анализатором запросов и планировщиком. Она принимает разобранный запрос, одно дерево запроса, и определённые пользователем правила перезаписи, тоже представленные деревьями с некоторой дополнительной информацией, и создаёт некоторое количество деревьев запросов в результате. Таким образом, на входе и выходе этой системы оказывается то, что может сформировать анализатор запросов, и как следствие, всё, с чем работает эта система, представимо в виде операторов SQL.
Так что же такое дерево запроса? Это внутреннее представление оператора SQL, в котором все образующие его части хранятся отдельно. Эти деревья можно увидеть в журнале сервера, если установить параметры конфигурации debug_print_parse, debug_print_rewritten или debug_print_plan. Действия правил также хранятся в виде деревьев запросов, в системном каталоге pg_rewrite. Они не форматируются как при выводе в журнал, но содержат точно такую же информацию.
Для прочтения неформатированного дерева требуется некоторый навык. Но так как представления дерева запросов в виде SQL достаточно, чтобы понять систему правил, в этой главе не будет рассказываться, как их читать.
Читая SQL-представления деревьев запросов в этой главе, необходимо понимать, на какие части разбивается оператор, когда он преобразуется в структуру дерева запроса. Дерево запроса состоит из следующих частей:
- тип команды
Это простое значение, говорящее, какая команда (
SELECT,INSERT,UPDATEилиDELETE) сгенерировала дерево запросов.- список отношений
Список отношений представляет собой массив отношений, используемых в запросе. В запросе
SELECTон включает отношения, указанные после ключевого словаFROM.Каждый элемент списка отношений представляет таблицу или представление и говорит, с каким именем они упоминаются в других частях запроса. В дереве запросов записываются номера элементов списка отношений, а не их имена, поэтому для него неактуальна проблема дублирования имён, как для оператора SQL. Такая проблема может возникнуть при объединении списков отношений, образованных разными правилами. В этой главе данная ситуация рассматриваться не будет.
- результирующее отношение
Индекс в списке отношений, указывающий на отношение, которое будет получать результаты запроса.
В запросах
SELECTрезультирующее отношение отсутствует. (Особый случайSELECT INTOпрактически равнозначенCREATE TABLEс последующимINSERT ... SELECTи здесь отдельно не рассматривается.)Для команд
INSERT,UPDATEиDELETEрезультирующим отношением будет таблица (или представление!), в которой будут происходить изменения.- выходной список
Выходной список — это список выражений, определяющих результат запроса. В случае
SELECT, это выражения, которые образуют окончательный набор выходных данных. Они соответствуют выражениям, записанным между ключевыми словамиSELECTиFROM. (Указание*— это просто краткое обозначение имён всех столбцов отношения. Анализатор разворачивает его в список отдельных столбцов, так что система правил никогда не видит его.)Командам
DELETEне нужен обычный выходной список, так как они не выдают никакие результаты. Вместо этого планировщик добавляет в пустой выходной список специальную запись CTID, чтобы исполнитель мог найти удаляемую строку. (CTID добавляется, когда результирующее отношение — обычная таблица. Если это представление, планировщиком добавляется переменная, содержащая всю строку, как рассказывается в Подразделе 41.2.4.)Для команд
INSERTвыходной список описывает новые строки, которые должны попасть в результирующее отношение. Он включает выражения в предложенииVALUESили предложенииSELECTвINSERT ... SELECT. На первом этапе процесс перезаписи добавляет элементы выходного списка для столбцов, которым ничего не присвоила исходная команда, но имеющих значения по умолчанию. Все остальные столбцы (без заданного значения и значения по умолчанию) планировщик заполняет константой NULL.Для команд
UPDATEвыходной список описывает новые строки, которые должны заменить старые. В системе правил он содержит только выражения из частиSET столбец = выражение. Для пропущенных столбцов планировщик вставляет выражения, копирующие значения из старой строки в новую. Так же, как и с командойDELETE, при этом добавляется CTID или переменная со всей строкой, чтобы исполнитель мог найти изменяемую старую строку.Каждая запись в выходном списке содержит выражение, которое может быть константой, переменной, указывающей на столбец отношения в таблице отношений, параметром или деревом выражений, образованным из констант, переменных, операторов, вызовов функций и т. д.
- условие фильтра
Условие фильтра запроса — это выражение, во многом похожее на те, что содержатся в выходном списке. Результат этого выражения — логический, он говорит, должна ли выполняться операция (
INSERT,UPDATE,DELETEилиSELECT) для данной строки в результате. Оно соответствует предложениюWHERESQL-оператора.- дерево соединения
Дерево соединения запроса показывает структуру предложения
FROM. Для простых запросов видаSELECT ... FROM a, b, c, дерево соединения — это просто список элементовFROM, так как они могут соединяться в любом порядке. Но с выражениямиJOIN, особенно с внешними соединениями, приходится соединять отношения именно в заданном порядке. В этом случае дерево соединения отражает структуру выраженийJOIN. Ограничения, связанные с конкретными предложениямиJOIN(из выраженийONилиUSING), тоже сохраняются в виде условных выражений, добавленных к соответствующим узлам дерева соединения. Как оказалось, выражениеWHEREверхнего уровня тоже удобно хранить как условие, добавленное к элементу верхнего уровня дерева соединения. Поэтому в дереве соединения на самом деле представляются оба предложения оператораSELECT—FROMиWHERE.- другие
Другие части дерева запроса, например, предложение
ORDER BY, в данном контексте не представляют интереса. Система правил выполняет в них некоторые подстановки, применяя правила, но это не имеет непосредственного отношения к основам системы правил.