Line data Source code
1 : /* ------------------------------------------------------------------------
2 : *
3 : * nodeCustom.c
4 : * Routines to handle execution of custom scan node
5 : *
6 : * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : * ------------------------------------------------------------------------
10 : */
11 : #include "postgres.h"
12 :
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"
23 :
24 :
25 : static TupleTableSlot *ExecCustomScan(PlanState *pstate);
26 :
27 :
28 : CustomScanState *
29 0 : ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags)
30 : {
31 : CustomScanState *css;
32 0 : Relation scan_rel = NULL;
33 0 : Index scanrelid = cscan->scan.scanrelid;
34 : Index tlistvarno;
35 :
36 : /*
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
41 : * set to zero.
42 : */
43 0 : css = castNode(CustomScanState,
44 : cscan->methods->CreateCustomScanState(cscan));
45 :
46 : /* ensure flags is filled correctly */
47 0 : css->flags = cscan->flags;
48 :
49 : /* fill up fields of ScanState */
50 0 : css->ss.ps.plan = &cscan->scan.plan;
51 0 : css->ss.ps.state = estate;
52 0 : css->ss.ps.ExecProcNode = ExecCustomScan;
53 :
54 : /* create expression context for node */
55 0 : ExecAssignExprContext(estate, &css->ss.ps);
56 :
57 : /* initialize child expressions */
58 0 : css->ss.ps.qual =
59 0 : ExecInitQual(cscan->scan.plan.qual, (PlanState *) css);
60 :
61 : /* tuple table initialization */
62 0 : ExecInitScanTupleSlot(estate, &css->ss);
63 0 : ExecInitResultTupleSlot(estate, &css->ss.ps);
64 :
65 : /*
66 : * open the base relation, if any, and acquire an appropriate lock on it
67 : */
68 0 : if (scanrelid > 0)
69 : {
70 0 : scan_rel = ExecOpenScanRelation(estate, scanrelid, eflags);
71 0 : css->ss.ss_currentRelation = scan_rel;
72 : }
73 :
74 : /*
75 : * Determine the scan tuple type. If the custom scan provider provided a
76 : * targetlist describing the scan tuples, use that; else use base
77 : * relation's rowtype.
78 : */
79 0 : if (cscan->custom_scan_tlist != NIL || scan_rel == NULL)
80 0 : {
81 : TupleDesc scan_tupdesc;
82 :
83 0 : scan_tupdesc = ExecTypeFromTL(cscan->custom_scan_tlist, false);
84 0 : ExecAssignScanType(&css->ss, scan_tupdesc);
85 : /* Node's targetlist will contain Vars with varno = INDEX_VAR */
86 0 : tlistvarno = INDEX_VAR;
87 : }
88 : else
89 : {
90 0 : ExecAssignScanType(&css->ss, RelationGetDescr(scan_rel));
91 : /* Node's targetlist will contain Vars with varno = scanrelid */
92 0 : tlistvarno = scanrelid;
93 : }
94 :
95 : /*
96 : * Initialize result tuple type and projection info.
97 : */
98 0 : ExecAssignResultTypeFromTL(&css->ss.ps);
99 0 : ExecAssignScanProjectionInfoWithVarno(&css->ss, tlistvarno);
100 :
101 : /*
102 : * The callback of custom-scan provider applies the final initialization
103 : * of the custom-scan-state node according to its logic.
104 : */
105 0 : css->methods->BeginCustomScan(css, estate, eflags);
106 :
107 0 : return css;
108 : }
109 :
110 : static TupleTableSlot *
111 0 : ExecCustomScan(PlanState *pstate)
112 : {
113 0 : CustomScanState *node = castNode(CustomScanState, pstate);
114 :
115 0 : CHECK_FOR_INTERRUPTS();
116 :
117 0 : Assert(node->methods->ExecCustomScan != NULL);
118 0 : return node->methods->ExecCustomScan(node);
119 : }
120 :
121 : void
122 0 : ExecEndCustomScan(CustomScanState *node)
123 : {
124 0 : Assert(node->methods->EndCustomScan != NULL);
125 0 : node->methods->EndCustomScan(node);
126 :
127 : /* Free the exprcontext */
128 0 : ExecFreeExprContext(&node->ss.ps);
129 :
130 : /* Clean out the tuple table */
131 0 : ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
132 0 : ExecClearTuple(node->ss.ss_ScanTupleSlot);
133 :
134 : /* Close the heap relation */
135 0 : if (node->ss.ss_currentRelation)
136 0 : ExecCloseScanRelation(node->ss.ss_currentRelation);
137 0 : }
138 :
139 : void
140 0 : ExecReScanCustomScan(CustomScanState *node)
141 : {
142 0 : Assert(node->methods->ReScanCustomScan != NULL);
143 0 : node->methods->ReScanCustomScan(node);
144 0 : }
145 :
146 : void
147 0 : ExecCustomMarkPos(CustomScanState *node)
148 : {
149 0 : if (!node->methods->MarkPosCustomScan)
150 0 : ereport(ERROR,
151 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
152 : errmsg("custom scan \"%s\" does not support MarkPos",
153 : node->methods->CustomName)));
154 0 : node->methods->MarkPosCustomScan(node);
155 0 : }
156 :
157 : void
158 0 : ExecCustomRestrPos(CustomScanState *node)
159 : {
160 0 : if (!node->methods->RestrPosCustomScan)
161 0 : ereport(ERROR,
162 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
163 : errmsg("custom scan \"%s\" does not support MarkPos",
164 : node->methods->CustomName)));
165 0 : node->methods->RestrPosCustomScan(node);
166 0 : }
167 :
168 : void
169 0 : ExecCustomScanEstimate(CustomScanState *node, ParallelContext *pcxt)
170 : {
171 0 : const CustomExecMethods *methods = node->methods;
172 :
173 0 : if (methods->EstimateDSMCustomScan)
174 : {
175 0 : node->pscan_len = methods->EstimateDSMCustomScan(node, pcxt);
176 0 : shm_toc_estimate_chunk(&pcxt->estimator, node->pscan_len);
177 0 : shm_toc_estimate_keys(&pcxt->estimator, 1);
178 : }
179 0 : }
180 :
181 : void
182 0 : ExecCustomScanInitializeDSM(CustomScanState *node, ParallelContext *pcxt)
183 : {
184 0 : const CustomExecMethods *methods = node->methods;
185 :
186 0 : if (methods->InitializeDSMCustomScan)
187 : {
188 0 : int plan_node_id = node->ss.ps.plan->plan_node_id;
189 : void *coordinate;
190 :
191 0 : coordinate = shm_toc_allocate(pcxt->toc, node->pscan_len);
192 0 : methods->InitializeDSMCustomScan(node, pcxt, coordinate);
193 0 : shm_toc_insert(pcxt->toc, plan_node_id, coordinate);
194 : }
195 0 : }
196 :
197 : void
198 0 : ExecCustomScanReInitializeDSM(CustomScanState *node, ParallelContext *pcxt)
199 : {
200 0 : const CustomExecMethods *methods = node->methods;
201 :
202 0 : if (methods->ReInitializeDSMCustomScan)
203 : {
204 0 : int plan_node_id = node->ss.ps.plan->plan_node_id;
205 : void *coordinate;
206 :
207 0 : coordinate = shm_toc_lookup(pcxt->toc, plan_node_id, false);
208 0 : methods->ReInitializeDSMCustomScan(node, pcxt, coordinate);
209 : }
210 0 : }
211 :
212 : void
213 0 : ExecCustomScanInitializeWorker(CustomScanState *node, shm_toc *toc)
214 : {
215 0 : const CustomExecMethods *methods = node->methods;
216 :
217 0 : if (methods->InitializeWorkerCustomScan)
218 : {
219 0 : int plan_node_id = node->ss.ps.plan->plan_node_id;
220 : void *coordinate;
221 :
222 0 : coordinate = shm_toc_lookup(toc, plan_node_id, false);
223 0 : methods->InitializeWorkerCustomScan(node, toc, coordinate);
224 : }
225 0 : }
226 :
227 : void
228 0 : ExecShutdownCustomScan(CustomScanState *node)
229 : {
230 0 : const CustomExecMethods *methods = node->methods;
231 :
232 0 : if (methods->ShutdownCustomScan)
233 0 : methods->ShutdownCustomScan(node);
234 0 : }
|