PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
nodeMergeAppend.c File Reference
#include "postgres.h"
#include "executor/executor.h"
#include "executor/execPartition.h"
#include "executor/nodeMergeAppend.h"
#include "lib/binaryheap.h"
#include "miscadmin.h"
Include dependency graph for nodeMergeAppend.c:

Go to the source code of this file.

Typedefs

typedef int32 SlotNumber
 

Functions

static TupleTableSlotExecMergeAppend (PlanState *pstate)
 
static int heap_compare_slots (Datum a, Datum b, void *arg)
 
MergeAppendStateExecInitMergeAppend (MergeAppend *node, EState *estate, int eflags)
 
void ExecEndMergeAppend (MergeAppendState *node)
 
void ExecReScanMergeAppend (MergeAppendState *node)
 

Typedef Documentation

◆ SlotNumber

typedef int32 SlotNumber

Definition at line 52 of file nodeMergeAppend.c.

Function Documentation

◆ ExecEndMergeAppend()

void ExecEndMergeAppend ( MergeAppendState node)

Definition at line 334 of file nodeMergeAppend.c.

335{
336 PlanState **mergeplans;
337 int nplans;
338 int i;
339
340 /*
341 * get information from the node
342 */
343 mergeplans = node->mergeplans;
344 nplans = node->ms_nplans;
345
346 /*
347 * shut down each of the subscans
348 */
349 for (i = 0; i < nplans; i++)
350 ExecEndNode(mergeplans[i]);
351}
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:562
int i
Definition: isn.c:72
PlanState ** mergeplans
Definition: execnodes.h:1493

References ExecEndNode(), i, MergeAppendState::mergeplans, and MergeAppendState::ms_nplans.

Referenced by ExecEndNode().

◆ ExecInitMergeAppend()

MergeAppendState * ExecInitMergeAppend ( MergeAppend node,
EState estate,
int  eflags 
)

Definition at line 65 of file nodeMergeAppend.c.

