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