Un escaneo personalizado se representa en un árbol de plan terminado utilizando la siguiente estructura:
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 debe inicializarse como para cualquier otro escaneo, incluyendo
costos estimados, listas de destino, calificaciones, etc.
flags es una máscara de bits con el mismo significado que en
CustomPath.
custom_plans se puede utilizar para almacenar nodos hijos
Plan.
custom_exprs debe usarse para
almacenar árboles de expresiones que necesitarán ser reparados por
setrefs.c y subselect.c, mientras que
custom_private debe usarse para almacenar otros datos privados
que solo usa el propio proveedor de escaneo personalizado.
custom_scan_tlist puede ser NIL al escanear una relación
base, indicando que el escaneo personalizado devuelve tuplas de escaneo que coinciden
con el tipo de fila de la relación base. De lo contrario, es una lista de destino que describe
las tuplas de escaneo reales. custom_scan_tlist se debe
proporcionar para uniones, y se podría proporcionar para escaneos si el proveedor de escaneo
personalizado puede calcular algunas expresiones que no sean Var.
El código central establece custom_relids en el conjunto de
relaciones (índices de la tabla de rango) que maneja este nodo de escaneo; excepto cuando
este escaneo reemplaza una unión, tendrá solo un miembro.
methods debe apuntar a un objeto (generalmente asignado estáticamente)
que implemente los métodos de escaneo personalizados requeridos, que se detallan más adelante.
Cuando un CustomScan escanea una sola relación,
scan.scanrelid debe ser el índice de la tabla de rango de la tabla
a escanear. Cuando reemplaza una unión, scan.scanrelid
debe ser cero.
Los árboles de plan deben poder duplicarse usando copyObject,
por lo que todos los datos almacenados dentro de los campos “custom” deben consistir en
nodos que esa función pueda manejar. Además, los proveedores de escaneo
personalizados no pueden sustituir una estructura más grande que incorpore
un CustomScan en lugar de la estructura misma, como sería posible
para un CustomPath o un CustomScanState.
Node *(*CreateCustomScanState) (CustomScan *cscan);
Asigna un CustomScanState para este
CustomScan. La asignación real a menudo será mayor que la
requerida para un CustomScanState ordinario, porque muchos
proveedores desearán incorporar eso como el primer campo de una estructura más grande.
El valor devuelto debe tener la etiqueta del nodo y methods
establecidos apropiadamente, pero los otros campos deben dejarse en cero en esta
etapa; después de que ExecInitCustomScan realice la inicialización básica,
se invocará el callback BeginCustomScan para dar al
proveedor de escaneo personalizado la oportunidad de hacer lo que sea necesario.