56.2. Функции обратного вызова обертки внешних данных#
56.2. Функции обратного вызова обертки внешних данных #
- 56.2.1. FDW процедуры для Сканирования Внешних Таблиц
- 56.2.2. FDW процедуры для Сканирования Внешних Соединений
- 56.2.3. FDW процедуры для планирования пост-сканирования/соединения обработки
- 56.2.4. FDW процедуры для обновления внешних таблиц
- 56.2.5. FDW процедуры для
TRUNCATE
- 56.2.6. FDW процедуры для блокировки строк
- 56.2.7. FDW процедуры для
EXPLAIN
- 56.2.8. FDW процедуры для
ANALYZE
- 56.2.9. FDW процедуры для
IMPORT FOREIGN SCHEMA
- 56.2.10. FDW процедуры для Параллельного Выполнения
- 56.2.11. FDW процедуры для асинхронного выполнения
- 56.2.12. FDW процедуры для перепараметризации путей
Функция обработчика FDW возвращает структуру FdwRoutine
, выделенную с помощью palloc, содержащую указатели на описанные ниже функции обратного вызова. Функции, связанные со сканированием, являются обязательными, остальные - необязательными.
Структурный тип FdwRoutine
объявлен в файле src/include/foreign/fdwapi.h
, см. его для получения дополнительной информации.
56.2.1. FDW процедуры для Сканирования Внешних Таблиц #
void GetForeignRelSize(PlannerInfo *root, RelOptInfo *baserel, Oid foreigntableid);
Получить оценки размера отношения для внешней таблицы. Это вызывается в начале планирования запроса, который сканирует внешнюю таблицу. root
- это глобальная информация планировщика о запросе; baserel
- информация планировщика об этой таблице; а foreigntableid
- это OID внешней таблицы pg_class
. (foreigntableid
можно получить из структур данных планировщика, но он передается явно для экономии усилий).
Эта функция должна обновить baserel->rows
до ожидаемого количества строк, возвращаемых сканированием таблицы, после учета фильтрации, выполненной ограничениями. Начальное значение baserel->rows
является только постоянной оценкой по умолчанию, которую следует заменить, если это возможно. Функция также может выбрать обновление baserel->width
, если она может вычислить более точную оценку средней ширины результирующей строки.
(Начальное значение основано на типах данных столбцов и на средних значениях ширины столбцов, измеренных последней командой ANALYZE
).
Кроме того, эта функция может обновить baserel->tuples
, если она может вычислить более точную оценку общего количества строк во внешней таблице.
(Начальное значение берется из pg_class
.reltuples
, которое представляет общее количество строк, увиденных последней командой ANALYZE
; оно будет равно -1
, если на этой внешней таблице не выполнялась команда ANALYZE
).
См. Раздел 56.4 для получения дополнительной информации.
void GetForeignPaths(PlannerInfo *root, RelOptInfo *baserel, Oid foreigntableid);
Создает возможные пути доступа для сканирования внешней таблицы.
Это вызывается во время планирования запроса.
Параметры такие же, как и для функции GetForeignRelSize
,
которая уже была вызвана.
Эта функция должна генерировать как минимум один путь доступа
(узел ForeignPath
) для сканирования внешней таблицы и
должна вызывать add_path
для добавления каждого такого пути в
baserel->pathlist
. Рекомендуется использовать
create_foreignscan_path
для создания узлов
ForeignPath
. Функция может генерировать несколько
путей доступа, например, путь, который имеет допустимые pathkeys
для
представления предварительно отсортированного результата. Каждый путь доступа должен содержать оценки стоимости,
и может содержать любую приватную информацию FDW, которая необходима для
идентификации конкретного метода сканирования.
См. Раздел 56.4 для получения дополнительной информации.
ForeignScan * GetForeignPlan(PlannerInfo *root, RelOptInfo *baserel, Oid foreigntableid, ForeignPath *best_path, List *tlist, List *scan_clauses, Plan *outer_plan);
Создает узел плана ForeignScan
из выбранного внешнего пути доступа. Это вызывается в конце планирования запроса. Параметры такие же, как для GetForeignRelSize
, плюс выбранный ForeignPath
(ранее созданный с помощью GetForeignPaths
, GetForeignJoinPaths
или GetForeignUpperPaths
), список целей, которые должны быть выведены узлом плана, ограничивающие предложения, которые должны быть применены узлом плана, и внешний подплан ForeignScan
, который используется для повторных проверок, выполняемых RecheckForeignScan
. (Если путь относится к соединению, а не к базовому отношению, foreigntableid
равен InvalidOid
).
Эта функция должна создавать и возвращать узел плана ForeignScan
; рекомендуется использовать функцию make_foreignscan
для построения узла ForeignScan
.
См. Раздел 56.4 для получения дополнительной информации.
void BeginForeignScan(ForeignScanState *node, int eflags);
Начало выполнения внешнего сканирования. Это вызывается при запуске исполнителя.
Оно должно выполнять любую необходимую инициализацию перед началом сканирования,
но не начинать выполнение фактического сканирования (это должно быть сделано при
первом вызове функции IterateForeignScan
).
Узел ForeignScanState
уже был создан, но
его поле fdw_state
все еще равно NULL. Информация о
таблице для сканирования доступна через
узел ForeignScanState
(в частности, из основного
узла плана ForeignScan
, который содержит любую
частную информацию FDW, предоставленную функцией GetForeignPlan
).
eflags
содержит флаги, описывающие режим работы исполнителя
для данного узла плана.
Обратите внимание, что когда (eflags & EXEC_FLAG_EXPLAIN_ONLY)
истинно, эта функция не должна выполнять никаких внешне видимых действий; она должна только выполнить минимально необходимые действия, чтобы сделать состояние узла допустимым для ExplainForeignScan
и EndForeignScan
.
TupleTableSlot * IterateForeignScan(ForeignScanState *node);
Извлеките одну строку из внешнего источника и верните ее в слот таблицы кортежей (для этой цели следует использовать ScanTupleSlot
узла). Верните NULL, если больше нет строк. Инфраструктура слота таблицы кортежей позволяет возвращать как физический, так и виртуальный кортеж; в большинстве случаев предпочтительнее второй вариант с точки зрения производительности. Обратите внимание, что это вызывается в контексте памяти с коротким сроком жизни, который будет сброшен между вызовами. Создайте контекст памяти в BeginForeignScan
, если вам нужно хранение с более длительным сроком жизни, или используйте es_query_cxt
узла EState
.
Строки, возвращаемые, должны соответствовать целевому списку fdw_scan_tlist
, если он был предоставлен, в противном случае они должны соответствовать типу строки сканируемой внешней таблицы. Если вы решите оптимизировать извлечение столбцов, которые не нужны, вы должны вставить значения NULL в эти позиции столбцов или сгенерировать список fdw_scan_tlist
с не указанными этими столбцами.
Обратите внимание, что исполнитель Tantor BE не обращает внимания на то, нарушают ли возвращаемые строки какие-либо ограничения, определенные для внешней таблицы - но планировщик обращает внимание и может неправильно оптимизировать запросы, если во внешней таблице видны строки, которые не удовлетворяют объявленному ограничению. Если ограничение нарушается, когда пользователь заявил, что ограничение должно быть true, может быть целесообразно вызвать ошибку (как и в случае несоответствия типов данных).
void ReScanForeignScan(ForeignScanState *node);
Перезапустите сканирование с самого начала. Обратите внимание, что значения любых параметров, от которых зависит сканирование, могут измениться, поэтому новое сканирование не обязательно вернет точно те же строки.
void EndForeignScan(ForeignScanState *node);
Завершите сканирование и освободите ресурсы. Обычно не важно освобождать память, выделенную с помощью palloc, но, например, открытые файлы и соединения с удаленными серверами следует очистить.
56.2.2. FDW процедуры для Сканирования Внешних Соединений #
Если FDW поддерживает выполнение удаленного соединения (вместо извлечения данных обоих таблиц и выполнения соединения локально), он должен предоставить эту функцию обратного вызова:
void GetForeignJoinPaths(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra);
Создайте возможные пути доступа для соединения двух (или более) внешних таблиц, которые все принадлежат одному внешнему серверу. Эта необязательная функция вызывается во время планирования запроса. Как и GetForeignPaths
, эта функция должна генерировать путь(и) ForeignPath
для предоставленного joinrel
(используйте create_foreign_join_path
для их построения) и вызывать add_path
для добавления этих путей в набор путей, рассматриваемых для соединения. Но в отличие от GetForeignPaths
, не обязательно, чтобы эта функция успешно создала хотя бы один путь, так как всегда возможны пути, включающие локальное соединение.
Обратите внимание, что эта функция будет вызываться несколько раз для одного и того же соединения с различными комбинациями внутренних и внешних отношений; ответственность за минимизацию дублированной работы лежит на FDW.
Если для соединения выбран путь ForeignPath
, он будет представлять весь процесс соединения; пути, генерируемые для компонентных таблиц и вспомогательных соединений, не будут использоваться. Дальнейшая обработка пути соединения происходит примерно так же, как и для пути, сканирующего отдельную внешнюю таблицу. Одно отличие заключается в том, что поле scanrelid
результирующего узла плана ForeignScan
должно быть установлено в ноль, поскольку оно не представляет отдельное отношение; вместо этого поле fs_relids
узла ForeignScan
представляет набор соединенных отношений. (Последнее поле устанавливается автоматически кодом основного планировщика и не требует заполнения FDW.) Другое отличие заключается в том, что, поскольку список столбцов для удаленного соединения не может быть найден в системных каталогах, FDW должен заполнить поле fdw_scan_tlist
соответствующим списком узлов TargetEntry
, представляющих набор столбцов, которые он будет предоставлять во время выполнения возвращаемых им кортежей.
Примечание
Начиная с Tantor BE 16,
fs_relids
включает индексы таблицы диапазонов
внешних соединений, если они были задействованы в этом соединении. Новое поле
fs_base_relids
включает только индексы базовых
отношений, и таким образом
имитирует старую семантику fs_relids
.
См. Раздел 56.4 для получения дополнительной информации.
56.2.3. FDW процедуры для планирования пост-сканирования/соединения обработки #
Если FDW поддерживает выполнение удаленной обработки после сканирования/соединения, такую как удаленная агрегация, он должен предоставить эту функцию обратного вызова:
void GetForeignUpperPaths(PlannerInfo *root, UpperRelationKind stage, RelOptInfo *input_rel, RelOptInfo *output_rel, void *extra);
Создайте возможные пути доступа для обработки верхнего отношения, что является термином планировщика для всех операций обработки запроса после сканирования/соединения, таких как агрегация, оконные функции, сортировка и обновление таблицы. Эта необязательная функция вызывается во время планирования запроса. В настоящее время она вызывается только в том случае, если все базовые отношения, участвующие в запросе, принадлежат одному внешнему источнику данных (FDW). Эта функция должна генерировать пути ForeignPath
для любой операции обработки после сканирования/соединения, которую FDW может выполнить удаленно (используйте create_foreign_upper_path
для их создания) и вызывать add_path
для добавления этих путей в указанное верхнее отношение. Как и в случае с GetForeignJoinPaths
, не обязательно, чтобы эта функция успешно создала какие-либо пути, так как всегда возможны пути с локальной обработкой.
Параметр stage
определяет, какой шаг после сканирования/соединения в данный момент рассматривается. output_rel
- это верхнее отношение, которое должно получить пути, представляющие вычисление этого шага, а input_rel
- это отношение, представляющее входные данные для этого шага. Параметр extra
предоставляет дополнительные детали, в настоящее время он устанавливается только для UPPERREL_PARTIAL_GROUP_AGG
или UPPERREL_GROUP_AGG
, в этом случае он указывает на структуру GroupPathExtraData
; или для UPPERREL_FINAL
, в этом случае он указывает на структуру FinalPathExtraData
. (Обратите внимание, что пути ForeignPath
, добавленные в output_rel
, обычно не имеют прямой зависимости от путей input_rel
, поскольку их обработка ожидается внешней. Однако, изучение ранее сгенерированных путей для предыдущего шага обработки может быть полезным для избежания избыточной работы по планированию).
См. Раздел 56.4 для получения дополнительной информации.
56.2.4. FDW процедуры для обновления внешних таблиц #
Если FDW поддерживает записываемые внешние таблицы, он должен предоставить некоторые или все из следующих функций обратного вызова в зависимости от потребностей и возможностей FDW:
void AddForeignUpdateTargets(PlannerInfo *root, Index rtindex, RangeTblEntry *target_rte, Relation target_relation);
UPDATE
и DELETE
операции выполняются
против строк, ранее выбранных функциями сканирования таблицы. Внешний
поставщик данных может потребовать дополнительной информации, такой как идентификатор строки или значения
первичных ключей, чтобы убедиться, что он может идентифицировать точную строку для
обновления или удаления. Для поддержки этого, эта функция может добавить дополнительные скрытые,
или “мусорные”, целевые столбцы в список столбцов, которые должны быть
извлечены из внешней таблицы во время UPDATE
или
DELETE
.
Для этого создайте Var
, представляющий
дополнительное значение, которое вам нужно, и передайте его
в add_row_identity_var
, вместе с именем для
мусорного столбца. (Вы можете сделать это несколько раз, если требуется несколько столбцов). Вы должны выбрать отдельное имя мусорного столбца для каждого
различного Var
, которое вам нужно, за исключением
того, что Var
, идентичные за исключением
поля varno
, могут и должны использовать
одно и то же имя столбца.
Ядро системы использует имена мусорных столбцов
tableoid
для
столбца tableoid
таблицы,
ctid
или ctid
для N
ctid
,
wholerow
для целой строки Var
, помеченной
vartype
= RECORD
,
и wholerow
для целой строки N
Var
с
vartype
, равным объявленному типу строки таблицы.
Используйте эти имена, когда это возможно (планировщик объединит дублирующиеся
запросы на идентичные мусорные столбцы). Если вам нужен другой вид
мусорного столбца помимо этих, мудро будет выбрать имя с префиксом
вашего расширения, чтобы избежать конфликтов с другими FDW.
Если указатель AddForeignUpdateTargets
установлен в
NULL
, дополнительные выражения целей не добавляются.
(Это сделает невозможным реализацию операций DELETE
,
хотя UPDATE
все еще может быть выполнимым, если FDW
полагается на неизменный первичный ключ для идентификации строк).
List * PlanForeignModify(PlannerInfo *root, ModifyTable *plan, Index resultRelation, int subplan_index);
Выполните все необходимые дополнительные действия планирования для вставки, обновления или удаления во внешней таблице. Эта функция генерирует приватную информацию FDW, которая будет прикреплена к узлу плана ModifyTable
, выполняющему действие обновления. Эта приватная информация должна иметь форму List
и будет передана в BeginForeignModify
на этапе выполнения.
root
- это глобальная информация планировщика о запросе.
plan
- это узел плана ModifyTable
, который
полностью готов, за исключением поля fdwPrivLists
.
resultRelation
идентифицирует целевую внешнюю таблицу по ее
индексу в таблице диапазона. subplan_index
указывает, какая цель
узла плана ModifyTable
это, считая с нуля;
используйте это, если нужно индексировать в подструктуры отношений для каждой цели
узла plan
.
См. Раздел 56.4 для получения дополнительной информации.
Если указатель PlanForeignModify
установлен в
NULL
, дополнительные действия на этапе планирования не выполняются, и
список fdw_private
, переданный в
BeginForeignModify
, будет равен NIL.
void BeginForeignModify(ModifyTableState *mtstate, ResultRelInfo *rinfo, List *fdw_private, int subplan_index, int eflags);
Начало выполнения операции модификации внешней таблицы. Эта процедура вызывается при запуске исполнителя. Она должна выполнить любую необходимую инициализацию перед фактическими модификациями таблицы. В дальнейшем будут вызваны функции ExecForeignInsert/ExecForeignBatchInsert
, ExecForeignUpdate
или ExecForeignDelete
для вставки, обновления или удаления кортежей.
mtstate
- это общее состояние узла плана ModifyTable
, который выполняется; глобальные данные о плане и состоянии выполнения доступны через эту структуру.
rinfo
- это структура ResultRelInfo
, описывающая целевую внешнюю таблицу. (Поле ri_FdwState
структуры ResultRelInfo
доступно для хранения любого частного состояния FDW, необходимого для этой операции).
fdw_private
содержит приватные данные, сгенерированные PlanForeignModify
, если они есть.
subplan_index
определяет, какая цель узла плана ModifyTable
это.
eflags
содержит флаги, описывающие режим работы исполнителя для этого узла плана.
Обратите внимание, что когда (eflags & EXEC_FLAG_EXPLAIN_ONLY)
истинно, эта функция не должна выполнять никаких внешне видимых действий; она должна только выполнить минимально необходимые действия, чтобы сделать состояние узла допустимым для ExplainForeignModify
и EndForeignModify
.
Если указатель BeginForeignModify
установлен в
NULL
, при запуске исполнителя никаких действий не выполняется.
TupleTableSlot * ExecForeignInsert(EState *estate, ResultRelInfo *rinfo, TupleTableSlot *slot, TupleTableSlot *planSlot);
Вставьте одну кортеж во внешнюю таблицу.
estate
- это глобальное состояние выполнения запроса.
rinfo
- это структура ResultRelInfo
, описывающая
целевую внешнюю таблицу.
slot
содержит кортеж, который будет вставлен; он должен соответствовать
определению типа строки внешней таблицы.
planSlot
содержит кортеж, который был сгенерирован
подпланом узла плана ModifyTable
; он отличается от
slot
возможным наличием дополнительных “мусорных”
столбцов. (Обычно planSlot
мало интересен
для случаев с INSERT
, но предоставляется для полноты).
Возвращаемое значение - это либо слот, содержащий фактически вставленные данные (это может отличаться от предоставленных данных, например, из-за действий триггеров), либо NULL, если ни одна строка фактически не была вставлена (опять же, обычно из-за триггеров). Переданный слот slot
может быть повторно использован для этой цели.
Данные в возвращаемом слоте используются только в том случае, если оператор INSERT
включает предложение RETURNING
или связан с представлением
WITH CHECK OPTION
; или если внешняя таблица имеет
триггер AFTER ROW
. Триггеры требуют все столбцы,
но FDW может выбрать оптимизацию и вернуть некоторые или все столбцы
в зависимости от содержимого предложения RETURNING
или
ограничений WITH CHECK OPTION
. В любом случае, должен быть
возвращен хотя бы один слот, чтобы указать успешность операции, иначе
количество строк, возвращаемых запросом, будет неверным.
Если указатель ExecForeignInsert
установлен в
NULL
, попытки вставки во внешнюю таблицу завершатся
с ошибкой и будет выведено сообщение об ошибке.
Обратите внимание, что эта функция также вызывается при вставке маршрутизированных кортежей в секцию внешней таблицы или выполнении COPY FROM
на внешней таблице, в котором случае она вызывается по-другому, чем в случае INSERT
. См. описанные ниже обратные вызовы, которые позволяют FDW поддерживать это.
TupleTableSlot ** ExecForeignBatchInsert(EState *estate, ResultRelInfo *rinfo, TupleTableSlot **slots, TupleTableSlot **planSlots, int *numSlots);
Вставьте несколько кортежей массово во внешнюю таблицу.
Параметры для ExecForeignInsert
такие же,
за исключением того, что slots
и planSlots
содержат
несколько кортежей, а *numSlots
указывает количество
кортежей в этих массивах.
Возвращаемое значение представляет собой массив слотов, содержащих данные, которые были фактически вставлены (это может отличаться от предоставленных данных, например, в результате действий триггера).
Переданные слоты slots
могут быть использованы повторно для этой цели.
Количество успешно вставленных кортежей возвращается в *numSlots
.
Данные в возвращаемом слоте используются только в том случае, если оператор INSERT
включает представление WITH CHECK OPTION
; или если у внешней таблицы есть триггер AFTER ROW
. Триггеры требуют все столбцы, но FDW может выбрать оптимизацию и не возвращать некоторые или все столбцы в зависимости от содержимого ограничений WITH CHECK OPTION
.
Если указатель ExecForeignBatchInsert
или
GetForeignModifyBatchSize
установлен в
NULL
, попытки вставки во внешнюю таблицу будут
использовать функцию ExecForeignInsert
.
Эта функция не используется, если у INSERT
есть
фраза RETURNING
.
Обратите внимание, что эта функция также вызывается при вставке маршрутизированных кортежей в секцию внешней таблицы или выполнении COPY FROM
на внешней таблице, в котором случае она вызывается по-другому, чем в случае INSERT
. См. описанные ниже обратные вызовы, которые позволяют FDW поддерживать это.
int GetForeignModifyBatchSize(ResultRelInfo *rinfo);
Сообщите максимальное количество кортежей, которое может обработать один вызов ExecForeignBatchInsert
для указанной внешней таблицы. Исполнитель передает в ExecForeignBatchInsert
не более указанного количества кортежей. rinfo
- это структура ResultRelInfo
, описывающая целевую внешнюю таблицу. Ожидается, что FDW предоставит пользователю внешний сервер и/или опцию внешней таблицы для установки этого значения или некоторого жестко закодированного значения.
Если указатель ExecForeignBatchInsert
или
GetForeignModifyBatchSize
установлен в
NULL
, попытки вставки во внешнюю таблицу будут
использовать ExecForeignInsert
.
TupleTableSlot * ExecForeignUpdate(EState *estate, ResultRelInfo *rinfo, TupleTableSlot *slot, TupleTableSlot *planSlot);
Обновите одну кортеж во внешней таблице.
estate
- это глобальное состояние выполнения запроса.
rinfo
- это структура ResultRelInfo
, описывающая
целевую внешнюю таблицу.
slot
содержит новые данные для кортежа; они должны соответствовать
определению типа строки внешней таблицы.
planSlot
содержит кортеж, генерируемый
подзапросом узла плана ModifyTable
. В отличие от
slot
, этот кортеж содержит только новые значения для
столбцов, измененных запросом, поэтому не полагайтесь на номера атрибутов внешней таблицы для индексации в planSlot
.
Кроме того, planSlot
обычно содержит
дополнительные “мусорные” столбцы. В частности, все мусорные столбцы,
которые были запрошены с помощью AddForeignUpdateTargets
,
будут доступны из этого слота.
Возвращаемое значение - это либо слот, содержащий строку, как она была фактически обновлена (это может отличаться от предоставленных данных, например, из-за действий триггеров), либо NULL, если строка фактически не была обновлена (опять же, обычно из-за триггеров). Переданный слот slot
может быть повторно использован для этой цели.
Данные в возвращаемом слоте используются только в том случае, если оператор UPDATE
включает предложение RETURNING
или связан с представлением
WITH CHECK OPTION
; или если внешняя таблица имеет
триггер AFTER ROW
. Триггеры требуют все столбцы,
но FDW может выбрать оптимизацию и вернуть некоторые или все столбцы
в зависимости от содержимого предложения RETURNING
или
ограничений WITH CHECK OPTION
. В любом случае, должен быть
возвращен хотя бы один слот, чтобы указать успешность операции, иначе
количество строк, возвращаемых запросом, будет неверным.
Если указатель ExecForeignUpdate
установлен в
NULL
, попытки обновления внешней таблицы завершатся
с ошибкой и будет выведено сообщение об ошибке.
TupleTableSlot * ExecForeignDelete(EState *estate, ResultRelInfo *rinfo, TupleTableSlot *slot, TupleTableSlot *planSlot);
Удалить одну кортеж из внешней таблицы.
estate
- это глобальное состояние выполнения запроса.
rinfo
- это структура ResultRelInfo
, описывающая
целевую внешнюю таблицу.
slot
не содержит ничего полезного при вызове, но может быть использован для
хранения возвращенного кортежа.
planSlot
содержит кортеж, генерируемый подпланом узла плана
ModifyTable
; в частности, он будет
содержать любые ненужные столбцы, запрошенные с помощью
AddForeignUpdateTargets
. Ненужный столбец (-ы) должен быть использован
для идентификации удаляемого кортежа.
Возвращаемое значение - это либо слот, содержащий удаленную строку, либо NULL, если ни одна строка не была удалена (обычно в результате триггеров). Переданный slot
может быть использован для хранения возвращаемой кортежа.
Данные в возвращаемом слоте используются только в том случае, если запрос DELETE
включает предложение RETURNING
или у внешней таблицы есть
триггер AFTER ROW
. Триггеры требуют все столбцы, но
FDW может выбрать оптимизацию и вернуть только некоторые или все столбцы,
в зависимости от содержимого предложения RETURNING
. В любом случае,
необходимо вернуть какой-либо слот, чтобы указать успешность выполнения запроса,
иначе количество возвращенных строк будет неверным.
Если указатель ExecForeignDelete
установлен в
NULL
, попытки удаления из внешней таблицы завершатся
с ошибкой и будет выведено сообщение об ошибке.
void EndForeignModify(EState *estate, ResultRelInfo *rinfo);
Завершите обновление таблицы и освободите ресурсы. Обычно не важно освобождать память, выделенную с помощью palloc, но, например, открытые файлы и соединения с удаленными серверами следует очистить.
Если указатель EndForeignModify
установлен в
NULL
, при завершении работы исполнителя никаких действий не выполняется.
Кортежи, вставленные в секционированную таблицу с помощью команды INSERT
или
COPY FROM
, направляются в соответствующие секции. Если FDW
поддерживает направляемые секции внешней таблицы, он также должен предоставить
следующие функции обратного вызова. Эти функции также вызываются при выполнении
команды COPY FROM
на внешней таблице.
void BeginForeignInsert(ModifyTableState *mtstate, ResultRelInfo *rinfo);
Начало выполнения операции вставки во внешнюю таблицу. Эта процедура вызывается непосредственно перед вставкой первой кортежа во внешнюю таблицу в обоих случаях: когда она является выбранной для маршрутизации кортежей и когда она является целью, указанной в команде COPY FROM
. Она должна выполнить любую необходимую инициализацию перед фактической вставкой. Затем для вставки кортежей во внешнюю таблицу будет вызвана функция ExecForeignInsert
или ExecForeignBatchInsert
.
mtstate
- это общее состояние узла плана ModifyTable
, который выполняется; глобальные данные о плане и состоянии выполнения доступны через эту структуру. rinfo
- это структура ResultRelInfo
, описывающая целевую внешнюю таблицу. (Поле ri_FdwState
структуры ResultRelInfo
доступно для хранения любого частного состояния, необходимого для этой операции, внешним модулем обработки данных (FDW).)
Когда это вызывается командой COPY FROM
, глобальные данные, связанные с планом, в mtstate
не предоставляются, и параметр planSlot
функции ExecForeignInsert
, вызываемой для каждой вставленной кортежа, равен NULL
, независимо от того, является ли внешняя таблица выбранной для маршрутизации кортежа или целевой таблицей, указанной в команде.
Если указатель BeginForeignInsert
установлен в
NULL
, то инициализация не выполняется.
Обратите внимание, что если FDW не поддерживает размещение внешних таблиц по маршруту
и/или выполнение COPY FROM
на внешних таблицах,
эта функция или ExecForeignInsert/ExecForeignBatchInsert
,
вызванная впоследствии, должна выбрасывать ошибку при необходимости.
void EndForeignInsert(EState *estate, ResultRelInfo *rinfo);
Завершите операцию вставки и освободите ресурсы. Обычно не важно освобождать память, выделенную с помощью palloc, но, например, открытые файлы и соединения с удаленными серверами следует очистить.
Если указатель EndForeignInsert
установлен в
NULL
, то никаких действий не выполняется при завершении.
int IsForeignRelUpdatable(Relation rel);
Отчет о том, какие операции обновления поддерживает указанная внешняя таблица.
Возвращаемое значение должно быть битовой маской номеров событий правил, указывающих
какие операции поддерживаются внешней таблицей, используя перечисление
CmdType
; то есть,
(1 << CMD_UPDATE) = 4
для UPDATE
,
(1 << CMD_INSERT) = 8
для INSERT
, и
(1 << CMD_DELETE) = 16
для DELETE
.
Если указатель IsForeignRelUpdatable
установлен в
NULL
, предполагается, что внешние таблицы могут быть вставлены, обновлены
или удалены, если FDW предоставляет функции ExecForeignInsert
,
ExecForeignUpdate
или ExecForeignDelete
соответственно. Эта функция необходима только в том случае, если FDW поддерживает
некоторые таблицы, которые можно обновлять, и некоторые, которые нельзя. (Даже в этом случае
допускается вызов ошибки в процедуре выполнения вместо проверки в этой функции.
Однако эта функция используется для определения возможности обновления для отображения в представлениях information_schema
).
Некоторые операции вставки, обновления и удаления во внешних таблицах могут быть оптимизированы путем реализации альтернативного набора интерфейсов. Обычные интерфейсы для вставки, обновления и удаления извлекают строки с удаленного сервера и затем изменяют эти строки по одной. В некоторых случаях такой подход построчной обработки необходим, но он может быть неэффективным. Если удаленному серверу возможно определить, какие строки следует изменить, не извлекая их фактически, и если нет локальных структур, которые бы повлияли на операцию (локальные триггеры на уровне строки, хранимые генерируемые столбцы или ограничения WITH CHECK OPTION
от родительских представлений), то можно организовать так, чтобы вся операция выполнялась на удаленном сервере. Описанные ниже интерфейсы делают это возможным.
bool PlanDirectModify(PlannerInfo *root, ModifyTable *plan, Index resultRelation, int subplan_index);
Решите, безопасно ли выполнять прямое изменение на удаленном сервере. Если да, то верните true
после выполнения необходимых планировочных действий. В противном случае верните false
. Эта необязательная функция вызывается во время планирования запроса. Если эта функция успешно выполняется, то на этапе выполнения будут вызваны функции BeginDirectModify
, IterateDirectModify
и EndDirectModify
. В противном случае изменение таблицы будет выполнено с использованием описанных выше функций обновления таблицы. Параметры такие же, как и для функции PlanForeignModify
.
Для выполнения прямого изменения на удаленном сервере эта функция должна переписать целевой подплан с узлом плана ForeignScan
, который выполняет прямое изменение на удаленном сервере. Поля operation
и resultRelation
в ForeignScan
должны быть установлены соответствующим образом. Поле operation
должно быть установлено на перечисление CmdType
, соответствующее виду оператора (то есть CMD_UPDATE
для UPDATE
, CMD_INSERT
для INSERT
и CMD_DELETE
для DELETE
), а аргумент resultRelation
должен быть скопирован в поле resultRelation
.
См. Раздел 56.4 для получения дополнительной информации.
Если указатель PlanDirectModify
установлен в
NULL
, то не предпринимаются попытки выполнить прямое изменение на
удаленном сервере.
void BeginDirectModify(ForeignScanState *node, int eflags);
Подготовка к выполнению прямого изменения на удаленном сервере.
Это вызывается во время запуска исполнителя. Он должен выполнить любую
инициализацию, необходимую перед прямым изменением (которое должно быть
выполнено при первом вызове функции IterateDirectModify
).
Узел ForeignScanState
уже был создан, но
его поле fdw_state
все еще равно NULL. Информация о
таблице для изменения доступна через
узел ForeignScanState
(в частности, из основного
узла плана ForeignScan
, который содержит любую частную
информацию FDW, предоставленную функцией PlanDirectModify
).
eflags
содержит флаги, описывающие режим работы исполнителя
для этого узла плана.
Обратите внимание, что когда (eflags & EXEC_FLAG_EXPLAIN_ONLY)
истинно, эта функция не должна выполнять никаких внешне видимых действий; она должна только выполнить минимально необходимые действия, чтобы сделать состояние узла допустимым для ExplainDirectModify
и EndDirectModify
.
Если указатель BeginDirectModify
установлен в
NULL
, то не предпринимаются попытки выполнить прямое изменение на
удаленном сервере.
TupleTableSlot * IterateDirectModify(ForeignScanState *node);
Когда запрос INSERT
, UPDATE
или DELETE
не содержит
предложение RETURNING
, просто возвращайте NULL
после прямого изменения на удаленном сервере.
Когда запрос содержит это предложение, извлеките один результат, содержащий данные,
необходимые для вычисления RETURNING
, и верните его в
слот таблицы кортежей (для этой цели следует использовать поле ScanTupleSlot
узла).
Данные, которые были фактически вставлены, обновлены
или удалены, должны быть сохранены в
node->resultRelInfo->ri_projectReturning->pi_exprContext->ecxt_scantuple
.
Верните NULL, если больше нет строк.
Обратите внимание, что это вызывается в контексте памяти с коротким сроком жизни, который будет
сброшен между вызовами. Создайте контекст памяти в
функции BeginDirectModify
, если вам нужно хранение с более длительным сроком жизни, или используйте
поле es_query_cxt
узла EState
.
Строки, возвращаемые, должны соответствовать целевому списку fdw_scan_tlist
, если он был предоставлен, в противном случае они должны соответствовать типу строки внешней таблицы, которая обновляется. Если вы решите оптимизировать извлечение столбцов, которые не нужны для вычисления RETURNING
, вы должны вставить null в эти позиции столбцов или сгенерировать список fdw_scan_tlist
с не указанными этими столбцами.
Независимо от того, есть ли в запросе данная фраза или нет, количество строк, сообщаемое запросом, должно быть увеличено самим FDW. Когда в запросе нет данной фразы, FDW также должен увеличить количество строк для узла ForeignScanState
в случае EXPLAIN ANALYZE
.
Если указатель IterateDirectModify
установлен в
NULL
, то не предпринимаются попытки выполнить прямое изменение на
удаленном сервере.
void EndDirectModify(ForeignScanState *node);
Очистка после прямого изменения на удаленном сервере. Обычно не важно освобождать память, выделенную с помощью palloc, но, например, открытые файлы и соединения с удаленным сервером должны быть очищены.
Если указатель EndDirectModify
установлен в
NULL
, то не предпринимаются попытки выполнить прямое изменение на
удаленном сервере.
56.2.5. FDW процедуры для TRUNCATE
#
void ExecForeignTruncate(List *rels, DropBehavior behavior, bool restart_seqs);
Обрезать внешние таблицы. Эта функция вызывается при выполнении команды TRUNCATE на внешней таблице. rels
- это список структур данных Relation
внешних таблиц, которые нужно обрезать.
behavior
может быть либо DROP_RESTRICT
,
либо DROP_CASCADE
, указывающее на то, что
опция RESTRICT
или CASCADE
была
запрошена в исходной команде TRUNCATE
,
соответственно.
Если restart_seqs
равно true
,
исходная команда TRUNCATE
запрашивает
поведение RESTART IDENTITY
, в противном случае
запрашивается поведение CONTINUE IDENTITY
.
Обратите внимание, что ONLY
опции, указанные
в исходной команде TRUNCATE
, не передаются
в ExecForeignTruncate
. Это поведение аналогично
функциям обратного вызова SELECT
,
UPDATE
и DELETE
на внешней таблице.
ExecForeignTruncate
вызывается один раз для каждого внешнего сервера, для которого требуется очистка внешних таблиц.
Это означает, что все внешние таблицы, включенные в rels
,
должны принадлежать одному серверу.
Если указатель ExecForeignTruncate
установлен в
NULL
, попытки обрезать внешние таблицы завершатся
с ошибкой и будет выведено сообщение об ошибке.
56.2.6. FDW процедуры для блокировки строк #
Если FDW хочет поддерживать позднюю блокировку строк (как описано в Раздел 56.5), он должен предоставить следующие функции обратного вызова:
RowMarkType GetForeignRowMarkType(RangeTblEntry *rte, LockClauseStrength strength);
Сообщите, какую опцию маркировки строк использовать для внешней таблицы.
rte
- это узел RangeTblEntry
для таблицы,
а strength
описывает требуемую силу блокировки, запрошенную
соответствующим предложением FOR UPDATE/SHARE
, если таковое имеется. Результат должен быть
членом перечислимого типа RowMarkType
.
Эта функция вызывается во время планирования запроса для каждой внешней таблицы, которая
появляется в запросе UPDATE
, DELETE
или SELECT
FOR UPDATE/SHARE
и не является целью UPDATE
или DELETE
.
Если указатель GetForeignRowMarkType
установлен в
NULL
, всегда используется опция ROW_MARK_COPY
.
(Это означает, что RefetchForeignRow
никогда не будет вызываться,
поэтому его также необходимо предоставлять).
См. Раздел 56.5 для получения дополнительной информации.
void RefetchForeignRow(EState *estate, ExecRowMark *erm, Datum rowid, TupleTableSlot *slot, bool *updated);
Повторно получить один слот кортежа из внешней таблицы, после его блокировки, если это требуется.
estate
- это глобальное состояние выполнения запроса.
erm
- это структура ExecRowMark
, описывающая
целевую внешнюю таблицу и тип блокировки строки (если есть), которую нужно получить.
rowid
идентифицирует кортеж, который нужно получить.
slot
не содержит ничего полезного при вызове, но может использоваться для
хранения полученного кортежа. updated
- это выходной параметр.
Эта функция должна сохранить кортеж в предоставленный слот или очистить его, если не удалось получить блокировку строки. Тип блокировки строки, который нужно получить, определяется значением erm->markType
, которое было ранее возвращено функцией GetForeignRowMarkType
. (ROW_MARK_REFERENCE
означает просто повторное извлечение кортежа без получения блокировки, а ROW_MARK_COPY
никогда не будет использоваться этой процедурой).
Кроме того, *updated
должно быть установлено в true
,
если полученная кортежа является обновленной версией, а не той же версией,
которая была получена ранее. (Если FDW не может быть уверен в этом, рекомендуется всегда возвращать true
).
Обратите внимание, что по умолчанию, неудачная попытка получить блокировку строки должна приводить к возникновению ошибки; возвращение с пустым слотом является допустимым только в том случае, если опция SKIP LOCKED
указана в erm->waitPolicy
.
The rowid
- это значение ctid
, прочитанное ранее для строки, которую нужно повторно получить. Хотя значение rowid
передается как Datum
, в настоящее время оно может быть только tid
. Функциональный интерфейс выбран в надежде, что в будущем будет возможно разрешить использование других типов данных для идентификаторов строк.
Если указатель RefetchForeignRow
установлен в
NULL
, попытки повторного получения строк завершатся
с ошибкой и выводом сообщения об ошибке.
См. Раздел 56.5 для получения дополнительной информации.
bool RecheckForeignScan(ForeignScanState *node, TupleTableSlot *slot);
Проверьте, что ранее возвращенный кортеж по-прежнему соответствует соответствующим условиям сканирования и соединения, и, возможно, предоставьте измененную версию кортежа. Для оберток внешних данных, которые не выполняют оптимизацию соединения, обычно удобнее установить это значение в NULL
и соответствующим образом установить fdw_recheck_quals
. Однако, когда внешние соединения выполняются вниз, недостаточно повторно применить проверки, относящиеся ко всем базовым таблицам, к результату кортежа, даже если все необходимые атрибуты присутствуют, потому что несоответствие некоторого условия может привести к тому, что некоторые атрибуты станут NULL, а не к тому, что кортеж не будет возвращен. RecheckForeignScan
может повторно проверить условия и вернуть true, если они по-прежнему выполняются, и false в противном случае, но он также может сохранить замену кортежа в предоставленном слоте.
Для реализации передачи соединения, обертка внешних данных обычно создает альтернативный локальный план соединения, который используется только для повторных проверок; это становится внешним подпланом ForeignScan
. Когда требуется повторная проверка, этот подплан может быть выполнен, и полученный кортеж может быть сохранен в слоте. Этот план не обязан быть эффективным, так как ни одна базовая таблица не вернет более одной строки; например, он может реализовывать все соединения в виде вложенных циклов. Функция GetExistingLocalJoinPath
может использоваться для поиска существующих путей для подходящего локального пути соединения, который может быть использован в качестве альтернативного локального плана соединения. GetExistingLocalJoinPath
ищет непараметризованный путь в списке путей указанного соединения. (Если такой путь не найден, он возвращает NULL, в этом случае обертка внешних данных может самостоятельно создать локальный путь или может выбрать не создавать доступные пути для этого соединения).
56.2.7. FDW процедуры для EXPLAIN
#
void ExplainForeignScan(ForeignScanState *node, ExplainState *es);
Выводить дополнительную информацию EXPLAIN
для сканирования внешней таблицы.
Эта функция может вызывать ExplainPropertyText
и
связанные функции для добавления полей в вывод EXPLAIN
.
Флаги в es
могут использоваться для определения того, что выводить,
и состояние узла ForeignScanState
может быть проверено для
предоставления статистики выполнения в случае использования EXPLAIN
ANALYZE
.
Если указатель ExplainForeignScan
установлен в
NULL
, дополнительная информация не будет выводиться во время
EXPLAIN
.
void ExplainForeignModify(ModifyTableState *mtstate, ResultRelInfo *rinfo, List *fdw_private, int subplan_index, struct ExplainState *es);
Выводить дополнительную информацию EXPLAIN
для обновления внешней таблицы.
Эта функция может вызывать ExplainPropertyText
и
связанные функции для добавления полей в вывод EXPLAIN
.
Флаги в es
могут использоваться для определения того, что выводить,
и состояние узла ModifyTableState
может быть проверено для
предоставления статистики выполнения в случае использования EXPLAIN
ANALYZE
. Первые четыре аргумента такие же, как для
BeginForeignModify
.
Если указатель ExplainForeignModify
установлен в
NULL
, дополнительная информация не выводится во время
EXPLAIN
.
void ExplainDirectModify(ForeignScanState *node, ExplainState *es);
Выводите дополнительную информацию EXPLAIN
для прямого изменения на удаленном сервере. Эта функция может вызывать ExplainPropertyText
и связанные функции для добавления полей в вывод EXPLAIN
. Флаговые поля в es
могут использоваться для определения того, что нужно печатать, и состояние узла ForeignScanState
может быть проверено для предоставления статистики времени выполнения в случае использования EXPLAIN ANALYZE
.
Если указатель ExplainDirectModify
установлен в
NULL
, дополнительная информация не будет выводиться во время
EXPLAIN
.
56.2.8. FDW процедуры для ANALYZE
#
bool AnalyzeForeignTable(Relation relation, AcquireSampleRowsFunc *func, BlockNumber *totalpages);
Эта функция вызывается, когда выполняется ANALYZE на
внешней таблице. Если FDW может собирать статистику для этой
внешней таблицы, он должен вернуть true
и предоставить указатель
на функцию, которая будет собирать образцовые строки из таблицы в
func
, а также оценочный размер таблицы в страницах в
totalpages
. В противном случае вернуть false
.
Если FDW не поддерживает сбор статистики для каких-либо таблиц, указатель AnalyzeForeignTable
может быть установлен в значение NULL
.
Если предоставлено, функция сбора образца должна иметь сигнатуру
int AcquireSampleRowsFunc(Relation relation, int elevel, HeapTuple *rows, int targrows, double *totalrows, double *totaldeadrows);
Следует собрать случайную выборку из до targrows
строк из таблицы и сохранить их в предоставленный вызывающей стороной массив rows
. Фактическое количество собранных строк должно быть возвращено. Кроме того, оценки общего количества активных и удаленных строк в таблице должны быть сохранены в выходных параметрах totalrows
и totaldeadrows
. (Установите totaldeadrows
в ноль, если FDW не имеет понятия об удаленных строках).
56.2.9. FDW процедуры для IMPORT FOREIGN SCHEMA
#
List * ImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid);
Получить список команд создания внешних таблиц. Эта функция вызывается при выполнении IMPORT FOREIGN SCHEMA, и ей передается дерево разбора для этого оператора, а также OID внешнего сервера, который нужно использовать. Она должна вернуть список C-строк, каждая из которых должна содержать команду CREATE FOREIGN TABLE. Эти строки будут разобраны и выполнены ядром сервера.
Внутри структуры ImportForeignSchemaStmt
,
remote_schema
- это имя удаленной схемы, из которой
будут импортироваться таблицы.
list_type
определяет, как фильтровать имена таблиц:
FDW_IMPORT_SCHEMA_ALL
означает, что все таблицы в удаленной
схеме должны быть импортированы (в этом случае table_list
пуст),
FDW_IMPORT_SCHEMA_LIMIT_TO
означает, что нужно включить только
таблицы, перечисленные в table_list
,
а FDW_IMPORT_SCHEMA_EXCEPT
означает, что нужно исключить таблицы,
перечисленные в table_list
.
options
- это список опций, используемых для процесса импорта.
Значения опций зависят от FDW.
Например, FDW может использовать опцию для определения того, должны ли
импортироваться атрибуты NOT NULL
столбцов.
Эти опции не обязательно должны иметь отношение к опциям, поддерживаемым
FDW в качестве опций объектов базы данных.
FDW может игнорировать поле local_schema
в ImportForeignSchemaStmt
, поскольку ядро сервера автоматически вставляет это имя в разобранные команды CREATE FOREIGN TABLE
.
FDW не должен беспокоиться о реализации фильтрации, указанной в list_type
и table_list
, так как ядро сервера автоматически пропускает любые возвращаемые команды для таблиц, исключенных в соответствии с этими опциями. Однако часто полезно избежать работы по созданию команд для исключенных таблиц в первую очередь. Функция IsImportableForeignTable()
может быть полезна для проверки, пройдет ли заданное имя внешней таблицы фильтр.
Если FDW не поддерживает импорт определений таблиц, указатель ImportForeignSchema
может быть установлен в NULL
.
56.2.10. FDW процедуры для Параллельного Выполнения #
Узел ForeignScan
может, по желанию, поддерживать параллельное выполнение. Параллельный ForeignScan
будет выполняться в нескольких процессах и должен возвращать каждую строку ровно один раз во всех взаимодействующих процессах. Для этого процессы могут согласовываться через фиксированные части динамической общей памяти. Эта общая память не гарантирует, что она будет отображена по тому же адресу в каждом процессе, поэтому она не должна содержать указателей. Все перечисленные ниже функции являются необязательными, но большинство из них требуется для поддержки параллельного выполнения.
bool IsForeignScanParallelSafe(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte);
Проверьте, может ли быть выполнено сканирование внутри параллельного рабочего процесса. Эта функция будет вызвана только тогда, когда планировщик считает возможным параллельное планирование, и должна вернуть true, если это безопасно для выполнения сканирования внутри параллельного рабочего процесса. Это обычно не будет возможно, если удаленный источник данных имеет семантику транзакций, если только соединение рабочего процесса с данными не может быть как-то сделано для совместного использования того же контекста транзакции, что и у лидера.
Если эта функция не определена, предполагается, что сканирование должно происходить внутри параллельного лидера. Обратите внимание, что возвращение значения true не означает, что само сканирование может выполняться параллельно, а только то, что сканирование может быть выполнено внутри параллельного рабочего процесса. Поэтому может быть полезно определить этот метод, даже когда параллельное выполнение не поддерживается.
Size EstimateDSMForeignScan(ForeignScanState *node, ParallelContext *pcxt);
Оцените количество динамической общей памяти, которая будет необходима для параллельной работы. Это значение может быть выше, чем фактически используемое количество, но не должно быть меньше. Возвращаемое значение указано в байтах. Эта функция является необязательной и можно опустить, если не требуется; но если она не указана, следующие три функции также должны быть не указаны, потому что для использования FDW не будет выделена общая память.
void InitializeDSMForeignScan(ForeignScanState *node, ParallelContext *pcxt, void *coordinate);
Инициализируйте динамическую общую память, которая будет необходима для параллельной работы. coordinate
указывает на область общей памяти размером, равным возвращаемому значению функции EstimateDSMForeignScan
. Эта функция является необязательной и можно опустить, если она не требуется.
void ReInitializeDSMForeignScan(ForeignScanState *node, ParallelContext *pcxt, void *coordinate);
Переинициализируйте динамическую общую память, необходимую для параллельной работы, когда узел плана foreign-scan должен быть повторно отсканирован.
Эта функция является необязательной и можно опустить, если не требуется.
Рекомендуется, чтобы эта функция сбрасывала только общее состояние, в то время как функция ReScanForeignScan
сбрасывает только локальное состояние. В настоящее время эта функция будет вызвана перед ReScanForeignScan
, но лучше не полагаться на этот порядок.
void InitializeWorkerForeignScan(ForeignScanState *node, shm_toc *toc, void *coordinate);
Инициализирует локальное состояние параллельного рабочего процесса на основе общего состояния, установленного лидером во время InitializeDSMForeignScan
.
Эта функция является необязательной и можно опустить, если не требуется.
void ShutdownForeignScan(ForeignScanState *node);
Освободите ресурсы, когда ожидается, что узел не будет выполнен до конца. Это не вызывается во всех случаях; иногда EndForeignScan
может быть вызван без предварительного вызова этой функции. Поскольку сегмент DSM, используемый параллельным запросом, уничтожается сразу после вызова этого обратного вызова, обертки внешних данных, которые хотят выполнить некоторые действия перед уничтожением сегмента DSM, должны реализовать этот метод.
56.2.11. FDW процедуры для асинхронного выполнения #
Узел ForeignScan
может, по желанию, поддерживать асинхронное выполнение, как описано в файле src/backend/executor/README
. Следующие функции все являются необязательными, но все они необходимы для поддержки асинхронного выполнения.
bool IsForeignPathAsyncCapable(ForeignPath *path);
Проверяет, может ли данный путь ForeignPath
сканировать
базовое внешнее отношение асинхронно.
Эта функция будет вызвана только в конце планирования запроса, когда
данный путь является прямым наследником пути AppendPath
и когда планировщик считает, что асинхронное выполнение улучшает
производительность, и должна возвращать true, если данный путь может сканировать
внешнее отношение асинхронно.
Если эта функция не определена, предполагается, что указанный путь сканирует внешнее отношение с помощью функции IterateForeignScan
.
(Это означает, что описанные ниже функции обратного вызова никогда не будут вызываться, поэтому их также не нужно предоставлять).
void ForeignAsyncRequest(AsyncRequest *areq);
Асинхронно производит одну кортеж из узла ForeignScan
. areq
- это структура AsyncRequest
, описывающая узел ForeignScan
и родительский узел Append
, который запросил кортеж из него. Эта функция должна сохранить кортеж в слоте, указанном в areq->result
, и установить areq->request_complete
в true
; или, если она должна ожидать события внешнего от ядра сервера, такого как сетевой ввод-вывод, и не может немедленно произвести кортеж, установить флаг в false
, и установить areq->callback_pending
в true
для узла ForeignScan
, чтобы получить обратный вызов от описанных ниже функций обратного вызова. Если больше нет доступных кортежей, установите слот в NULL или пустой слот, и флаг areq->request_complete
в true
. Рекомендуется использовать функции ExecAsyncRequestDone
или ExecAsyncRequestPending
для установки выходных параметров в areq
.
void ForeignAsyncConfigureWait(AsyncRequest *areq);
Настроить событие файлового дескриптора, на которое узел ForeignScan
хочет ожидать.
Эта функция будет вызвана только тогда, когда узел ForeignScan
имеет установленный флаг areq->callback_pending
и должна добавить событие в as_eventset
родительского узла Append
, описанного areq
. Дополнительную информацию см. в комментариях к функции ExecAsyncConfigureWait
в файле src/backend/executor/execAsync.c
. При возникновении события файлового дескриптора будет вызвана функция ForeignAsyncNotify
.
void ForeignAsyncNotify(AsyncRequest *areq);
Обработайте соответствующее событие, которое произошло, затем асинхронно создайте одну кортеж из узла ForeignScan
.
Эта функция должна установить выходные параметры в areq
так же, как и ForeignAsyncRequest
.
56.2.12. FDW процедуры для перепараметризации путей #
List * ReparameterizeForeignPathByChild(PlannerInfo *root, List *fdw_private, RelOptInfo *child_rel);
Эта функция вызывается при преобразовании пути, параметризованного верхним родительским отношением заданного дочернего отношения child_rel
, чтобы параметризовать его дочерним отношением. Функция используется для повторного параметризации любых путей или перевода любых сохраненных узлов выражений в члене fdw_private
структуры ForeignPath
. Обратный вызов может использовать reparameterize_path_by_child
, adjust_appendrel_attrs
или adjust_appendrel_attrs_multilevel
по необходимости.