Перейти к основному содержимому

Выполнение пользовательского сканирования

Когда выполняется CustomScan, состояние его выполнения представлено CustomScanState, который объявляется следующим образом:

typedef struct CustomScanState
{
ScanState ss;
uint32 flags;
const CustomExecMethods *methods;
} CustomScanState;

ss инициализируется так же, как и любое другое состояние сканирования, за исключением того, что если сканирование выполняется для join, а не для базового отношения, ss.ss_currentRelation оставляется NULL. flags - битовая маска с тем же значением, что и в CustomPath и CustomScan. methods должны указывать на (обычно статически выделенный) объект, реализующий необходимые методы пользовательского состояния сканирования, которые более подробно описаны ниже. Как правило, CustomScanState, который не обязательно должен поддерживать copyObject, на самом деле является более крупной структурой, содержащей вышеуказанные методы в качестве первого члена.

Обработчики выполнения пользовательского сканирования

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, такие как список целей и отношение сканирования, будут показаны и без этого вызова, но этот вызов позволяет отобразить дополнительное, частное состояние.