66{
68 PlanState **mergeplanstates;
69 const TupleTableSlotOps *mergeops;
70 Bitmapset *validsubplans;
71 int nplans;
72 int i,
73 j;
74
75 /* check for unsupported flags */
77
78 /*
79 * create new MergeAppendState for our node
80 */
81 mergestate->ps.plan = (Plan *) node;
82 mergestate->ps.state = estate;
83 mergestate->ps.ExecProcNode = ExecMergeAppend;
84
85 /* If run-time partition pruning is enabled, then set that up now */
86 if (node->part_prune_info != NULL)
87 {
88 PartitionPruneState *prunestate;
89
90 /*
91 * Set up pruning data structure. This also initializes the set of
92 * subplans to initialize (validsubplans) by taking into account the
93 * result of performing initial pruning if any.
94 */
95 prunestate = ExecInitPartitionPruning(&mergestate->ps,
97 node->part_prune_info,
98 &validsubplans);
99 mergestate->ms_prune_state = prunestate;
100 nplans = bms_num_members(validsubplans);
101
102 /*
103 * When no run-time pruning is required and there's at least one
104 * subplan, we can fill ms_valid_subplans immediately, preventing
105 * later calls to ExecFindMatchingSubPlans.
106 */
107 if (!prunestate->do_exec_prune && nplans > 0)
108 mergestate->ms_valid_subplans = bms_add_range(NULL, 0, nplans - 1);
109 }
110 else
111 {
112 nplans = list_length(node->mergeplans);
113
114 /*
115 * When run-time partition pruning is not enabled we can just mark all
116 * subplans as valid; they must also all be initialized.
117 */
118 Assert(nplans > 0);
119 mergestate->ms_valid_subplans = validsubplans =
120 bms_add_range(NULL, 0, nplans - 1);
121 mergestate->ms_prune_state = NULL;
122 }
123
124 mergeplanstates = (PlanState **) palloc(nplans * sizeof(PlanState *));
125 mergestate->mergeplans = mergeplanstates;
126 mergestate->ms_nplans = nplans;
127
128 mergestate->ms_slots = (TupleTableSlot **) palloc0(sizeof(TupleTableSlot *) * nplans);
129 mergestate->ms_heap = binaryheap_allocate(nplans, heap_compare_slots,
130 mergestate);
131
132 /*
133 * call ExecInitNode on each of the valid plans to be executed and save
134 * the results into the mergeplanstates array.
135 */
136 j = 0;
137 i = -1;
138 while ((i = bms_next_member(validsubplans, i)) >= 0)
139 {
140 Plan *initNode = (Plan *) list_nth(node->mergeplans, i);
141
142 mergeplanstates[j++] = ExecInitNode(initNode, estate, eflags);
143 }
144
145 /*
146 * Initialize MergeAppend's result tuple type and slot. If the child
147 * plans all produce the same fixed slot type, we can use that slot type;
148 * otherwise make a virtual slot. (Note that the result slot itself is
149 * used only to return a null tuple at end of execution; real tuples are
150 * returned to the caller in the children's own result slots. What we are
151 * doing here is allowing the parent plan node to optimize if the
152 * MergeAppend will return only one kind of slot.)
153 */
154 mergeops = ExecGetCommonSlotOps(mergeplanstates, j);
155 if (mergeops != NULL)
156 {
157 ExecInitResultTupleSlotTL(&mergestate->ps, mergeops);
158 }
159 else
160 {
162 /* show that the output slot type is not fixed */
163 mergestate->ps.resultopsset = true;
164 mergestate->ps.resultopsfixed = false;
165 }
166
167 /*
168 * Miscellaneous initialization
169 */
170 mergestate->ps.ps_ProjInfo = NULL;
171
172 /*
173 * initialize sort-key information
174 */
175 mergestate->ms_nkeys = node->numCols;
176 mergestate->ms_sortkeys = palloc0(sizeof(SortSupportData) * node->numCols);
177
178 for (i = 0; i < node->numCols; i++)
179 {
180 SortSupport sortKey = mergestate->ms_sortkeys + i;
181
183 sortKey->ssup_collation = node->collations[i];
184 sortKey->ssup_nulls_first = node->nullsFirst[i];
185 sortKey->ssup_attno = node->sortColIdx[i];
186
187 /*
188 * It isn't feasible to perform abbreviated key conversion, since
189 * tuples are pulled into mergestate's binary heap as needed. It
190 * would likely be counter-productive to convert tuples into an
191 * abbreviated representation as they're pulled up, so opt out of that
192 * additional optimization entirely.
193 */
194 sortKey->abbreviate = false;
195
196 PrepareSortSupportFromOrderingOp(node->sortOperators[i], sortKey);
197 }
198
199 /*
200 * initialize to show we have not run the subplans yet
201 */
202 mergestate->ms_initialized = false;
203
204 return mergestate;
205}
binaryheap * binaryheap_allocate(int capacity, binaryheap_comparator compare, void *arg)
Definition: binaryheap.c:39
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1306
Bitmapset * bms_add_range(Bitmapset *a, int lower, int upper)
Definition: bitmapset.c:1019
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:751
#define Assert(condition)
Definition: c.h:812
PartitionPruneState * ExecInitPartitionPruning(PlanState *planstate, int n_total_subplans, PartitionPruneInfo *pruneinfo, Bitmapset **initially_valid_subplans)
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:142
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:84
void ExecInitResultTupleSlotTL(PlanState *planstate, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1986
const TupleTableSlotOps * ExecGetCommonSlotOps(PlanState **planstates, int nplans)
Definition: execUtils.c:536
#define EXEC_FLAG_BACKWARD
Definition: executor.h:68
#define EXEC_FLAG_MARK
Definition: executor.h:69
int j
Definition: isn.c:73
void * palloc0(Size size)
Definition: mcxt.c:1347
void * palloc(Size size)
Definition: mcxt.c:1317
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
static int heap_compare_slots(Datum a, Datum b, void *arg)
static TupleTableSlot * ExecMergeAppend(PlanState *pstate)
#define makeNode(_type_)
Definition: nodes.h:155
static int list_length(const List *l)
Definition: pg_list.h:152
static void * list_nth(const List *list, int n)
Definition: pg_list.h:299
void PrepareSortSupportFromOrderingOp(Oid orderingOp, SortSupport ssup)
Definition: sortsupport.c:134
SortSupport ms_sortkeys
Definition: execnodes.h:1496
Bitmapset * ms_valid_subplans
Definition: execnodes.h:1501
PlanState ps
Definition: execnodes.h:1492
struct binaryheap * ms_heap
Definition: execnodes.h:1498
TupleTableSlot ** ms_slots
Definition: execnodes.h:1497
struct PartitionPruneState * ms_prune_state
Definition: execnodes.h:1500
struct PartitionPruneInfo * part_prune_info
Definition: plannodes.h:315
List * mergeplans
Definition: plannodes.h:295
bool resultopsset
Definition: execnodes.h:1211
Plan * plan
Definition: execnodes.h:1126
EState * state
Definition: execnodes.h:1128
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:1166
bool resultopsfixed
Definition: execnodes.h:1207
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:1132
AttrNumber ssup_attno
Definition: sortsupport.h:81
bool ssup_nulls_first
Definition: sortsupport.h:75
MemoryContext ssup_cxt
Definition: sortsupport.h:66

References SortSupportData::abbreviate, Assert, binaryheap_allocate(), bms_add_range(), bms_next_member(), bms_num_members(), CurrentMemoryContext, PartitionPruneState::do_exec_prune, EXEC_FLAG_BACKWARD, EXEC_FLAG_MARK, ExecGetCommonSlotOps(), ExecInitNode(), ExecInitPartitionPruning(), ExecInitResultTupleSlotTL(), ExecMergeAppend(), PlanState::ExecProcNode, heap_compare_slots(), i, j, list_length(), list_nth(), makeNode, MergeAppendState::mergeplans, MergeAppend::mergeplans, MergeAppendState::ms_heap, MergeAppendState::ms_initialized, MergeAppendState::ms_nkeys, MergeAppendState::ms_nplans, MergeAppendState::ms_prune_state, MergeAppendState::ms_slots, MergeAppendState::ms_sortkeys, MergeAppendState::ms_valid_subplans, MergeAppend::numCols, palloc(), palloc0(), MergeAppend::part_prune_info, PlanState::plan, PrepareSortSupportFromOrderingOp(), MergeAppendState::ps, PlanState::ps_ProjInfo, PlanState::resultopsfixed, PlanState::resultopsset, SortSupportData::ssup_attno, SortSupportData::ssup_collation, SortSupportData::ssup_cxt, SortSupportData::ssup_nulls_first, PlanState::state, and TTSOpsVirtual.

Referenced by ExecInitNode().

◆ ExecMergeAppend()

static TupleTableSlot * ExecMergeAppend ( PlanState pstate)
static

Definition at line 214 of file nodeMergeAppend.c.

215{
217 TupleTableSlot *result;
219
221
222 if (!node->ms_initialized)
223 {
224 /* Nothing to do if all subplans were pruned */
225 if (node->ms_nplans == 0)
227
228 /*
229 * If we've yet to determine the valid subplans then do so now. If
230 * run-time pruning is disabled then the valid subplans will always be
231 * set to all subplans.
232 */
233 if (node->ms_valid_subplans == NULL)
234 node->ms_valid_subplans =
236
237 /*
238 * First time through: pull the first tuple from each valid subplan,
239 * and set up the heap.
240 */
241 i = -1;
242 while ((i = bms_next_member(node->ms_valid_subplans, i)) >= 0)
243 {
244 node->ms_slots[i] = ExecProcNode(node->mergeplans[i]);
245 if (!TupIsNull(node->ms_slots[i]))
247 }
249 node->ms_initialized = true;
250 }
251 else
252 {
253 /*
254 * Otherwise, pull the next tuple from whichever subplan we returned
255 * from last time, and reinsert the subplan index into the heap,
256 * because it might now compare differently against the existing
257 * elements of the heap. (We could perhaps simplify the logic a bit
258 * by doing this before returning from the prior call, but it's better
259 * to not pull tuples until necessary.)
260 */
262 node->ms_slots[i] = ExecProcNode(node->mergeplans[i]);
263 if (!TupIsNull(node->ms_slots[i]))
265 else
266 (void) binaryheap_remove_first(node->ms_heap);
267 }
268
269 if (binaryheap_empty(node->ms_heap))
270 {
271 /* All the subplans are exhausted, and so is the heap */
272 result = ExecClearTuple(node->ps.ps_ResultTupleSlot);
273 }
274 else
275 {
277 result = node->ms_slots[i];
278 }
279
280 return result;
281}
void binaryheap_build(binaryheap *heap)
Definition: binaryheap.c:138
void binaryheap_replace_first(binaryheap *heap, bh_node_type d)
Definition: binaryheap.c:255
bh_node_type binaryheap_first(binaryheap *heap)
Definition: binaryheap.c:177
bh_node_type binaryheap_remove_first(binaryheap *heap)
Definition: binaryheap.c:192
void binaryheap_add_unordered(binaryheap *heap, bh_node_type d)
Definition: binaryheap.c:116
#define binaryheap_empty(h)
Definition: binaryheap.h:65
Bitmapset * ExecFindMatchingSubPlans(PartitionPruneState *prunestate, bool initial_prune)
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition: executor.h:267
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
int32 SlotNumber
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:202
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1164
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:454
#define TupIsNull(slot)
Definition: tuptable.h:306

References binaryheap_add_unordered(), binaryheap_build(), binaryheap_empty, binaryheap_first(), binaryheap_remove_first(), binaryheap_replace_first(), bms_next_member(), castNode, CHECK_FOR_INTERRUPTS, DatumGetInt32(), ExecClearTuple(), ExecFindMatchingSubPlans(), ExecProcNode(), i, Int32GetDatum(), MergeAppendState::mergeplans, MergeAppendState::ms_heap, MergeAppendState::ms_initialized, MergeAppendState::ms_nplans, MergeAppendState::ms_prune_state, MergeAppendState::ms_slots, MergeAppendState::ms_valid_subplans, MergeAppendState::ps, PlanState::ps_ResultTupleSlot, and TupIsNull.

Referenced by ExecInitMergeAppend().

◆ ExecReScanMergeAppend()

void ExecReScanMergeAppend ( MergeAppendState node)

Definition at line 354 of file nodeMergeAppend.c.

355{
356 int i;
357
358 /*
359 * If any PARAM_EXEC Params used in pruning expressions have changed, then
360 * we'd better unset the valid subplans so that they are reselected for
361 * the new parameter values.
362 */
363 if (node->ms_prune_state &&
364 bms_overlap(node->ps.chgParam,
366 {
368 node->ms_valid_subplans = NULL;
369 }
370
371 for (i = 0; i < node->ms_nplans; i++)
372 {
373 PlanState *subnode = node->mergeplans[i];
374
375 /*
376 * ExecReScan doesn't know about my subplans, so I have to do
377 * changed-parameter signaling myself.
378 */
379 if (node->ps.chgParam != NULL)
380 UpdateChangedParamSet(subnode, node->ps.chgParam);
381
382 /*
383 * If chgParam of subnode is not null then plan will be re-scanned by
384 * first ExecProcNode.
385 */
386 if (subnode->chgParam == NULL)
387 ExecReScan(subnode);
388 }
390 node->ms_initialized = false;
391}
void binaryheap_reset(binaryheap *heap)
Definition: binaryheap.c:63
void bms_free(Bitmapset *a)
Definition: bitmapset.c:239
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:582
void ExecReScan(PlanState *node)
Definition: execAmi.c:76
void UpdateChangedParamSet(PlanState *node, Bitmapset *newchg)
Definition: execUtils.c:889
Bitmapset * execparamids
Bitmapset * chgParam
Definition: execnodes.h:1158

References binaryheap_reset(), bms_free(), bms_overlap(), PlanState::chgParam, PartitionPruneState::execparamids, ExecReScan(), i, MergeAppendState::mergeplans, MergeAppendState::ms_heap, MergeAppendState::ms_initialized, MergeAppendState::ms_nplans, MergeAppendState::ms_prune_state, MergeAppendState::ms_valid_subplans, MergeAppendState::ps, and UpdateChangedParamSet().

Referenced by ExecReScan().

◆ heap_compare_slots()

static int32 heap_compare_slots ( Datum  a,
Datum  b,
void *  arg 
)
static

Definition at line 287 of file nodeMergeAppend.c.

288{
290 SlotNumber slot1 = DatumGetInt32(a);
291 SlotNumber slot2 = DatumGetInt32(b);
292
293 TupleTableSlot *s1 = node->ms_slots[slot1];
294 TupleTableSlot *s2 = node->ms_slots[slot2];
295 int nkey;
296
299
300 for (nkey = 0; nkey < node->ms_nkeys; nkey++)
301 {
302 SortSupport sortKey = node->ms_sortkeys + nkey;
303 AttrNumber attno = sortKey->ssup_attno;
304 Datum datum1,
305 datum2;
306 bool isNull1,
307 isNull2;
308 int compare;
309
310 datum1 = slot_getattr(s1, attno, &isNull1);
311 datum2 = slot_getattr(s2, attno, &isNull2);
312
313 compare = ApplySortComparator(datum1, isNull1,
314 datum2, isNull2,
315 sortKey);
316 if (compare != 0)
317 {
319 return compare;
320 }
321 }
322 return 0;
323}
int16 AttrNumber
Definition: attnum.h:21
#define INVERT_COMPARE_RESULT(var)
Definition: c.h:1060
static int compare(const void *arg1, const void *arg2)
Definition: geqo_pool.c:145
int b
Definition: isn.c:69
int a
Definition: isn.c:68
void * arg
uintptr_t Datum
Definition: postgres.h:64
char * s1
char * s2
static int ApplySortComparator(Datum datum1, bool isNull1, Datum datum2, bool isNull2, SortSupport ssup)
Definition: sortsupport.h:200
static Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition: tuptable.h:395

References a, ApplySortComparator(), arg, Assert, b, compare(), DatumGetInt32(), INVERT_COMPARE_RESULT, MergeAppendState::ms_nkeys, MergeAppendState::ms_slots, MergeAppendState::ms_sortkeys, s1, s2, slot_getattr(), SortSupportData::ssup_attno, and TupIsNull.

Referenced by ExecInitMergeAppend().