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

Definition at line 51 of file nodeMergeAppend.c.

Function Documentation

◆ ExecEndMergeAppend()

void ExecEndMergeAppend ( MergeAppendState node)

Definition at line 274 of file nodeMergeAppend.c.

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

Referenced by ExecEndNode().

275 {
276  PlanState **mergeplans;
277  int nplans;
278  int i;
279 
280  /*
281  * get information from the node
282  */
283  mergeplans = node->mergeplans;
284  nplans = node->ms_nplans;
285 
286  /*
287  * shut down each of the subscans
288  */
289  for (i = 0; i < nplans; i++)
290  ExecEndNode(mergeplans[i]);
291 }
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:538
PlanState ** mergeplans
Definition: execnodes.h:1114
int i

◆ ExecInitMergeAppend()

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

Definition at line 64 of file nodeMergeAppend.c.

References SortSupportData::abbreviate, Assert, binaryheap_allocate(), MergeAppend::collations, CurrentMemoryContext, EXEC_FLAG_BACKWARD, EXEC_FLAG_MARK, ExecInitNode(), ExecInitResultTupleSlotTL(), ExecLockNonLeafAppendTables(), ExecMergeAppend(), PlanState::ExecProcNode, heap_compare_slots(), i, lfirst, list_length(), makeNode, MergeAppend::mergeplans, MergeAppendState::mergeplans, MergeAppendState::ms_heap, MergeAppendState::ms_initialized, MergeAppendState::ms_nkeys, MergeAppendState::ms_nplans, MergeAppendState::ms_slots, MergeAppendState::ms_sortkeys, MergeAppend::nullsFirst, MergeAppend::numCols, palloc0(), MergeAppend::partitioned_rels, PlanState::plan, PrepareSortSupportFromOrderingOp(), MergeAppendState::ps, PlanState::ps_ProjInfo, MergeAppend::sortColIdx, MergeAppend::sortOperators, SortSupportData::ssup_attno, SortSupportData::ssup_collation, SortSupportData::ssup_cxt, SortSupportData::ssup_nulls_first, and PlanState::state.

Referenced by ExecInitNode().

65 {
67  PlanState **mergeplanstates;
68  int nplans;
69  int i;
70  ListCell *lc;
71 
72  /* check for unsupported flags */
73  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
74 
75  /*
76  * Lock the non-leaf tables in the partition tree controlled by this node.
77  * It's a no-op for non-partitioned parent tables.
78  */
80 
81  /*
82  * Set up empty vector of subplan states
83  */
84  nplans = list_length(node->mergeplans);
85 
86  mergeplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
87 
88  /*
89  * create new MergeAppendState for our node
90  */
91  mergestate->ps.plan = (Plan *) node;
92  mergestate->ps.state = estate;
93  mergestate->ps.ExecProcNode = ExecMergeAppend;
94  mergestate->mergeplans = mergeplanstates;
95  mergestate->ms_nplans = nplans;
96 
97  mergestate->ms_slots = (TupleTableSlot **) palloc0(sizeof(TupleTableSlot *) * nplans);
98  mergestate->ms_heap = binaryheap_allocate(nplans, heap_compare_slots,
99  mergestate);
100 
101  /*
102  * Miscellaneous initialization
103  *
104  * MergeAppend plans don't have expression contexts because they never
105  * call ExecQual or ExecProject.
106  */
107 
108  /*
109  * MergeAppend nodes do have Result slots, which hold pointers to tuples,
110  * so we have to initialize them.
111  */
112  ExecInitResultTupleSlotTL(estate, &mergestate->ps);
113 
114  /*
115  * call ExecInitNode on each of the plans to be executed and save the
116  * results into the array "mergeplans".
117  */
118  i = 0;
119  foreach(lc, node->mergeplans)
120  {
121  Plan *initNode = (Plan *) lfirst(lc);
122 
123  mergeplanstates[i] = ExecInitNode(initNode, estate, eflags);
124  i++;
125  }
126 
127  mergestate->ps.ps_ProjInfo = NULL;
128 
129  /*
130  * initialize sort-key information
131  */
132  mergestate->ms_nkeys = node->numCols;
133  mergestate->ms_sortkeys = palloc0(sizeof(SortSupportData) * node->numCols);
134 
135  for (i = 0; i < node->numCols; i++)
136  {
137  SortSupport sortKey = mergestate->ms_sortkeys + i;
138 
139  sortKey->ssup_cxt = CurrentMemoryContext;
140  sortKey->ssup_collation = node->collations[i];
141  sortKey->ssup_nulls_first = node->nullsFirst[i];
142  sortKey->ssup_attno = node->sortColIdx[i];
143 
144  /*
145  * It isn't feasible to perform abbreviated key conversion, since
146  * tuples are pulled into mergestate's binary heap as needed. It
147  * would likely be counter-productive to convert tuples into an
148  * abbreviated representation as they're pulled up, so opt out of that
149  * additional optimization entirely.
150  */
151  sortKey->abbreviate = false;
152 
154  }
155 
156  /*
157  * initialize to show we have not run the subplans yet
158  */
159  mergestate->ms_initialized = false;
160 
161  return mergestate;
162 }
bool ssup_nulls_first
Definition: sortsupport.h:75
void ExecLockNonLeafAppendTables(List *partitioned_rels, EState *estate)
Definition: execUtils.c:866
TupleTableSlot ** ms_slots
Definition: execnodes.h:1118
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:948
SortSupport ms_sortkeys
Definition: execnodes.h:1117
Oid * collations
Definition: plannodes.h:282
void PrepareSortSupportFromOrderingOp(Oid orderingOp, SortSupport ssup)
Definition: sortsupport.c:133
EState * state
Definition: execnodes.h:914
MemoryContext ssup_cxt
Definition: sortsupport.h:66
#define EXEC_FLAG_BACKWARD
Definition: executor.h:60
List * partitioned_rels
Definition: plannodes.h:276
PlanState ** mergeplans
Definition: execnodes.h:1114
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
void * palloc0(Size size)
Definition: mcxt.c:955
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:918
AttrNumber ssup_attno
Definition: sortsupport.h:81
void ExecInitResultTupleSlotTL(EState *estate, PlanState *planstate)
Definition: execTuples.c:890
Plan * plan
Definition: execnodes.h:912
PlanState ps
Definition: execnodes.h:1113
struct binaryheap * ms_heap
Definition: execnodes.h:1119
#define makeNode(_type_)
Definition: nodes.h:565
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
#define EXEC_FLAG_MARK
Definition: executor.h:61
AttrNumber * sortColIdx
Definition: plannodes.h:280
static int list_length(const List *l)
Definition: pg_list.h:89
bool * nullsFirst
Definition: plannodes.h:283
static int heap_compare_slots(Datum a, Datum b, void *arg)
binaryheap * binaryheap_allocate(int capacity, binaryheap_comparator compare, void *arg)
Definition: binaryheap.c:33
List * mergeplans
Definition: plannodes.h:277
int i
Oid * sortOperators
Definition: plannodes.h:281
static TupleTableSlot * ExecMergeAppend(PlanState *pstate)
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:139

