58.2. Создание пользовательских планов сканирования#
58.2. Создание пользовательских планов сканирования #
Пользовательское сканирование представлено в готовом дереве плана с использованием следующей структуры:
typedef struct CustomScan { Scan scan; uint32 flags; List *custom_plans; List *custom_exprs; List *custom_private; List *custom_scan_tlist; Bitmapset *custom_relids; const CustomScanMethods *methods; } CustomScan;
scan
должен быть инициализирован так же, как и любой другой скан, включая
оценочные затраты, целевые списки, квалификации и так далее.
flags
- это битовая маска с тем же значением, что и в
CustomPath
.
custom_plans
может использоваться для хранения дочерних
узлов Plan
.
custom_exprs
должен использоваться для
хранения деревьев выражений, которые должны быть исправлены
setrefs.c
и subselect.c
, в то время как
custom_private
должен использоваться для хранения других частных данных,
которые используются только самим поставщиком пользовательского сканирования.
custom_scan_tlist
может быть NIL при сканировании базового
отношения, что указывает на то, что пользовательское сканирование возвращает кортежи сканирования, которые соответствуют
типу строк базового отношения. В противном случае это целевой список, описывающий
фактические кортежи сканирования. custom_scan_tlist
должен быть
предоставлен для соединений и может быть предоставлен для сканирования, если пользовательское сканирование
поставщик может вычислить некоторые выражения, не являющиеся Var.
custom_relids
устанавливается основным кодом в набор
отношений (индексы таблицы диапазона), которые обрабатывает этот узел сканирования; за исключением случая,
когда этот скан заменяет соединение, у него будет только один элемент.
methods
должен указывать на (обычно статически выделенный)
объект, реализующий требуемые методы пользовательского сканирования, которые далее
подробно описаны ниже.
Когда CustomScan
сканирует одну таблицу,
scan.scanrelid
должен быть индексом диапазона таблицы,
которую нужно просканировать. Когда он заменяет соединение, scan.scanrelid
должен быть равен нулю.
Деревья планов должны иметь возможность быть дублированными с помощью функции copyObject
, поэтому все данные, хранящиеся в полях “custom”, должны состоять из узлов, которые эта функция может обрабатывать. Кроме того, провайдеры пользовательских сканирований не могут заменить более крупную структуру, которая включает в себя CustomScan
, самой структурой, как это возможно для CustomPath
или CustomScanState
.
58.2.1. Пользовательские обратные вызовы плана сканирования #
Node *(*CreateCustomScanState) (CustomScan *cscan);
Выделите память для структуры CustomScanState
для этого CustomScan
. Фактическое выделение памяти часто будет больше, чем требуется для обычной структуры CustomScanState
, поскольку многие поставщики захотят встроить ее в качестве первого поля более крупной структуры. Возвращаемое значение должно иметь соответствующий тег узла и methods
, но другие поля должны оставаться нулевыми на этом этапе; после базовой инициализации, выполненной в функции ExecInitCustomScan
, будет вызван обратный вызов BeginCustomScan
, чтобы дать пользовательскому поставщику сканирования возможность выполнить все остальное, что требуется.