/Users/deen/code/yugabyte-db/src/postgres/src/backend/executor/nodeCustom.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* ------------------------------------------------------------------------ |
2 | | * |
3 | | * nodeCustom.c |
4 | | * Routines to handle execution of custom scan node |
5 | | * |
6 | | * Portions Copyright (c) 1996-2018, 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 | 0 | { |
31 | 0 | CustomScanState *css; |
32 | 0 | Relation scan_rel = NULL; |
33 | 0 | Index scanrelid = cscan->scan.scanrelid; |
34 | 0 | 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 | 0 | 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 | | /* |
58 | | * open the base relation, if any, and acquire an appropriate lock on it |
59 | | */ |
60 | 0 | if (scanrelid > 0) |
61 | 0 | { |
62 | 0 | scan_rel = ExecOpenScanRelation(estate, scanrelid, eflags); |
63 | 0 | css->ss.ss_currentRelation = scan_rel; |
64 | 0 | } |
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 | 0 | if (cscan->custom_scan_tlist != NIL || scan_rel == NULL) |
72 | 0 | { |
73 | 0 | TupleDesc scan_tupdesc; |
74 | |
|
75 | 0 | scan_tupdesc = ExecTypeFromTL(cscan->custom_scan_tlist, false); |
76 | 0 | ExecInitScanTupleSlot(estate, &css->ss, scan_tupdesc); |
77 | | /* Node's targetlist will contain Vars with varno = INDEX_VAR */ |
78 | 0 | tlistvarno = INDEX_VAR; |
79 | 0 | } |
80 | 0 | else |
81 | 0 | { |
82 | 0 | ExecInitScanTupleSlot(estate, &css->ss, RelationGetDescr(scan_rel)); |
83 | | /* Node's targetlist will contain Vars with varno = scanrelid */ |
84 | 0 | tlistvarno = scanrelid; |
85 | 0 | } |
86 | | |
87 | | /* |
88 | | * Initialize result slot, type and projection. |
89 | | */ |
90 | 0 | ExecInitResultTupleSlotTL(&css->ss.ps); |
91 | 0 | ExecAssignScanProjectionInfoWithVarno(&css->ss, tlistvarno); |
92 | | |
93 | | /* initialize child expressions */ |
94 | 0 | css->ss.ps.qual = |
95 | 0 | ExecInitQual(cscan->scan.plan.qual, (PlanState *) css); |
96 | | |
97 | | /* |
98 | | * The callback of custom-scan provider applies the final initialization |
99 | | * of the custom-scan-state node according to its logic. |
100 | | */ |
101 | 0 | css->methods->BeginCustomScan(css, estate, eflags); |
102 | |
|
103 | 0 | return css; |
104 | 0 | } |
105 | | |
106 | | static TupleTableSlot * |
107 | | ExecCustomScan(PlanState *pstate) |
108 | 0 | { |
109 | 0 | CustomScanState *node = castNode(CustomScanState, pstate); |
110 | |
|
111 | 0 | CHECK_FOR_INTERRUPTS(); |
112 | |
|
113 | 0 | Assert(node->methods->ExecCustomScan != NULL); |
114 | 0 | return node->methods->ExecCustomScan(node); |
115 | 0 | } |
116 | | |
117 | | void |
118 | | ExecEndCustomScan(CustomScanState *node) |
119 | 0 | { |
120 | 0 | Assert(node->methods->EndCustomScan != NULL); |
121 | 0 | node->methods->EndCustomScan(node); |
122 | | |
123 | | /* Free the exprcontext */ |
124 | 0 | ExecFreeExprContext(&node->ss.ps); |
125 | | |
126 | | /* Clean out the tuple table */ |
127 | 0 | ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); |
128 | 0 | ExecClearTuple(node->ss.ss_ScanTupleSlot); |
129 | | |
130 | | /* Close the heap relation */ |
131 | 0 | if (node->ss.ss_currentRelation) |
132 | 0 | ExecCloseScanRelation(node->ss.ss_currentRelation); |
133 | 0 | } |
134 | | |
135 | | void |
136 | | ExecReScanCustomScan(CustomScanState *node) |
137 | 0 | { |
138 | 0 | Assert(node->methods->ReScanCustomScan != NULL); |
139 | 0 | node->methods->ReScanCustomScan(node); |
140 | 0 | } |
141 | | |
142 | | void |
143 | | ExecCustomMarkPos(CustomScanState *node) |
144 | 0 | { |
145 | 0 | if (!node->methods->MarkPosCustomScan) |
146 | 0 | ereport(ERROR, |
147 | 0 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
148 | 0 | errmsg("custom scan \"%s\" does not support MarkPos", |
149 | 0 | node->methods->CustomName))); |
150 | 0 | node->methods->MarkPosCustomScan(node); |
151 | 0 | } |
152 | | |
153 | | void |
154 | | ExecCustomRestrPos(CustomScanState *node) |
155 | 0 | { |
156 | 0 | if (!node->methods->RestrPosCustomScan) |
157 | 0 | ereport(ERROR, |
158 | 0 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
159 | 0 | errmsg("custom scan \"%s\" does not support MarkPos", |
160 | 0 | node->methods->CustomName))); |
161 | 0 | node->methods->RestrPosCustomScan(node); |
162 | 0 | } |
163 | | |
164 | | void |
165 | | ExecCustomScanEstimate(CustomScanState *node, ParallelContext *pcxt) |
166 | 0 | { |
167 | 0 | const CustomExecMethods *methods = node->methods; |
168 | |
|
169 | 0 | if (methods->EstimateDSMCustomScan) |
170 | 0 | { |
171 | 0 | node->pscan_len = methods->EstimateDSMCustomScan(node, pcxt); |
172 | 0 | shm_toc_estimate_chunk(&pcxt->estimator, node->pscan_len); |
173 | 0 | shm_toc_estimate_keys(&pcxt->estimator, 1); |
174 | 0 | } |
175 | 0 | } |
176 | | |
177 | | void |
178 | | ExecCustomScanInitializeDSM(CustomScanState *node, ParallelContext *pcxt) |
179 | 0 | { |
180 | 0 | const CustomExecMethods *methods = node->methods; |
181 | |
|
182 | 0 | if (methods->InitializeDSMCustomScan) |
183 | 0 | { |
184 | 0 | int plan_node_id = node->ss.ps.plan->plan_node_id; |
185 | 0 | void *coordinate; |
186 | |
|
187 | 0 | coordinate = shm_toc_allocate(pcxt->toc, node->pscan_len); |
188 | 0 | methods->InitializeDSMCustomScan(node, pcxt, coordinate); |
189 | 0 | shm_toc_insert(pcxt->toc, plan_node_id, coordinate); |
190 | 0 | } |
191 | 0 | } |
192 | | |
193 | | void |
194 | | ExecCustomScanReInitializeDSM(CustomScanState *node, ParallelContext *pcxt) |
195 | 0 | { |
196 | 0 | const CustomExecMethods *methods = node->methods; |
197 | |
|
198 | 0 | if (methods->ReInitializeDSMCustomScan) |
199 | 0 | { |
200 | 0 | int plan_node_id = node->ss.ps.plan->plan_node_id; |
201 | 0 | void *coordinate; |
202 | |
|
203 | 0 | coordinate = shm_toc_lookup(pcxt->toc, plan_node_id, false); |
204 | 0 | methods->ReInitializeDSMCustomScan(node, pcxt, coordinate); |
205 | 0 | } |
206 | 0 | } |
207 | | |
208 | | void |
209 | | ExecCustomScanInitializeWorker(CustomScanState *node, |
210 | | ParallelWorkerContext *pwcxt) |
211 | 0 | { |
212 | 0 | const CustomExecMethods *methods = node->methods; |
213 | |
|
214 | 0 | if (methods->InitializeWorkerCustomScan) |
215 | 0 | { |
216 | 0 | int plan_node_id = node->ss.ps.plan->plan_node_id; |
217 | 0 | void *coordinate; |
218 | |
|
219 | 0 | coordinate = shm_toc_lookup(pwcxt->toc, plan_node_id, false); |
220 | 0 | methods->InitializeWorkerCustomScan(node, pwcxt->toc, coordinate); |
221 | 0 | } |
222 | 0 | } |
223 | | |
224 | | void |
225 | | ExecShutdownCustomScan(CustomScanState *node) |
226 | 0 | { |
227 | 0 | const CustomExecMethods *methods = node->methods; |
228 | |
|
229 | 0 | if (methods->ShutdownCustomScan) |
230 | 0 | methods->ShutdownCustomScan(node); |
231 | 0 | } |