58.3. Выполнение нестандартного сканирования #
Когда выполняется узел CustomScan
, его состояние представляется структурой CustomScanState
, объявленной следующим образом:
typedef struct CustomScanState { ScanState ss; uint32 flags; const CustomExecMethods *methods; } CustomScanState;
Поле ss
инициализируется как и для состояния любого другого сканирования, за исключением того, что когда это сканирование для соединения, а не для базового отношения, в ss.ss_currentRelation
остаётся NULL. Поле flags
содержит битовую маску с тем же значением, что и в CustomPath
и CustomScan
. Поле methods
должно указывать на объект (обычно статически размещённый), реализующий требуемые методы состояния нестандартного сканирования, подробнее описанные ниже. Обычно структура CustomScanState
, которой не нужно поддерживать copyObject
, фактически включается в расширенную структуру в качестве её первого члена.
58.3.1. Обработчики выполнения нестандартного сканирования #
void (*BeginCustomScan) (CustomScanState *node, EState *estate, int eflags);
Завершает инициализацию переданного объекта CustomScanState
. Стандартные поля инициализируются в ExecInitCustomScan
, но все внутренние поля должны инициализироваться здесь.
TupleTableSlot *(*ExecCustomScan) (CustomScanState *node);
Считывает следующий кортеж. В случае наличия кортежей эта функция должна записать в ps_ResultTupleSlot
следующий кортеж в текущем направлении сканирования и вернуть слот с кортежем. Если же кортежей больше нет, она должна вернуть NULL
или пустой слот.
void (*EndCustomScan) (CustomScanState *node);
Очищает все внутренние данные, связанные с CustomScanState
. Этот метод является обязательным, но он может ничего не делать, если такие данные отсутствуют или они будут очищены автоматически.
void (*ReScanCustomScan) (CustomScanState *node);
Возвращает позицию текущего сканирования в начало и подготавливает повторное сканирование отношения.
void (*MarkPosCustomScan) (CustomScanState *node);
Сохраняет текущую позицию сканирования, чтобы к ней впоследствии можно было вернуться, вызвав обработчик RestrPosCustomScan
. Данный обработчик является необязательным и должен присутствовать, только если установлен флаг CUSTOMPATH_SUPPORT_MARK_RESTORE
.
void (*RestrPosCustomScan) (CustomScanState *node);
Восстанавливает предыдущую позицию сканирования, сохранённую обработчиком MarkPosCustomScan
. Данный обработчик является необязательным и должен присутствовать, только если установлен флаг CUSTOMPATH_SUPPORT_MARK_RESTORE
.
Size (*EstimateDSMCustomScan) (CustomScanState *node, ParallelContext *pcxt);
Оценивает объём динамической разделяемой памяти, которая потребуется для параллельной операции. Это значение может превышать объём, который будет занят фактически, но не должно быть меньше. Возвращаемое значение задаётся в байтах. Этот обработчик не является обязательным и должен устанавливаться, только если провайдер нестандартного сканирования поддерживает параллельное выполнение.
void (*InitializeDSMCustomScan) (CustomScanState *node, ParallelContext *pcxt, void *coordinate);
Инициализирует динамическую разделяемую память, которая потребуется для параллельной операции; coordinate
указывает на область разделяемой памяти размера, равного возвращаемому значению EstimateDSMCustomScan
. Этот обработчик является необязательным и должен устанавливаться, только если провайдер нестандартного сканирования поддерживает параллельное выполнение.
void (*ReInitializeDSMCustomScan) (CustomScanState *node, ParallelContext *pcxt, void *coordinate);
Заново инициализирует динамическую разделяемую память, требуемую для параллельной операции, перед тем как будет повторно просканирован узел нестандартного сканирования. Этот обработчик является необязательным и должен устанавливаться, только если провайдер нестандартного сканирования поддерживает параллельное выполнение. В этом обработчике рекомендуется сбрасывать только общее состояние, а в обработчике ReScanCustomScan
сбрасывать только локальное. В настоящее время этот обработчик будет вызываться перед ReScanCustomScan
, но лучше на этот порядок не рассчитывать.
void (*InitializeWorkerCustomScan) (CustomScanState *node, shm_toc *toc, void *coordinate);
Инициализирует локальное состояние параллельного исполнителя на основе общего состояния, заданного ведущим исполнителем во время InitializeDSMCustomScan
. Этот обработчик является необязательным и должен устанавливаться, только если провайдер нестандартного сканирования поддерживает параллельное выполнение.
void (*ShutdownCustomScan) (CustomScanState *node);
Освобождает ресурсы, когда становится понятно, что этот узел больше не будет выполняться. Этот обработчик вызывается не во всех случаях; иногда может вызываться только EndCustomScan
. Так как сегмент DSM, используемый параллельным запросом, освобождается сразу после вызова этого обработчика, провайдеры нестандартного сканирования, которым нужно выполнять некоторые действия до ликвидации сегмента DSM, должны реализовывать этот метод.
void (*ExplainCustomScan) (CustomScanState *node, List *ancestors, ExplainState *es);
Выводит дополнительную информацию для EXPLAIN
об узле нестандартного сканирования. Этот обработчик является необязательным. Общие данные, сохранённые в ScanState
, такие как целевой список и сканируемое отношение, будут выводиться и без этого обработчика, но с помощью этого обработчика можно выдать дополнительные, внутренние сведения.