Age Owner Branch data TLA Line data Source code
1 : : /* ------------------------------------------------------------------------
2 : : *
3 : : * nodeCustom.c
4 : : * Routines to handle execution of custom scan node
5 : : *
6 : : * Portions Copyright (c) 1996-2024, 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 "miscadmin.h"
17 : : #include "nodes/execnodes.h"
18 : : #include "nodes/extensible.h"
19 : : #include "nodes/plannodes.h"
20 : : #include "utils/rel.h"
21 : :
22 : : static TupleTableSlot *ExecCustomScan(PlanState *pstate);
23 : :
24 : :
25 : : CustomScanState *
3446 rhaas@postgresql.org 26 :UBC 0 : ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags)
27 : : {
28 : : CustomScanState *css;
29 : : const TupleTableSlotOps *slotOps;
3262 tgl@sss.pgh.pa.us 30 : 0 : Relation scan_rel = NULL;
31 : 0 : Index scanrelid = cscan->scan.scanrelid;
32 : : int tlistvarno;
33 : :
34 : : /*
35 : : * Allocate the CustomScanState object. We let the custom scan provider
36 : : * do the palloc, in case it wants to make a larger object that embeds
37 : : * CustomScanState as the first field. It must set the node tag and the
38 : : * methods field correctly at this time. Other standard fields should be
39 : : * set to zero.
40 : : */
2635 andres@anarazel.de 41 : 0 : css = castNode(CustomScanState,
42 : : cscan->methods->CreateCustomScanState(cscan));
43 : :
44 : : /* ensure flags is filled correctly */
3262 tgl@sss.pgh.pa.us 45 : 0 : css->flags = cscan->flags;
46 : :
47 : : /* fill up fields of ScanState */
3446 rhaas@postgresql.org 48 : 0 : css->ss.ps.plan = &cscan->scan.plan;
49 : 0 : css->ss.ps.state = estate;
2463 andres@anarazel.de 50 : 0 : css->ss.ps.ExecProcNode = ExecCustomScan;
51 : :
52 : : /* create expression context for node */
3446 rhaas@postgresql.org 53 : 0 : ExecAssignExprContext(estate, &css->ss.ps);
54 : :
55 : : /*
56 : : * open the scan relation, if any
57 : : */
3262 tgl@sss.pgh.pa.us 58 [ # # ]: 0 : if (scanrelid > 0)
59 : : {
60 : 0 : scan_rel = ExecOpenScanRelation(estate, scanrelid, eflags);
3271 rhaas@postgresql.org 61 : 0 : css->ss.ss_currentRelation = scan_rel;
62 : : }
63 : :
64 : : /*
65 : : * Use a custom slot if specified in CustomScanState or use virtual slot
66 : : * otherwise.
67 : : */
507 akorotkov@postgresql 68 : 0 : slotOps = css->slotOps;
69 [ # # ]: 0 : if (!slotOps)
70 : 0 : slotOps = &TTSOpsVirtual;
71 : :
72 : : /*
73 : : * Determine the scan tuple type. If the custom scan provider provided a
74 : : * targetlist describing the scan tuples, use that; else use base
75 : : * relation's rowtype.
76 : : */
3262 tgl@sss.pgh.pa.us 77 [ # # # # ]: 0 : if (cscan->custom_scan_tlist != NIL || scan_rel == NULL)
3271 rhaas@postgresql.org 78 : 0 : {
79 : : TupleDesc scan_tupdesc;
80 : :
1972 andres@anarazel.de 81 : 0 : scan_tupdesc = ExecTypeFromTL(cscan->custom_scan_tlist);
507 akorotkov@postgresql 82 : 0 : ExecInitScanTupleSlot(estate, &css->ss, scan_tupdesc, slotOps);
83 : : /* Node's targetlist will contain Vars with varno = INDEX_VAR */
3262 tgl@sss.pgh.pa.us 84 : 0 : tlistvarno = INDEX_VAR;
85 : : }
86 : : else
87 : : {
1977 andres@anarazel.de 88 : 0 : ExecInitScanTupleSlot(estate, &css->ss, RelationGetDescr(scan_rel),
89 : : slotOps);
90 : : /* Node's targetlist will contain Vars with varno = scanrelid */
3262 tgl@sss.pgh.pa.us 91 : 0 : tlistvarno = scanrelid;
92 : : }
93 : :
94 : : /*
95 : : * Initialize result slot, type and projection.
96 : : */
1977 andres@anarazel.de 97 : 0 : ExecInitResultTupleSlotTL(&css->ss.ps, &TTSOpsVirtual);
3262 tgl@sss.pgh.pa.us 98 : 0 : ExecAssignScanProjectionInfoWithVarno(&css->ss, tlistvarno);
99 : :
100 : : /* initialize child expressions */
2249 andres@anarazel.de 101 : 0 : css->ss.ps.qual =
102 : 0 : ExecInitQual(cscan->scan.plan.qual, (PlanState *) css);
103 : :
104 : : /*
105 : : * The callback of custom-scan provider applies the final initialization
106 : : * of the custom-scan-state node according to its logic.
107 : : */
3446 rhaas@postgresql.org 108 : 0 : css->methods->BeginCustomScan(css, estate, eflags);
109 : :
110 : 0 : return css;
111 : : }
112 : :
113 : : static TupleTableSlot *
2463 andres@anarazel.de 114 : 0 : ExecCustomScan(PlanState *pstate)
115 : : {
116 : 0 : CustomScanState *node = castNode(CustomScanState, pstate);
117 : :
2455 118 [ # # ]: 0 : CHECK_FOR_INTERRUPTS();
119 : :
3446 rhaas@postgresql.org 120 [ # # ]: 0 : Assert(node->methods->ExecCustomScan != NULL);
121 : 0 : return node->methods->ExecCustomScan(node);
122 : : }
123 : :
124 : : void
125 : 0 : ExecEndCustomScan(CustomScanState *node)
126 : : {
127 [ # # ]: 0 : Assert(node->methods->EndCustomScan != NULL);
128 : 0 : node->methods->EndCustomScan(node);
129 : 0 : }
130 : :
131 : : void
132 : 0 : ExecReScanCustomScan(CustomScanState *node)
133 : : {
134 [ # # ]: 0 : Assert(node->methods->ReScanCustomScan != NULL);
135 : 0 : node->methods->ReScanCustomScan(node);
136 : 0 : }
137 : :
138 : : void
139 : 0 : ExecCustomMarkPos(CustomScanState *node)
140 : : {
141 [ # # ]: 0 : if (!node->methods->MarkPosCustomScan)
142 [ # # ]: 0 : ereport(ERROR,
143 : : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
144 : : errmsg("custom scan \"%s\" does not support MarkPos",
145 : : node->methods->CustomName)));
146 : 0 : node->methods->MarkPosCustomScan(node);
147 : 0 : }
148 : :
149 : : void
150 : 0 : ExecCustomRestrPos(CustomScanState *node)
151 : : {
152 [ # # ]: 0 : if (!node->methods->RestrPosCustomScan)
153 [ # # ]: 0 : ereport(ERROR,
154 : : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
155 : : errmsg("custom scan \"%s\" does not support MarkPos",
156 : : node->methods->CustomName)));
157 : 0 : node->methods->RestrPosCustomScan(node);
158 : 0 : }
159 : :
160 : : void
2993 161 : 0 : ExecCustomScanEstimate(CustomScanState *node, ParallelContext *pcxt)
162 : : {
163 : 0 : const CustomExecMethods *methods = node->methods;
164 : :
165 [ # # ]: 0 : if (methods->EstimateDSMCustomScan)
166 : : {
167 : 0 : node->pscan_len = methods->EstimateDSMCustomScan(node, pcxt);
168 : 0 : shm_toc_estimate_chunk(&pcxt->estimator, node->pscan_len);
169 : 0 : shm_toc_estimate_keys(&pcxt->estimator, 1);
170 : : }
171 : 0 : }
172 : :
173 : : void
174 : 0 : ExecCustomScanInitializeDSM(CustomScanState *node, ParallelContext *pcxt)
175 : : {
176 : 0 : const CustomExecMethods *methods = node->methods;
177 : :
178 [ # # ]: 0 : if (methods->InitializeDSMCustomScan)
179 : : {
180 : 0 : int plan_node_id = node->ss.ps.plan->plan_node_id;
181 : : void *coordinate;
182 : :
183 : 0 : coordinate = shm_toc_allocate(pcxt->toc, node->pscan_len);
184 : 0 : methods->InitializeDSMCustomScan(node, pcxt, coordinate);
185 : 0 : shm_toc_insert(pcxt->toc, plan_node_id, coordinate);
186 : : }
187 : 0 : }
188 : :
189 : : void
2419 tgl@sss.pgh.pa.us 190 : 0 : ExecCustomScanReInitializeDSM(CustomScanState *node, ParallelContext *pcxt)
191 : : {
192 : 0 : const CustomExecMethods *methods = node->methods;
193 : :
194 [ # # ]: 0 : if (methods->ReInitializeDSMCustomScan)
195 : : {
196 : 0 : int plan_node_id = node->ss.ps.plan->plan_node_id;
197 : : void *coordinate;
198 : :
199 : 0 : coordinate = shm_toc_lookup(pcxt->toc, plan_node_id, false);
200 : 0 : methods->ReInitializeDSMCustomScan(node, pcxt, coordinate);
201 : : }
202 : 0 : }
203 : :
204 : : void
2341 andres@anarazel.de 205 : 0 : ExecCustomScanInitializeWorker(CustomScanState *node,
206 : : ParallelWorkerContext *pwcxt)
207 : : {
2993 rhaas@postgresql.org 208 : 0 : const CustomExecMethods *methods = node->methods;
209 : :
210 [ # # ]: 0 : if (methods->InitializeWorkerCustomScan)
211 : : {
212 : 0 : int plan_node_id = node->ss.ps.plan->plan_node_id;
213 : : void *coordinate;
214 : :
2341 andres@anarazel.de 215 : 0 : coordinate = shm_toc_lookup(pwcxt->toc, plan_node_id, false);
216 : 0 : methods->InitializeWorkerCustomScan(node, pwcxt->toc, coordinate);
217 : : }
2993 rhaas@postgresql.org 218 : 0 : }
219 : :
220 : : void
2604 221 : 0 : ExecShutdownCustomScan(CustomScanState *node)
222 : : {
223 : 0 : const CustomExecMethods *methods = node->methods;
224 : :
225 [ # # ]: 0 : if (methods->ShutdownCustomScan)
226 : 0 : methods->ShutdownCustomScan(node);
227 : 0 : }
|