60.2. Creación de planes de escaneo personalizados #

60.2.1. Callbacks de plan de escaneo personalizado

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.

60.2.1. Callbacks de plan de escaneo personalizado #

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.