◆ ExecMergeAppend()

static TupleTableSlot * ExecMergeAppend ( PlanState pstate)
static

Definition at line 171 of file nodeMergeAppend.c.

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

Referenced by ExecInitMergeAppend().

172 {
173  MergeAppendState *node = castNode(MergeAppendState, pstate);
174  TupleTableSlot *result;
175  SlotNumber i;
176 
178 
179  if (!node->ms_initialized)
180  {
181  /*
182  * First time through: pull the first tuple from each subplan, and set
183  * up the heap.
184  */
185  for (i = 0; i < node->ms_nplans; i++)
186  {
187  node->ms_slots[i] = ExecProcNode(node->mergeplans[i]);
188  if (!TupIsNull(node->ms_slots[i]))
190  }
191  binaryheap_build(node->ms_heap);
192  node->ms_initialized = true;
193  }
194  else
195  {
196  /*
197  * Otherwise, pull the next tuple from whichever subplan we returned
198  * from last time, and reinsert the subplan index into the heap,
199  * because it might now compare differently against the existing
200  * elements of the heap. (We could perhaps simplify the logic a bit
201  * by doing this before returning from the prior call, but it's better
202  * to not pull tuples until necessary.)
203  */
205  node->ms_slots[i] = ExecProcNode(node->mergeplans[i]);
206  if (!TupIsNull(node->ms_slots[i]))
208  else
209  (void) binaryheap_remove_first(node->ms_heap);
210  }
211 
212  if (binaryheap_empty(node->ms_heap))
213  {
214  /* All the subplans are exhausted, and so is the heap */
215  result = ExecClearTuple(node->ps.ps_ResultTupleSlot);
216  }
217  else
218  {
220  result = node->ms_slots[i];
221  }
222 
223  return result;
224 }
TupleTableSlot ** ms_slots
Definition: execnodes.h:1118
#define binaryheap_empty(h)
Definition: binaryheap.h:52
#define DatumGetInt32(X)
Definition: postgres.h:457
#define castNode(_type_, nodeptr)
Definition: nodes.h:586
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:475
void binaryheap_replace_first(binaryheap *heap, Datum d)
Definition: binaryheap.c:204
void binaryheap_add_unordered(binaryheap *heap, Datum d)
Definition: binaryheap.c:110
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:946
Datum binaryheap_first(binaryheap *heap)
Definition: binaryheap.c:159
PlanState ** mergeplans
Definition: execnodes.h:1114
int32 SlotNumber
#define TupIsNull(slot)
Definition: tuptable.h:146
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition: executor.h:233
PlanState ps
Definition: execnodes.h:1113
void binaryheap_build(binaryheap *heap)
Definition: binaryheap.c:126
struct binaryheap * ms_heap
Definition: execnodes.h:1119
#define Int32GetDatum(X)
Definition: postgres.h:464
int i
Datum binaryheap_remove_first(binaryheap *heap)
Definition: binaryheap.c:174
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98

