]> granicus.if.org Git - postgresql/blob - src/backend/executor/nodeCustom.c
Update copyright for 2019
[postgresql] / src / backend / executor / nodeCustom.c
1 /* ------------------------------------------------------------------------
2  *
3  * nodeCustom.c
4  *              Routines to handle execution of custom scan node
5  *
6  * Portions Copyright (c) 1996-2019, 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 ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags)
30 {
31         CustomScanState *css;
32         Relation        scan_rel = NULL;
33         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         css = castNode(CustomScanState,
44                                    cscan->methods->CreateCustomScanState(cscan));
45
46         /* ensure flags is filled correctly */
47         css->flags = cscan->flags;
48
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;
53
54         /* create expression context for node */
55         ExecAssignExprContext(estate, &css->ss.ps);
56
57         /*
58          * open the scan relation, if any
59          */
60         if (scanrelid > 0)
61         {
62                 scan_rel = ExecOpenScanRelation(estate, scanrelid, eflags);
63                 css->ss.ss_currentRelation = scan_rel;
64         }
65
66         /*
67          * Determine the scan tuple type.  If the custom scan provider provided a
68          * targetlist describing the scan tuples, use that; else use base
69          * relation's rowtype.
70          */
71         if (cscan->custom_scan_tlist != NIL || scan_rel == NULL)
72         {
73                 TupleDesc       scan_tupdesc;
74
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;
79         }
80         else
81         {
82                 ExecInitScanTupleSlot(estate, &css->ss, RelationGetDescr(scan_rel),
83                                                           &TTSOpsVirtual);
84                 /* Node's targetlist will contain Vars with varno = scanrelid */
85                 tlistvarno = scanrelid;
86         }
87
88         /*
89          * Initialize result slot, type and projection.
90          */
91         ExecInitResultTupleSlotTL(&css->ss.ps, &TTSOpsVirtual);
92         ExecAssignScanProjectionInfoWithVarno(&css->ss, tlistvarno);
93
94         /* initialize child expressions */
95         css->ss.ps.qual =
96                 ExecInitQual(cscan->scan.plan.qual, (PlanState *) css);
97
98         /*
99          * The callback of custom-scan provider applies the final initialization
100          * of the custom-scan-state node according to its logic.
101          */
102         css->methods->BeginCustomScan(css, estate, eflags);
103
104         return css;
105 }
106
107 static TupleTableSlot *
108 ExecCustomScan(PlanState *pstate)
109 {
110         CustomScanState *node = castNode(CustomScanState, pstate);
111
112         CHECK_FOR_INTERRUPTS();
113
114         Assert(node->methods->ExecCustomScan != NULL);
115         return node->methods->ExecCustomScan(node);
116 }
117
118 void
119 ExecEndCustomScan(CustomScanState *node)
120 {
121         Assert(node->methods->EndCustomScan != NULL);
122         node->methods->EndCustomScan(node);
123
124         /* Free the exprcontext */
125         ExecFreeExprContext(&node->ss.ps);
126
127         /* Clean out the tuple table */
128         ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
129         ExecClearTuple(node->ss.ss_ScanTupleSlot);
130 }
131
132 void
133 ExecReScanCustomScan(CustomScanState *node)
134 {
135         Assert(node->methods->ReScanCustomScan != NULL);
136         node->methods->ReScanCustomScan(node);
137 }
138
139 void
140 ExecCustomMarkPos(CustomScanState *node)
141 {
142         if (!node->methods->MarkPosCustomScan)
143                 ereport(ERROR,
144                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
145                                  errmsg("custom scan \"%s\" does not support MarkPos",
146                                                 node->methods->CustomName)));
147         node->methods->MarkPosCustomScan(node);
148 }
149
150 void
151 ExecCustomRestrPos(CustomScanState *node)
152 {
153         if (!node->methods->RestrPosCustomScan)
154                 ereport(ERROR,
155                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
156                                  errmsg("custom scan \"%s\" does not support MarkPos",
157                                                 node->methods->CustomName)));
158         node->methods->RestrPosCustomScan(node);
159 }
160
161 void
162 ExecCustomScanEstimate(CustomScanState *node, ParallelContext *pcxt)
163 {
164         const CustomExecMethods *methods = node->methods;
165
166         if (methods->EstimateDSMCustomScan)
167         {
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);
171         }
172 }
173
174 void
175 ExecCustomScanInitializeDSM(CustomScanState *node, ParallelContext *pcxt)
176 {
177         const CustomExecMethods *methods = node->methods;
178
179         if (methods->InitializeDSMCustomScan)
180         {
181                 int                     plan_node_id = node->ss.ps.plan->plan_node_id;
182                 void       *coordinate;
183
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);
187         }
188 }
189
190 void
191 ExecCustomScanReInitializeDSM(CustomScanState *node, ParallelContext *pcxt)
192 {
193         const CustomExecMethods *methods = node->methods;
194
195         if (methods->ReInitializeDSMCustomScan)
196         {
197                 int                     plan_node_id = node->ss.ps.plan->plan_node_id;
198                 void       *coordinate;
199
200                 coordinate = shm_toc_lookup(pcxt->toc, plan_node_id, false);
201                 methods->ReInitializeDSMCustomScan(node, pcxt, coordinate);
202         }
203 }
204
205 void
206 ExecCustomScanInitializeWorker(CustomScanState *node,
207                                                            ParallelWorkerContext *pwcxt)
208 {
209         const CustomExecMethods *methods = node->methods;
210
211         if (methods->InitializeWorkerCustomScan)
212         {
213                 int                     plan_node_id = node->ss.ps.plan->plan_node_id;
214                 void       *coordinate;
215
216                 coordinate = shm_toc_lookup(pwcxt->toc, plan_node_id, false);
217                 methods->InitializeWorkerCustomScan(node, pwcxt->toc, coordinate);
218         }
219 }
220
221 void
222 ExecShutdownCustomScan(CustomScanState *node)
223 {
224         const CustomExecMethods *methods = node->methods;
225
226         if (methods->ShutdownCustomScan)
227                 methods->ShutdownCustomScan(node);
228 }