PostgreSQL Source Code  git master
nodeCustom.c
Go to the documentation of this file.
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 
26 ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags)
27 {
28  CustomScanState *css;
29  const TupleTableSlotOps *slotOps;
30  Relation scan_rel = NULL;
31  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  */
42  cscan->methods->CreateCustomScanState(cscan));
43 
44  /* ensure flags is filled correctly */
45  css->flags = cscan->flags;
46 
47  /* fill up fields of ScanState */
48  css->ss.ps.plan = &cscan->scan.plan;
49  css->ss.ps.state = estate;
51 
52  /* create expression context for node */
53  ExecAssignExprContext(estate, &css->ss.ps);
54 
55  /*
56  * open the scan relation, if any
57  */
58  if (scanrelid > 0)
59  {
60  scan_rel = ExecOpenScanRelation(estate, scanrelid, eflags);
61  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  */
68  slotOps = css->slotOps;
69  if (!slotOps)
70  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  */
77  if (cscan->custom_scan_tlist != NIL || scan_rel == NULL)
78  {
79  TupleDesc scan_tupdesc;
80 
81  scan_tupdesc = ExecTypeFromTL(cscan->custom_scan_tlist);
82  ExecInitScanTupleSlot(estate, &css->ss, scan_tupdesc, slotOps);
83  /* Node's targetlist will contain Vars with varno = INDEX_VAR */
84  tlistvarno = INDEX_VAR;
85  }
86  else
87  {
88  ExecInitScanTupleSlot(estate, &css->ss, RelationGetDescr(scan_rel),
89  slotOps);
90  /* Node's targetlist will contain Vars with varno = scanrelid */
91  tlistvarno = scanrelid;
92  }
93 
94  /*
95  * Initialize result slot, type and projection.
96  */
98  ExecAssignScanProjectionInfoWithVarno(&css->ss, tlistvarno);
99 
100  /* initialize child expressions */
101  css->ss.ps.qual =
102  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  */
108  css->methods->BeginCustomScan(css, estate, eflags);
109 
110  return css;
111 }
112 
113 static TupleTableSlot *
115 {
116  CustomScanState *node = castNode(CustomScanState, pstate);
117 
119 
120  Assert(node->methods->ExecCustomScan != NULL);
121  return node->methods->ExecCustomScan(node);
122 }
123 
124 void
126 {
127  Assert(node->methods->EndCustomScan != NULL);
128  node->methods->EndCustomScan(node);
129 }
130 
131 void
133 {
134  Assert(node->methods->ReScanCustomScan != NULL);
135  node->methods->ReScanCustomScan(node);
136 }
137 
138 void
140 {
141  if (!node->methods->MarkPosCustomScan)
142  ereport(ERROR,
143  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
144  errmsg("custom scan \"%s\" does not support MarkPos",
145  node->methods->CustomName)));
146  node->methods->MarkPosCustomScan(node);
147 }
148 
149 void
151 {
152  if (!node->methods->RestrPosCustomScan)
153  ereport(ERROR,
154  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
155  errmsg("custom scan \"%s\" does not support MarkPos",
156  node->methods->CustomName)));
157  node->methods->RestrPosCustomScan(node);
158 }
159 
160 void
162 {
163  const CustomExecMethods *methods = node->methods;
164 
165  if (methods->EstimateDSMCustomScan)
166  {
167  node->pscan_len = methods->EstimateDSMCustomScan(node, pcxt);
169  shm_toc_estimate_keys(&pcxt->estimator, 1);
170  }
171 }
172 
173 void
175 {
176  const CustomExecMethods *methods = node->methods;
177 
178  if (methods->InitializeDSMCustomScan)
179  {
180  int plan_node_id = node->ss.ps.plan->plan_node_id;
181  void *coordinate;
182 
183  coordinate = shm_toc_allocate(pcxt->toc, node->pscan_len);
184  methods->InitializeDSMCustomScan(node, pcxt, coordinate);
185  shm_toc_insert(pcxt->toc, plan_node_id, coordinate);
186  }
187 }
188 
189 void
191 {
192  const CustomExecMethods *methods = node->methods;
193 
194  if (methods->ReInitializeDSMCustomScan)
195  {
196  int plan_node_id = node->ss.ps.plan->plan_node_id;
197  void *coordinate;
198 
199  coordinate = shm_toc_lookup(pcxt->toc, plan_node_id, false);
200  methods->ReInitializeDSMCustomScan(node, pcxt, coordinate);
201  }
202 }
203 
204 void
206  ParallelWorkerContext *pwcxt)
207 {
208  const CustomExecMethods *methods = node->methods;
209 
210  if (methods->InitializeWorkerCustomScan)
211  {
212  int plan_node_id = node->ss.ps.plan->plan_node_id;
213  void *coordinate;
214 
215  coordinate = shm_toc_lookup(pwcxt->toc, plan_node_id, false);
216  methods->InitializeWorkerCustomScan(node, pwcxt->toc, coordinate);
217  }
218 }
219 
220 void
222 {
223  const CustomExecMethods *methods = node->methods;
224 
225  if (methods->ShutdownCustomScan)
226  methods->ShutdownCustomScan(node);
227 }
#define Assert(condition)
Definition: c.h:861
unsigned int Index
Definition: c.h:617
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:224
void ExecAssignScanProjectionInfoWithVarno(ScanState *node, int varno)
Definition: execScan.c:283
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:84
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1898
void ExecInitResultTupleSlotTL(PlanState *planstate, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1886
TupleDesc ExecTypeFromTL(List *targetList)
Definition: execTuples.c:2025
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:483
Relation ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
Definition: execUtils.c:697
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
void ExecCustomScanInitializeDSM(CustomScanState *node, ParallelContext *pcxt)
Definition: nodeCustom.c:174
void ExecShutdownCustomScan(CustomScanState *node)
Definition: nodeCustom.c:221
void ExecCustomScanEstimate(CustomScanState *node, ParallelContext *pcxt)
Definition: nodeCustom.c:161
CustomScanState * ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags)
Definition: nodeCustom.c:26
void ExecCustomRestrPos(CustomScanState *node)
Definition: nodeCustom.c:150
void ExecReScanCustomScan(CustomScanState *node)
Definition: nodeCustom.c:132
void ExecCustomScanReInitializeDSM(CustomScanState *node, ParallelContext *pcxt)
Definition: nodeCustom.c:190
void ExecEndCustomScan(CustomScanState *node)
Definition: nodeCustom.c:125
void ExecCustomScanInitializeWorker(CustomScanState *node, ParallelWorkerContext *pwcxt)
Definition: nodeCustom.c:205
void ExecCustomMarkPos(CustomScanState *node)
Definition: nodeCustom.c:139
static TupleTableSlot * ExecCustomScan(PlanState *pstate)
Definition: nodeCustom.c:114
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
#define NIL
Definition: pg_list.h:68
#define INDEX_VAR
Definition: primnodes.h:238
#define RelationGetDescr(relation)
Definition: rel.h:531
void shm_toc_insert(shm_toc *toc, uint64 key, void *address)
Definition: shm_toc.c:171
void * shm_toc_allocate(shm_toc *toc, Size nbytes)
Definition: shm_toc.c:88
void * shm_toc_lookup(shm_toc *toc, uint64 key, bool noError)
Definition: shm_toc.c:232
#define shm_toc_estimate_chunk(e, sz)
Definition: shm_toc.h:51
#define shm_toc_estimate_keys(e, cnt)
Definition: shm_toc.h:53
void(* BeginCustomScan)(CustomScanState *node, EState *estate, int eflags)
Definition: extensible.h:129
TupleTableSlot *(* ExecCustomScan)(CustomScanState *node)
Definition: extensible.h:132
void(* EndCustomScan)(CustomScanState *node)
Definition: extensible.h:133
void(* ShutdownCustomScan)(CustomScanState *node)
Definition: extensible.h:152
const char * CustomName
Definition: extensible.h:126
void(* ReInitializeDSMCustomScan)(CustomScanState *node, ParallelContext *pcxt, void *coordinate)
Definition: extensible.h:146
void(* InitializeDSMCustomScan)(CustomScanState *node, ParallelContext *pcxt, void *coordinate)
Definition: extensible.h:143
void(* RestrPosCustomScan)(CustomScanState *node)
Definition: extensible.h:138
Size(* EstimateDSMCustomScan)(CustomScanState *node, ParallelContext *pcxt)
Definition: extensible.h:141
void(* MarkPosCustomScan)(CustomScanState *node)
Definition: extensible.h:137
void(* InitializeWorkerCustomScan)(CustomScanState *node, shm_toc *toc, void *coordinate)
Definition: extensible.h:149
void(* ReScanCustomScan)(CustomScanState *node)
Definition: extensible.h:134
Node *(* CreateCustomScanState)(CustomScan *cscan)
Definition: extensible.h:117
const struct TupleTableSlotOps * slotOps
Definition: execnodes.h:2103
const struct CustomExecMethods * methods
Definition: execnodes.h:2102
ScanState ss
Definition: execnodes.h:2097
uint32 flags
Definition: plannodes.h:743
List * custom_scan_tlist
Definition: plannodes.h:748
Scan scan
Definition: plannodes.h:742
const struct CustomScanMethods * methods
Definition: plannodes.h:756
shm_toc_estimator estimator
Definition: parallel.h:41
shm_toc * toc
Definition: parallel.h:44
ExprState * qual
Definition: execnodes.h:1144
Plan * plan
Definition: execnodes.h:1123
EState * state
Definition: execnodes.h:1125
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:1129
int plan_node_id
Definition: plannodes.h:152
Relation ss_currentRelation
Definition: execnodes.h:1571
PlanState ps
Definition: execnodes.h:1570
Index scanrelid
Definition: plannodes.h:390