◆ ExecReScanMergeAppend()

void ExecReScanMergeAppend ( MergeAppendState node)

Definition at line 294 of file nodeMergeAppend.c.

References binaryheap_reset(), PlanState::chgParam, ExecReScan(), i, MergeAppendState::mergeplans, MergeAppendState::ms_heap, MergeAppendState::ms_initialized, MergeAppendState::ms_nplans, MergeAppendState::ps, and UpdateChangedParamSet().

Referenced by ExecReScan().

295 {
296  int i;
297 
298  for (i = 0; i < node->ms_nplans; i++)
299  {
300  PlanState *subnode = node->mergeplans[i];
301 
302  /*
303  * ExecReScan doesn't know about my subplans, so I have to do
304  * changed-parameter signaling myself.
305  */
306  if (node->ps.chgParam != NULL)
307  UpdateChangedParamSet(subnode, node->ps.chgParam);
308 
309  /*
310  * If chgParam of subnode is not null then plan will be re-scanned by
311  * first ExecProcNode.
312  */
313  if (subnode->chgParam == NULL)
314  ExecReScan(subnode);
315  }
316  binaryheap_reset(node->ms_heap);
317  node->ms_initialized = false;
318 }
void ExecReScan(PlanState *node)
Definition: execAmi.c:76
PlanState ** mergeplans
Definition: execnodes.h:1114
void binaryheap_reset(binaryheap *heap)
Definition: binaryheap.c:57
Bitmapset * chgParam
Definition: execnodes.h:941
PlanState ps
Definition: execnodes.h:1113
void UpdateChangedParamSet(PlanState *node, Bitmapset *newchg)
Definition: execUtils.c:711
struct binaryheap * ms_heap
Definition: execnodes.h:1119
int i

◆ heap_compare_slots()

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

Definition at line 230 of file nodeMergeAppend.c.

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

Referenced by ExecInitMergeAppend().

231 {
233  SlotNumber slot1 = DatumGetInt32(a);
234  SlotNumber slot2 = DatumGetInt32(b);
235 
236  TupleTableSlot *s1 = node->ms_slots[slot1];
237  TupleTableSlot *s2 = node->ms_slots[slot2];
238  int nkey;
239 
240  Assert(!TupIsNull(s1));
241  Assert(!TupIsNull(s2));
242 
243  for (nkey = 0; nkey < node->ms_nkeys; nkey++)
244  {
245  SortSupport sortKey = node->ms_sortkeys + nkey;
246  AttrNumber attno = sortKey->ssup_attno;
247  Datum datum1,
248  datum2;
249  bool isNull1,
250  isNull2;
251  int compare;
252 
253  datum1 = slot_getattr(s1, attno, &isNull1);
254  datum2 = slot_getattr(s2, attno, &isNull2);
255 
256  compare = ApplySortComparator(datum1, isNull1,
257  datum2, isNull2,
258  sortKey);
259  if (compare != 0)
260  return -compare;
261  }
262  return 0;
263 }
TupleTableSlot ** ms_slots
Definition: execnodes.h:1118
SortSupport ms_sortkeys
Definition: execnodes.h:1117
#define DatumGetInt32(X)
Definition: postgres.h:457
static int compare(const void *arg1, const void *arg2)
Definition: geqo_pool.c:145
char * s1
int32 SlotNumber
#define TupIsNull(slot)
Definition: tuptable.h:146
char * s2
uintptr_t Datum
Definition: postgres.h:367
AttrNumber ssup_attno
Definition: sortsupport.h:81
#define Assert(condition)
Definition: c.h:699
Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition: heaptuple.c:1518
void * arg
static int ApplySortComparator(Datum datum1, bool isNull1, Datum datum2, bool isNull2, SortSupport ssup)
Definition: sortsupport.h:201
int16 AttrNumber
Definition: attnum.h:21