1 /* ------------------------------------------------------------------------
4 * Routines to handle execution of custom scan node
6 * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
9 * ------------------------------------------------------------------------
13 #include "access/parallel.h"
14 #include "executor/executor.h"
15 #include "executor/nodeCustom.h"
16 #include "nodes/execnodes.h"
17 #include "nodes/plannodes.h"
18 #include "miscadmin.h"
19 #include "parser/parsetree.h"
20 #include "utils/hsearch.h"
21 #include "utils/memutils.h"
22 #include "utils/rel.h"
25 static TupleTableSlot *ExecCustomScan(PlanState *pstate);
29 ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags)
32 Relation scan_rel = NULL;
33 Index scanrelid = cscan->scan.scanrelid;
37 * Allocate the CustomScanState object. We let the custom scan provider
38 * do the palloc, in case it wants to make a larger object that embeds
39 * CustomScanState as the first field. It must set the node tag and the
40 * methods field correctly at this time. Other standard fields should be
43 css = castNode(CustomScanState,
44 cscan->methods->CreateCustomScanState(cscan));
46 /* ensure flags is filled correctly */
47 css->flags = cscan->flags;
49 /* fill up fields of ScanState */
50 css->ss.ps.plan = &cscan->scan.plan;
51 css->ss.ps.state = estate;
52 css->ss.ps.ExecProcNode = ExecCustomScan;
54 /* create expression context for node */
55 ExecAssignExprContext(estate, &css->ss.ps);
58 * open the scan relation, if any
62 scan_rel = ExecOpenScanRelation(estate, scanrelid, eflags);
63 css->ss.ss_currentRelation = scan_rel;
67 * Determine the scan tuple type. If the custom scan provider provided a
68 * targetlist describing the scan tuples, use that; else use base
71 if (cscan->custom_scan_tlist != NIL || scan_rel == NULL)
73 TupleDesc scan_tupdesc;
75 scan_tupdesc = ExecTypeFromTL(cscan->custom_scan_tlist);
76 ExecInitScanTupleSlot(estate, &css->ss, scan_tupdesc, &TTSOpsVirtual);
77 /* Node's targetlist will contain Vars with varno = INDEX_VAR */
78 tlistvarno = INDEX_VAR;
82 ExecInitScanTupleSlot(estate, &css->ss, RelationGetDescr(scan_rel),
84 /* Node's targetlist will contain Vars with varno = scanrelid */
85 tlistvarno = scanrelid;
89 * Initialize result slot, type and projection.
91 ExecInitResultTupleSlotTL(&css->ss.ps, &TTSOpsVirtual);
92 ExecAssignScanProjectionInfoWithVarno(&css->ss, tlistvarno);
94 /* initialize child expressions */
96 ExecInitQual(cscan->scan.plan.qual, (PlanState *) css);
99 * The callback of custom-scan provider applies the final initialization
100 * of the custom-scan-state node according to its logic.
102 css->methods->BeginCustomScan(css, estate, eflags);
107 static TupleTableSlot *
108 ExecCustomScan(PlanState *pstate)
110 CustomScanState *node = castNode(CustomScanState, pstate);
112 CHECK_FOR_INTERRUPTS();
114 Assert(node->methods->ExecCustomScan != NULL);
115 return node->methods->ExecCustomScan(node);
119 ExecEndCustomScan(CustomScanState *node)
121 Assert(node->methods->EndCustomScan != NULL);
122 node->methods->EndCustomScan(node);
124 /* Free the exprcontext */
125 ExecFreeExprContext(&node->ss.ps);
127 /* Clean out the tuple table */
128 ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
129 ExecClearTuple(node->ss.ss_ScanTupleSlot);
133 ExecReScanCustomScan(CustomScanState *node)
135 Assert(node->methods->ReScanCustomScan != NULL);
136 node->methods->ReScanCustomScan(node);
140 ExecCustomMarkPos(CustomScanState *node)
142 if (!node->methods->MarkPosCustomScan)
144 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
145 errmsg("custom scan \"%s\" does not support MarkPos",
146 node->methods->CustomName)));
147 node->methods->MarkPosCustomScan(node);
151 ExecCustomRestrPos(CustomScanState *node)
153 if (!node->methods->RestrPosCustomScan)
155 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
156 errmsg("custom scan \"%s\" does not support MarkPos",
157 node->methods->CustomName)));
158 node->methods->RestrPosCustomScan(node);
162 ExecCustomScanEstimate(CustomScanState *node, ParallelContext *pcxt)
164 const CustomExecMethods *methods = node->methods;
166 if (methods->EstimateDSMCustomScan)
168 node->pscan_len = methods->EstimateDSMCustomScan(node, pcxt);
169 shm_toc_estimate_chunk(&pcxt->estimator, node->pscan_len);
170 shm_toc_estimate_keys(&pcxt->estimator, 1);
175 ExecCustomScanInitializeDSM(CustomScanState *node, ParallelContext *pcxt)
177 const CustomExecMethods *methods = node->methods;
179 if (methods->InitializeDSMCustomScan)
181 int plan_node_id = node->ss.ps.plan->plan_node_id;
184 coordinate = shm_toc_allocate(pcxt->toc, node->pscan_len);
185 methods->InitializeDSMCustomScan(node, pcxt, coordinate);
186 shm_toc_insert(pcxt->toc, plan_node_id, coordinate);
191 ExecCustomScanReInitializeDSM(CustomScanState *node, ParallelContext *pcxt)
193 const CustomExecMethods *methods = node->methods;
195 if (methods->ReInitializeDSMCustomScan)
197 int plan_node_id = node->ss.ps.plan->plan_node_id;
200 coordinate = shm_toc_lookup(pcxt->toc, plan_node_id, false);
201 methods->ReInitializeDSMCustomScan(node, pcxt, coordinate);
206 ExecCustomScanInitializeWorker(CustomScanState *node,
207 ParallelWorkerContext *pwcxt)
209 const CustomExecMethods *methods = node->methods;
211 if (methods->InitializeWorkerCustomScan)
213 int plan_node_id = node->ss.ps.plan->plan_node_id;
216 coordinate = shm_toc_lookup(pwcxt->toc, plan_node_id, false);
217 methods->InitializeWorkerCustomScan(node, pwcxt->toc, coordinate);
222 ExecShutdownCustomScan(CustomScanState *node)
224 const CustomExecMethods *methods = node->methods;
226 if (methods->ShutdownCustomScan)
227 methods->ShutdownCustomScan(node);