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