YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/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
}