Un proveedor de escaneo personalizado agregará típicamente rutas para una relación base estableciendo el siguiente hook (gancho), que se llama después de que el código central ha generado todas las rutas de acceso posibles para la relación (excepto las rutas Gather y Gather Merge, que se realizan después de esta llamada para que puedan usar rutas parciales agregadas por el hook):
typedef void (*set_rel_pathlist_hook_type) (PlannerInfo *root,
RelOptInfo *rel,
Index rti,
RangeTblEntry *rte);
extern PGDLLIMPORT set_rel_pathlist_hook_type set_rel_pathlist_hook;
Aunque esta función de hook se puede usar para examinar, modificar o eliminar
rutas generadas por el sistema central, un proveedor de escaneo personalizado típicamente
se limitará a generar objetos CustomPath y agregarlos a
rel usando add_path, o
add_partial_path si son rutas parciales. El
proveedor de escaneo personalizado es responsable de inicializar el
objeto CustomPath, que se declara así:
typedef struct CustomPath
{
Path path;
uint32 flags;
List *custom_paths;
List *custom_restrictinfo;
List *custom_private;
const CustomPathMethods *methods;
} CustomPath;
path debe inicializarse como para cualquier otra ruta, incluyendo
la estimación del número de filas, el costo inicial y total, y el ordenamiento proporcionado
por esta ruta. flags es una máscara de bits que
especifica si el proveedor de escaneo puede admitir ciertas capacidades opcionales.
flags debe incluir
CUSTOMPATH_SUPPORT_BACKWARD_SCAN si la ruta personalizada admite
un escaneo hacia atrás, CUSTOMPATH_SUPPORT_MARK_RESTORE si
admite marcar y restaurar,
y CUSTOMPATH_SUPPORT_PROJECTION si puede realizar
proyecciones. (Si CUSTOMPATH_SUPPORT_PROJECTION no
está establecido, al nodo de escaneo solo se le pedirá que produzca Vars de la relación
escaneada; mientras que si se establece ese flag, el nodo de escaneo debe ser capaz de
evaluar expresiones escalares sobre estas Vars).
Un campo opcional custom_paths es una lista de nodos Path
utilizados por este nodo de ruta personalizada; el planificador los transformará en
nodos Plan.
Como se describe a continuación, también se pueden crear rutas personalizadas para relaciones de unión (join).
En tal caso, se debe usar custom_restrictinfo
para almacenar el conjunto de cláusulas de unión a aplicar a la unión que la
ruta personalizada reemplaza. De lo contrario, debe ser NIL.
custom_private se puede utilizar para almacenar los datos
privados de la ruta personalizada. Los datos privados deben almacenarse en una forma que pueda ser manejada
por nodeToString, para que las rutinas de depuración que intentan
imprimir la ruta personalizada funcionen como se diseñó. methods debe
apuntar a un objeto (generalmente asignado estáticamente) que implemente los métodos de
ruta personalizados requeridos, que se detallan más adelante.
Un proveedor de escaneo personalizado también puede proporcionar rutas de unión. Al igual
que para las relaciones base, dicha ruta debe producir la misma salida que normalmente se
produciría por la unión que reemplaza. Para hacer esto, el proveedor de unión debe
establecer el siguiente hook, y luego dentro de la función del hook,
crear ruta(s) CustomPath para la relación de unión.
typedef void (*set_join_pathlist_hook_type) (PlannerInfo *root,
RelOptInfo *joinrel,
RelOptInfo *outerrel,
RelOptInfo *innerrel,
JoinType jointype,
JoinPathExtraData *extra);
extern PGDLLIMPORT set_join_pathlist_hook_type set_join_pathlist_hook;
Este hook se invocará repetidamente para la misma relación de unión, con diferentes combinaciones de relaciones internas y externas; es responsabilidad del hook minimizar el trabajo duplicado.
Ten en cuenta también que el conjunto de cláusulas de unión a aplicar a la unión,
que se pasa como extra->restrictlist, varía
según la combinación de relaciones internas y externas. Una ruta
CustomPath generada para el
joinrel debe contener el conjunto de cláusulas de unión que utiliza,
que el planificador usará para convertir la ruta
CustomPath en un plan, si el planificador la selecciona
como la mejor ruta para el joinrel.
Plan *(*PlanCustomPath) (PlannerInfo *root,
RelOptInfo *rel,
CustomPath *best_path,
List *tlist,
List *clauses,
List *custom_plans);
Convierte una ruta personalizada en un plan terminado. El valor de retorno generalmente
será un objeto CustomScan, que el callback debe asignar e
inicializar. Consulta la Section 60.2 para obtener más detalles.
List *(*ReparameterizeCustomPathByChild) (PlannerInfo *root,
List *custom_private,
RelOptInfo *child_rel);
Este callback se llama al convertir una ruta parametrizada por el
padre más alto de la relación hija dada child_rel
para ser parametrizada por la relación hija. El callback se usa para
volver a parametrizar cualquier ruta o traducir cualquier nodo de expresión guardado en el
miembro custom_private dado de un
CustomPath. El callback puede usar
reparameterize_path_by_child,
adjust_appendrel_attrs o
adjust_appendrel_attrs_multilevel según sea necesario.