PostgreSQL Source Code  git master
nodeMergeAppend.c File Reference
#include "postgres.h"
#include "executor/execdebug.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 321 of file nodeMergeAppend.c.

322 {
323  PlanState **mergeplans;
324  int nplans;
325  int i;
326 
327  /*
328  * get information from the node
329  */
330  mergeplans = node->mergeplans;
331  nplans = node->ms_nplans;
332 
333  /*
334  * shut down each of the subscans
335  */
336  for (i = 0; i < nplans; i++)
337  ExecEndNode(mergeplans[i]);
338 }
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:557
int i
Definition: isn.c:73
PlanState ** mergeplans
Definition: execnodes.h:1374

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  Bitmapset *validsubplans;
70  int nplans;
71  int i,
72  j;
73 
74  /* check for unsupported flags */
75  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
76 
77  /*
78  * create new MergeAppendState for our node
79  */
80  mergestate->ps.plan = (Plan *) node;
81  mergestate->ps.state = estate;
82  mergestate->ps.ExecProcNode = ExecMergeAppend;
83 
84  /* If run-time partition pruning is enabled, then set that up now */
85  if (node->part_prune_index >= 0)
86  {
87  PartitionPruneState *prunestate;
88 
89  /*
90  * Set up pruning data structure. This also initializes the set of
91  * subplans to initialize (validsubplans) by taking into account the
92  * result of performing initial pruning if any.
93  */
94  prunestate = ExecInitPartitionPruning(&mergestate->ps,
95  list_length(node->mergeplans),
96  node->part_prune_index,
97  node->apprelids,
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  * Miscellaneous initialization
134  *
135  * MergeAppend nodes do have Result slots, which hold pointers to tuples,
136  * so we have to initialize them. FIXME
137  */
139 
140  /* node returns slots from each of its subnodes, therefore not fixed */
141  mergestate->ps.resultopsset = true;
142  mergestate->ps.resultopsfixed = false;
143 
144  /*
145  * call ExecInitNode on each of the valid plans to be executed and save
146  * the results into the mergeplanstates array.
147  */
148  j = 0;
149  i = -1;
150  while ((i = bms_next_member(validsubplans, i)) >= 0)
151  {
152  Plan *initNode = (Plan *) list_nth(node->mergeplans, i);
153 
154  mergeplanstates[j++] = ExecInitNode(initNode, estate, eflags);
155  }
156 
157  mergestate->ps.ps_ProjInfo = NULL;
158 
159  /*
160  * initialize sort-key information
161  */
162  mergestate->ms_nkeys = node->numCols;
163  mergestate->ms_sortkeys = palloc0(sizeof(SortSupportData) * node->numCols);
164 
165  for (i = 0; i < node->numCols; i++)
166  {
167  SortSupport sortKey = mergestate->ms_sortkeys + i;
168 
169  sortKey->ssup_cxt = CurrentMemoryContext;
170  sortKey->ssup_collation = node->collations[i];
171  sortKey->ssup_nulls_first = node->nullsFirst[i];
172  sortKey->ssup_attno = node->sortColIdx[i];
173 
174  /*
175  * It isn't feasible to perform abbreviated key conversion, since
176  * tuples are pulled into mergestate's binary heap as needed. It
177  * would likely be counter-productive to convert tuples into an
178  * abbreviated representation as they're pulled up, so opt out of that
179  * additional optimization entirely.
180  */
181  sortKey->abbreviate = false;
182 
183  PrepareSortSupportFromOrderingOp(node->sortOperators[i], sortKey);
184  }
185 
186  /*
187  * initialize to show we have not run the subplans yet
188  */
189  mergestate->ms_initialized = false;
190 
191  return mergestate;
192 }
binaryheap * binaryheap_allocate(int capacity, binaryheap_comparator compare, void *arg)
Definition: binaryheap.c:32
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1047
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:649
Bitmapset * bms_add_range(Bitmapset *a, int lower, int upper)
Definition: bitmapset.c:837
PartitionPruneState * ExecInitPartitionPruning(PlanState *planstate, int n_total_subplans, int part_prune_index, Bitmapset *root_parent_relids, Bitmapset **initially_valid_subplans)
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:142
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:83
void ExecInitResultTupleSlotTL(PlanState *planstate, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1799
#define EXEC_FLAG_BACKWARD
Definition: executor.h:58
#define EXEC_FLAG_MARK
Definition: executor.h:59
int j
Definition: isn.c:74
Assert(fmt[strlen(fmt) - 1] !='\n')
void * palloc0(Size size)
Definition: mcxt.c:1230
MemoryContext CurrentMemoryContext
Definition: mcxt.c:124
void * palloc(Size size)
Definition: mcxt.c:1199
static int heap_compare_slots(Datum a, Datum b, void *arg)
static TupleTableSlot * ExecMergeAppend(PlanState *pstate)
#define makeNode(_type_)
Definition: nodes.h:165
static int list_length(const List *l)
Definition: pg_list.h:150
static void * list_nth(const List *list, int n)
Definition: pg_list.h:297
void PrepareSortSupportFromOrderingOp(Oid orderingOp, SortSupport ssup)
Definition: sortsupport.c:135
SortSupport ms_sortkeys
Definition: execnodes.h:1377
Bitmapset * ms_valid_subplans
Definition: execnodes.h:1382
PlanState ps
Definition: execnodes.h:1373
struct binaryheap * ms_heap
Definition: execnodes.h:1379
TupleTableSlot ** ms_slots
Definition: execnodes.h:1378
struct PartitionPruneState * ms_prune_state
Definition: execnodes.h:1381
int part_prune_index
Definition: plannodes.h:312
Bitmapset * apprelids
Definition: plannodes.h:290
List * mergeplans
Definition: plannodes.h:292
bool resultopsset
Definition: execnodes.h:1114
Plan * plan
Definition: execnodes.h:1029
EState * state
Definition: execnodes.h:1031
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:1069
bool resultopsfixed
Definition: execnodes.h:1110
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:1035
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, MergeAppend::apprelids, Assert(), binaryheap_allocate(), bms_add_range(), bms_next_member(), bms_num_members(), CurrentMemoryContext, PartitionPruneState::do_exec_prune, EXEC_FLAG_BACKWARD, EXEC_FLAG_MARK, 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_index, 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 201 of file nodeMergeAppend.c.

202 {
203  MergeAppendState *node = castNode(MergeAppendState, pstate);
204  TupleTableSlot *result;
205  SlotNumber i;
206 
208 
209  if (!node->ms_initialized)
210  {
211  /* Nothing to do if all subplans were pruned */
212  if (node->ms_nplans == 0)
213  return ExecClearTuple(node->ps.ps_ResultTupleSlot);
214 
215  /*
216  * If we've yet to determine the valid subplans then do so now. If
217  * run-time pruning is disabled then the valid subplans will always be
218  * set to all subplans.
219  */
220  if (node->ms_valid_subplans == NULL)
221  node->ms_valid_subplans =
223 
224  /*
225  * First time through: pull the first tuple from each valid subplan,
226  * and set up the heap.
227  */
228  i = -1;
229  while ((i = bms_next_member(node->ms_valid_subplans, i)) >= 0)
230  {
231  node->ms_slots[i] = ExecProcNode(node->mergeplans[i]);
232  if (!TupIsNull(node->ms_slots[i]))
234  }
235  binaryheap_build(node->ms_heap);
236  node->ms_initialized = true;
237  }
238  else
239  {
240  /*
241  * Otherwise, pull the next tuple from whichever subplan we returned
242  * from last time, and reinsert the subplan index into the heap,
243  * because it might now compare differently against the existing
244  * elements of the heap. (We could perhaps simplify the logic a bit
245  * by doing this before returning from the prior call, but it's better
246  * to not pull tuples until necessary.)
247  */
249  node->ms_slots[i] = ExecProcNode(node->mergeplans[i]);
250  if (!TupIsNull(node->ms_slots[i]))
252  else
253  (void) binaryheap_remove_first(node->ms_heap);
254  }
255 
256  if (binaryheap_empty(node->ms_heap))
257  {
258  /* All the subplans are exhausted, and so is the heap */
259  result = ExecClearTuple(node->ps.ps_ResultTupleSlot);
260  }
261  else
262  {
264  result = node->ms_slots[i];
265  }
266 
267  return result;
268 }
void binaryheap_build(binaryheap *heap)
Definition: binaryheap.c:125
void binaryheap_add_unordered(binaryheap *heap, Datum d)
Definition: binaryheap.c:109
Datum binaryheap_remove_first(binaryheap *heap)
Definition: binaryheap.c:173
void binaryheap_replace_first(binaryheap *heap, Datum d)
Definition: binaryheap.c:207
Datum binaryheap_first(binaryheap *heap)
Definition: binaryheap.c:158
#define binaryheap_empty(h)
Definition: binaryheap.h:52
Bitmapset * ExecFindMatchingSubPlans(PartitionPruneState *prunestate, bool initial_prune)
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition: executor.h:254
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:121
int32 SlotNumber
#define castNode(_type_, nodeptr)
Definition: nodes.h:186
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:560
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:550
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1067
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:433
#define TupIsNull(slot)
Definition: tuptable.h:300

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 341 of file nodeMergeAppend.c.

342 {
343  int i;
344 
345  /*
346  * If any PARAM_EXEC Params used in pruning expressions have changed, then
347  * we'd better unset the valid subplans so that they are reselected for
348  * the new parameter values.
349  */
350  if (node->ms_prune_state &&
351  bms_overlap(node->ps.chgParam,
353  {
355  node->ms_valid_subplans = NULL;
356  }
357 
358  for (i = 0; i < node->ms_nplans; i++)
359  {
360  PlanState *subnode = node->mergeplans[i];
361 
362  /*
363  * ExecReScan doesn't know about my subplans, so I have to do
364  * changed-parameter signaling myself.
365  */
366  if (node->ps.chgParam != NULL)
367  UpdateChangedParamSet(subnode, node->ps.chgParam);
368 
369  /*
370  * If chgParam of subnode is not null then plan will be re-scanned by
371  * first ExecProcNode.
372  */
373  if (subnode->chgParam == NULL)
374  ExecReScan(subnode);
375  }
376  binaryheap_reset(node->ms_heap);
377  node->ms_initialized = false;
378 }
void binaryheap_reset(binaryheap *heap)
Definition: binaryheap.c:56
void bms_free(Bitmapset *a)
Definition: bitmapset.c:209
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:495
void ExecReScan(PlanState *node)
Definition: execAmi.c:78
void UpdateChangedParamSet(PlanState *node, Bitmapset *newchg)
Definition: execUtils.c:866
Bitmapset * execparamids
Bitmapset * chgParam
Definition: execnodes.h:1061

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 274 of file nodeMergeAppend.c.

275 {
277  SlotNumber slot1 = DatumGetInt32(a);
278  SlotNumber slot2 = DatumGetInt32(b);
279 
280  TupleTableSlot *s1 = node->ms_slots[slot1];
281  TupleTableSlot *s2 = node->ms_slots[slot2];
282  int nkey;
283 
284  Assert(!TupIsNull(s1));
285  Assert(!TupIsNull(s2));
286 
287  for (nkey = 0; nkey < node->ms_nkeys; nkey++)
288  {
289  SortSupport sortKey = node->ms_sortkeys + nkey;
290  AttrNumber attno = sortKey->ssup_attno;
291  Datum datum1,
292  datum2;
293  bool isNull1,
294  isNull2;
295  int compare;
296 
297  datum1 = slot_getattr(s1, attno, &isNull1);
298  datum2 = slot_getattr(s2, attno, &isNull2);
299 
300  compare = ApplySortComparator(datum1, isNull1,
301  datum2, isNull2,
302  sortKey);
303  if (compare != 0)
304  {
306  return compare;
307  }
308  }
309  return 0;
310 }
int16 AttrNumber
Definition: attnum.h:21
#define INVERT_COMPARE_RESULT(var)
Definition: c.h:1063
static int compare(const void *arg1, const void *arg2)
Definition: geqo_pool.c:145
int b
Definition: isn.c:70
int a
Definition: isn.c:69
void * arg
uintptr_t Datum
Definition: postgres.h:412
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:389

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().