59.1. Создание нестандартных путей сканирования
Провайдер нестандартного сканирования обычно добавляет пути для базового отношения, установив следующий обработчик, который вызывается после того, как ядро системы построит, по её мнению, полный и корректный набор путей доступа для отношения.
typedef void (*set_rel_pathlist_hook_type) (PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTblEntry *rte); extern PGDLLIMPORT set_rel_pathlist_hook_type set_rel_pathlist_hook;
Хотя эта функция-обработчик может изучать, изменять или удалять пути, сформированные основной системой, провайдер нестандартного сканирования обычно ограничивается созданием объектов CustomPath
и добавлением их в rel
(с помощью add_path
). Провайдер нестандартного сканирования отвечает за инициализацию объекта CustomPath
, который описан так:
typedef struct CustomPath { Path path; uint32 flags; List *custom_paths; List *custom_private; const CustomPathMethods *methods; } CustomPath;
Поле path
должно инициализироваться как для любого другого пути и включать оценку числа строк, стоимость запуска и общую, а также порядок сортировки, устанавливаемый этим путём. Поле flags
задаёт битовую маску, которая должна включать флаг CUSTOMPATH_SUPPORT_BACKWARD_SCAN
, если нестандартный путь поддерживает сканирование назад, и CUSTOMPATH_SUPPORT_MARK_RESTORE
, если он поддерживает пометку позиции и её восстановление. Обе эти возможности являются факультативными. В необязательном поле custom_paths
задаётся список узлов Path
, используемых данным узлом; они будут преобразованы планировщиком в узлы Plan
. В поле custom_private
могут быть сохранены внутренние данные нестандартного пути. Сохранять их нужно в форме, которую может принять nodeToString
, чтобы отладочные процедуры, пытающиеся вывести нестандартный путь, работали ожидаемым образом. Поле methods
должно указывать на объект (обычно статически размещённый), реализующий требуемые методы нестандартного пути (на данный момент это один метод). В этом объекте также должны быть инициализированы поля LibraryName
и SymbolName
, чтобы динамический загрузчик мог разрешить их и загрузить таблицу методов.
Провайдер нестандартного сканирования может также реализовать пути соединений. Как и для базовых отношений, такой путь должен выдавать тот же результат, какой был бы получен обычным соединением, которое он заменяет. Для этого провайдер соединения должен установить следующий обработчик, а затем внутри функции-обработчика создать пути CustomPath
для отношения соединения.
typedef void (*set_join_pathlist_hook_type) (PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra); extern PGDLLIMPORT set_join_pathlist_hook_type set_join_pathlist_hook;
Этот обработчик будет вызываться многократно для одного отношения соединения с разными сочетаниями внутренних и внешних отношений; задача обработчика — минимизировать при этом дублирующиеся операции.
59.1.1. Обработчики пути нестандартного сканирования
Plan *(*PlanCustomPath) (PlannerInfo *root, RelOptInfo *rel, CustomPath *best_path, List *tlist, List *clauses, List *custom_plans);
Преобразует нестандартный путь в законченный план. Возвращаемым значением обычно будет объект CustomScan
, который этот обработчик должен разместить в памяти и инициализировать. За подробностями обратитесь к Разделу 59.2.