59.2. Создание пользовательских планов сканирования#

59.2. Создание пользовательских планов сканирования

59.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.

59.2.1. Пользовательские обратные вызовы плана сканирования

Node *(*CreateCustomScanState) (CustomScan *cscan);

Выделите память для структуры CustomScanState для этого CustomScan. Фактическое выделение памяти часто будет больше, чем требуется для обычной структуры CustomScanState, поскольку многие поставщики захотят встроить ее в качестве первого поля более крупной структуры. Возвращаемое значение должно иметь соответствующий тег узла и methods, но другие поля должны оставаться нулевыми на этом этапе; после базовой инициализации, выполненной в функции ExecInitCustomScan, будет вызван обратный вызов BeginCustomScan, чтобы дать пользовательскому поставщику сканирования возможность выполнить все остальное, что требуется.