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