PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
nodeSetOp.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "executor/executor.h"
#include "executor/nodeSetOp.h"
#include "utils/memutils.h"
Include dependency graph for nodeSetOp.c:

Go to the source code of this file.

Data Structures

struct  SetOpStatePerGroupData
 

Typedefs

typedef struct
SetOpStatePerGroupData 
SetOpStatePerGroupData
 

Functions

static TupleTableSlotsetop_retrieve_direct (SetOpState *setopstate)
 
static void setop_fill_hash_table (SetOpState *setopstate)
 
static TupleTableSlotsetop_retrieve_hash_table (SetOpState *setopstate)
 
static void initialize_counts (SetOpStatePerGroup pergroup)
 
static void advance_counts (SetOpStatePerGroup pergroup, int flag)
 
static int fetch_tuple_flag (SetOpState *setopstate, TupleTableSlot *inputslot)
 
static void build_hash_table (SetOpState *setopstate)
 
static void set_output_count (SetOpState *setopstate, SetOpStatePerGroup pergroup)
 
TupleTableSlotExecSetOp (SetOpState *node)
 
SetOpStateExecInitSetOp (SetOp *node, EState *estate, int eflags)
 
void ExecEndSetOp (SetOpState *node)
 
void ExecReScanSetOp (SetOpState *node)
 

Typedef Documentation

Function Documentation

static void advance_counts ( SetOpStatePerGroup  pergroup,
int  flag 
)
inlinestatic

Definition at line 88 of file nodeSetOp.c.

References SetOpStatePerGroupData::numLeft, and SetOpStatePerGroupData::numRight.

Referenced by setop_fill_hash_table(), and setop_retrieve_direct().

89 {
90  if (flag)
91  pergroup->numRight++;
92  else
93  pergroup->numLeft++;
94 }
char * flag(int b)
Definition: test-ctype.c:33
static void build_hash_table ( SetOpState setopstate)
static

Definition at line 119 of file nodeSetOp.c.

References Assert, BuildTupleHashTable(), SetOp::dupColIdx, SetOpState::eqfunctions, SetOpState::hashfunctions, SetOpState::hashtable, SetOp::numCols, SetOp::numGroups, PlanState::plan, SetOpState::ps, SETOP_HASHED, SetOp::strategy, SetOpState::tableContext, and SetOpState::tempContext.

Referenced by ExecInitSetOp(), and ExecReScanSetOp().

120 {
121  SetOp *node = (SetOp *) setopstate->ps.plan;
122 
123  Assert(node->strategy == SETOP_HASHED);
124  Assert(node->numGroups > 0);
125 
126  setopstate->hashtable = BuildTupleHashTable(node->numCols,
127  node->dupColIdx,
128  setopstate->eqfunctions,
129  setopstate->hashfunctions,
130  node->numGroups,
131  0,
132  setopstate->tableContext,
133  setopstate->tempContext,
134  false);
135 }
SetOpStrategy strategy
Definition: plannodes.h:816
MemoryContext tableContext
Definition: execnodes.h:2052
MemoryContext tempContext
Definition: execnodes.h:2046
long numGroups
Definition: plannodes.h:823
PlanState ps
Definition: execnodes.h:2041
AttrNumber * dupColIdx
Definition: plannodes.h:819
int numCols
Definition: plannodes.h:817
FmgrInfo * hashfunctions
Definition: execnodes.h:2043
Plan * plan
Definition: execnodes.h:1047
#define Assert(condition)
Definition: c.h:671
FmgrInfo * eqfunctions
Definition: execnodes.h:2042
TupleHashTable BuildTupleHashTable(int numCols, AttrNumber *keyColIdx, FmgrInfo *eqfunctions, FmgrInfo *hashfunctions, long nbuckets, Size additionalsize, MemoryContext tablecxt, MemoryContext tempcxt, bool use_variable_hash_iv)
Definition: execGrouping.c:290
TupleHashTable hashtable
Definition: execnodes.h:2051
void ExecEndSetOp ( SetOpState node)

Definition at line 575 of file nodeSetOp.c.

References ExecClearTuple(), ExecEndNode(), MemoryContextDelete(), outerPlanState, SetOpState::ps, PlanState::ps_ResultTupleSlot, SetOpState::tableContext, and SetOpState::tempContext.

Referenced by ExecEndNode().

576 {
577  /* clean up tuple table */
579 
580  /* free subsidiary stuff including hashtable */
582  if (node->tableContext)
584 
586 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
MemoryContext tableContext
Definition: execnodes.h:2052
MemoryContext tempContext
Definition: execnodes.h:2046
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:624
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
PlanState ps
Definition: execnodes.h:2041
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1077
#define outerPlanState(node)
Definition: execnodes.h:1090
SetOpState* ExecInitSetOp ( SetOp node,
EState estate,
int  eflags 
)

Definition at line 470 of file nodeSetOp.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), Assert, build_hash_table(), CurrentMemoryContext, SetOp::dupOperators, SetOpState::eqfunctions, EXEC_FLAG_BACKWARD, EXEC_FLAG_MARK, EXEC_FLAG_REWIND, ExecAssignResultTypeFromTL(), ExecInitNode(), ExecInitResultTupleSlot(), execTuplesHashPrepare(), execTuplesMatchPrepare(), SetOpState::grp_firstTuple, SetOpState::hashfunctions, SetOpState::hashtable, makeNode, NULL, SetOp::numCols, SetOpState::numOutput, outerPlan, outerPlanState, palloc0(), SetOpState::pergroup, PlanState::plan, SetOpState::ps, PlanState::ps_ProjInfo, SetOpState::setop_done, SETOP_HASHED, PlanState::state, SetOp::strategy, SetOpState::table_filled, SetOpState::tableContext, and SetOpState::tempContext.

Referenced by ExecInitNode().

471 {
472  SetOpState *setopstate;
473 
474  /* check for unsupported flags */
475  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
476 
477  /*
478  * create state structure
479  */
480  setopstate = makeNode(SetOpState);
481  setopstate->ps.plan = (Plan *) node;
482  setopstate->ps.state = estate;
483 
484  setopstate->eqfunctions = NULL;
485  setopstate->hashfunctions = NULL;
486  setopstate->setop_done = false;
487  setopstate->numOutput = 0;
488  setopstate->pergroup = NULL;
489  setopstate->grp_firstTuple = NULL;
490  setopstate->hashtable = NULL;
491  setopstate->tableContext = NULL;
492 
493  /*
494  * Miscellaneous initialization
495  *
496  * SetOp nodes have no ExprContext initialization because they never call
497  * ExecQual or ExecProject. But they do need a per-tuple memory context
498  * anyway for calling execTuplesMatch.
499  */
500  setopstate->tempContext =
502  "SetOp",
504 
505  /*
506  * If hashing, we also need a longer-lived context to store the hash
507  * table. The table can't just be kept in the per-query context because
508  * we want to be able to throw it away in ExecReScanSetOp.
509  */
510  if (node->strategy == SETOP_HASHED)
511  setopstate->tableContext =
513  "SetOp hash table",
515 
516  /*
517  * Tuple table initialization
518  */
519  ExecInitResultTupleSlot(estate, &setopstate->ps);
520 
521  /*
522  * initialize child nodes
523  *
524  * If we are hashing then the child plan does not need to handle REWIND
525  * efficiently; see ExecReScanSetOp.
526  */
527  if (node->strategy == SETOP_HASHED)
528  eflags &= ~EXEC_FLAG_REWIND;
529  outerPlanState(setopstate) = ExecInitNode(outerPlan(node), estate, eflags);
530 
531  /*
532  * setop nodes do no projections, so initialize projection info for this
533  * node appropriately
534  */
535  ExecAssignResultTypeFromTL(&setopstate->ps);
536  setopstate->ps.ps_ProjInfo = NULL;
537 
538  /*
539  * Precompute fmgr lookup data for inner loop. We need both equality and
540  * hashing functions to do it by hashing, but only equality if not
541  * hashing.
542  */
543  if (node->strategy == SETOP_HASHED)
545  node->dupOperators,
546  &setopstate->eqfunctions,
547  &setopstate->hashfunctions);
548  else
549  setopstate->eqfunctions =
551  node->dupOperators);
552 
553  if (node->strategy == SETOP_HASHED)
554  {
555  build_hash_table(setopstate);
556  setopstate->table_filled = false;
557  }
558  else
559  {
560  setopstate->pergroup =
562  }
563 
564  return setopstate;
565 }
SetOpStrategy strategy
Definition: plannodes.h:816
MemoryContext tableContext
Definition: execnodes.h:2052
MemoryContext tempContext
Definition: execnodes.h:2046
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:1079
struct SetOpStatePerGroupData * SetOpStatePerGroup
Definition: execnodes.h:2037
PlanState ps
Definition: execnodes.h:2041
HeapTuple grp_firstTuple
Definition: execnodes.h:2049
EState * state
Definition: execnodes.h:1049
int numCols
Definition: plannodes.h:817
void execTuplesHashPrepare(int numCols, Oid *eqOperators, FmgrInfo **eqFunctions, FmgrInfo **hashFunctions)
Definition: execGrouping.c:233
void ExecAssignResultTypeFromTL(PlanState *planstate)
Definition: execUtils.c:430
void ExecInitResultTupleSlot(EState *estate, PlanState *planstate)
Definition: execTuples.c:832
static void build_hash_table(SetOpState *setopstate)
Definition: nodeSetOp.c:119
Oid * dupOperators
Definition: plannodes.h:820
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:145
#define EXEC_FLAG_BACKWARD
Definition: executor.h:60
#define outerPlanState(node)
Definition: execnodes.h:1090
bool table_filled
Definition: execnodes.h:2053
long numOutput
Definition: execnodes.h:2045
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
#define EXEC_FLAG_REWIND
Definition: executor.h:59
#define outerPlan(node)
Definition: plannodes.h:159
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:440
void * palloc0(Size size)
Definition: mcxt.c:920
FmgrInfo * hashfunctions
Definition: execnodes.h:2043
Plan * plan
Definition: execnodes.h:1047
#define makeNode(_type_)
Definition: nodes.h:556
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
#define EXEC_FLAG_MARK
Definition: executor.h:61
bool setop_done
Definition: execnodes.h:2044
FmgrInfo * eqfunctions
Definition: execnodes.h:2042
SetOpStatePerGroup pergroup
Definition: execnodes.h:2048
FmgrInfo * execTuplesMatchPrepare(int numCols, Oid *eqOperators)
Definition: execGrouping.c:204
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:137
TupleHashTable hashtable
Definition: execnodes.h:2051
void ExecReScanSetOp ( SetOpState node)

Definition at line 590 of file nodeSetOp.c.

References build_hash_table(), PlanState::chgParam, ExecClearTuple(), ExecReScan(), SetOpState::grp_firstTuple, SetOpState::hashiter, SetOpState::hashtable, heap_freetuple(), PlanState::lefttree, MemoryContextResetAndDeleteChildren, NULL, SetOpState::numOutput, PlanState::plan, SetOpState::ps, PlanState::ps_ResultTupleSlot, ResetTupleHashIterator, SetOpState::setop_done, SETOP_HASHED, SetOpState::table_filled, and SetOpState::tableContext.

Referenced by ExecReScan().

591 {
593  node->setop_done = false;
594  node->numOutput = 0;
595 
596  if (((SetOp *) node->ps.plan)->strategy == SETOP_HASHED)
597  {
598  /*
599  * In the hashed case, if we haven't yet built the hash table then we
600  * can just return; nothing done yet, so nothing to undo. If subnode's
601  * chgParam is not NULL then it will be re-scanned by ExecProcNode,
602  * else no reason to re-scan it at all.
603  */
604  if (!node->table_filled)
605  return;
606 
607  /*
608  * If we do have the hash table and the subplan does not have any
609  * parameter changes, then we can just rescan the existing hash table;
610  * no need to build it again.
611  */
612  if (node->ps.lefttree->chgParam == NULL)
613  {
615  return;
616  }
617  }
618 
619  /* Release first tuple of group, if we have made a copy */
620  if (node->grp_firstTuple != NULL)
621  {
623  node->grp_firstTuple = NULL;
624  }
625 
626  /* Release any hashtable storage */
627  if (node->tableContext)
629 
630  /* And rebuild empty hashtable if needed */
631  if (((SetOp *) node->ps.plan)->strategy == SETOP_HASHED)
632  {
633  build_hash_table(node);
634  node->table_filled = false;
635  }
636 
637  /*
638  * if chgParam of subnode is not null then plan will be re-scanned by
639  * first ExecProcNode.
640  */
641  if (node->ps.lefttree->chgParam == NULL)
642  ExecReScan(node->ps.lefttree);
643 }
MemoryContext tableContext
Definition: execnodes.h:2052
void ExecReScan(PlanState *node)
Definition: execAmi.c:73
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
PlanState ps
Definition: execnodes.h:2041
HeapTuple grp_firstTuple
Definition: execnodes.h:2049
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
struct PlanState * lefttree
Definition: execnodes.h:1063
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1077
static void build_hash_table(SetOpState *setopstate)
Definition: nodeSetOp.c:119
bool table_filled
Definition: execnodes.h:2053
long numOutput
Definition: execnodes.h:2045
TupleHashIterator hashiter
Definition: execnodes.h:2054
Bitmapset * chgParam
Definition: execnodes.h:1072
#define MemoryContextResetAndDeleteChildren(ctx)
Definition: memutils.h:88
Plan * plan
Definition: execnodes.h:1047
#define ResetTupleHashIterator(htable, iter)
Definition: execnodes.h:558
#define NULL
Definition: c.h:226
bool setop_done
Definition: execnodes.h:2044
TupleHashTable hashtable
Definition: execnodes.h:2051
TupleTableSlot* ExecSetOp ( SetOpState node)

Definition at line 183 of file nodeSetOp.c.

References NULL, SetOpState::numOutput, PlanState::plan, SetOpState::ps, PlanState::ps_ResultTupleSlot, SetOpState::setop_done, setop_fill_hash_table(), SETOP_HASHED, setop_retrieve_direct(), setop_retrieve_hash_table(), SetOp::strategy, and SetOpState::table_filled.

Referenced by ExecProcNode().

184 {
185  SetOp *plannode = (SetOp *) node->ps.plan;
186  TupleTableSlot *resultTupleSlot = node->ps.ps_ResultTupleSlot;
187 
188  /*
189  * If the previously-returned tuple needs to be returned more than once,
190  * keep returning it.
191  */
192  if (node->numOutput > 0)
193  {
194  node->numOutput--;
195  return resultTupleSlot;
196  }
197 
198  /* Otherwise, we're done if we are out of groups */
199  if (node->setop_done)
200  return NULL;
201 
202  /* Fetch the next tuple group according to the correct strategy */
203  if (plannode->strategy == SETOP_HASHED)
204  {
205  if (!node->table_filled)
206  setop_fill_hash_table(node);
207  return setop_retrieve_hash_table(node);
208  }
209  else
210  return setop_retrieve_direct(node);
211 }
SetOpStrategy strategy
Definition: plannodes.h:816
PlanState ps
Definition: execnodes.h:2041
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1077
static void setop_fill_hash_table(SetOpState *setopstate)
Definition: nodeSetOp.c:331
bool table_filled
Definition: execnodes.h:2053
static TupleTableSlot * setop_retrieve_direct(SetOpState *setopstate)
Definition: nodeSetOp.c:217
long numOutput
Definition: execnodes.h:2045
static TupleTableSlot * setop_retrieve_hash_table(SetOpState *setopstate)
Definition: nodeSetOp.c:416
Plan * plan
Definition: execnodes.h:1047
#define NULL
Definition: c.h:226
bool setop_done
Definition: execnodes.h:2044
static int fetch_tuple_flag ( SetOpState setopstate,
TupleTableSlot inputslot 
)
static

Definition at line 101 of file nodeSetOp.c.

References Assert, DatumGetInt32, flag(), SetOp::flagColIdx, PlanState::plan, SetOpState::ps, and slot_getattr().

Referenced by setop_fill_hash_table(), and setop_retrieve_direct().

102 {
103  SetOp *node = (SetOp *) setopstate->ps.plan;
104  int flag;
105  bool isNull;
106 
107  flag = DatumGetInt32(slot_getattr(inputslot,
108  node->flagColIdx,
109  &isNull));
110  Assert(!isNull);
111  Assert(flag == 0 || flag == 1);
112  return flag;
113 }
#define DatumGetInt32(X)
Definition: postgres.h:480
PlanState ps
Definition: execnodes.h:2041
AttrNumber flagColIdx
Definition: plannodes.h:821
char * flag(int b)
Definition: test-ctype.c:33
Plan * plan
Definition: execnodes.h:1047
#define Assert(condition)
Definition: c.h:671
Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition: heaptuple.c:1143
static void initialize_counts ( SetOpStatePerGroup  pergroup)
inlinestatic

Definition at line 79 of file nodeSetOp.c.

References SetOpStatePerGroupData::numLeft, and SetOpStatePerGroupData::numRight.

Referenced by setop_fill_hash_table(), and setop_retrieve_direct().

80 {
81  pergroup->numLeft = pergroup->numRight = 0;
82 }
static void set_output_count ( SetOpState setopstate,
SetOpStatePerGroup  pergroup 
)
static

Definition at line 143 of file nodeSetOp.c.

References SetOp::cmd, elog, ERROR, SetOpStatePerGroupData::numLeft, SetOpState::numOutput, SetOpStatePerGroupData::numRight, PlanState::plan, SetOpState::ps, SETOPCMD_EXCEPT, SETOPCMD_EXCEPT_ALL, SETOPCMD_INTERSECT, and SETOPCMD_INTERSECT_ALL.

Referenced by setop_retrieve_direct(), and setop_retrieve_hash_table().

144 {
145  SetOp *plannode = (SetOp *) setopstate->ps.plan;
146 
147  switch (plannode->cmd)
148  {
149  case SETOPCMD_INTERSECT:
150  if (pergroup->numLeft > 0 && pergroup->numRight > 0)
151  setopstate->numOutput = 1;
152  else
153  setopstate->numOutput = 0;
154  break;
156  setopstate->numOutput =
157  (pergroup->numLeft < pergroup->numRight) ?
158  pergroup->numLeft : pergroup->numRight;
159  break;
160  case SETOPCMD_EXCEPT:
161  if (pergroup->numLeft > 0 && pergroup->numRight == 0)
162  setopstate->numOutput = 1;
163  else
164  setopstate->numOutput = 0;
165  break;
166  case SETOPCMD_EXCEPT_ALL:
167  setopstate->numOutput =
168  (pergroup->numLeft < pergroup->numRight) ?
169  0 : (pergroup->numLeft - pergroup->numRight);
170  break;
171  default:
172  elog(ERROR, "unrecognized set op: %d", (int) plannode->cmd);
173  break;
174  }
175 }
SetOpCmd cmd
Definition: plannodes.h:815
PlanState ps
Definition: execnodes.h:2041
#define ERROR
Definition: elog.h:43
long numOutput
Definition: execnodes.h:2045
Plan * plan
Definition: execnodes.h:1047
#define elog
Definition: elog.h:219
static void setop_fill_hash_table ( SetOpState setopstate)
static

Definition at line 331 of file nodeSetOp.c.

References TupleHashEntryData::additional, advance_counts(), Assert, SetOp::cmd, ExecProcNode(), fetch_tuple_flag(), SetOp::firstFlag, flag(), SetOpState::hashiter, SetOpState::hashtable, initialize_counts(), LookupTupleHashEntry(), MemoryContextAlloc(), MemoryContextReset(), NULL, outerPlan, outerPlanState, PG_USED_FOR_ASSERTS_ONLY, PlanState::plan, SetOpState::ps, ResetTupleHashIterator, SETOPCMD_INTERSECT, SETOPCMD_INTERSECT_ALL, SetOpState::table_filled, TupleHashTableData::tablecxt, SetOpState::tempContext, and TupIsNull.

Referenced by ExecSetOp().

332 {
333  SetOp *node = (SetOp *) setopstate->ps.plan;
335  int firstFlag;
336  bool in_first_rel PG_USED_FOR_ASSERTS_ONLY;
337 
338  /*
339  * get state info from node
340  */
341  outerPlan = outerPlanState(setopstate);
342  firstFlag = node->firstFlag;
343  /* verify planner didn't mess up */
344  Assert(firstFlag == 0 ||
345  (firstFlag == 1 &&
346  (node->cmd == SETOPCMD_INTERSECT ||
347  node->cmd == SETOPCMD_INTERSECT_ALL)));
348 
349  /*
350  * Process each outer-plan tuple, and then fetch the next one, until we
351  * exhaust the outer plan.
352  */
353  in_first_rel = true;
354  for (;;)
355  {
356  TupleTableSlot *outerslot;
357  int flag;
358  TupleHashEntryData *entry;
359  bool isnew;
360 
361  outerslot = ExecProcNode(outerPlan);
362  if (TupIsNull(outerslot))
363  break;
364 
365  /* Identify whether it's left or right input */
366  flag = fetch_tuple_flag(setopstate, outerslot);
367 
368  if (flag == firstFlag)
369  {
370  /* (still) in first input relation */
371  Assert(in_first_rel);
372 
373  /* Find or build hashtable entry for this tuple's group */
374  entry = LookupTupleHashEntry(setopstate->hashtable, outerslot,
375  &isnew);
376 
377  /* If new tuple group, initialize counts */
378  if (isnew)
379  {
380  entry->additional = (SetOpStatePerGroup)
382  sizeof(SetOpStatePerGroupData));
384  }
385 
386  /* Advance the counts */
388  }
389  else
390  {
391  /* reached second relation */
392  in_first_rel = false;
393 
394  /* For tuples not seen previously, do not make hashtable entry */
395  entry = LookupTupleHashEntry(setopstate->hashtable, outerslot,
396  NULL);
397 
398  /* Advance the counts if entry is already present */
399  if (entry)
401  }
402 
403  /* Must reset temp context after each hashtable lookup */
404  MemoryContextReset(setopstate->tempContext);
405  }
406 
407  setopstate->table_filled = true;
408  /* Initialize to walk the hash table */
409  ResetTupleHashIterator(setopstate->hashtable, &setopstate->hashiter);
410 }
TupleTableSlot * ExecProcNode(PlanState *node)
Definition: execProcnode.c:380
SetOpCmd cmd
Definition: plannodes.h:815
MemoryContext tempContext
Definition: execnodes.h:2046
struct SetOpStatePerGroupData * SetOpStatePerGroup
Definition: execnodes.h:2037
PlanState ps
Definition: execnodes.h:2041
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:135
static void initialize_counts(SetOpStatePerGroup pergroup)
Definition: nodeSetOp.c:79
#define outerPlanState(node)
Definition: execnodes.h:1090
MemoryContext tablecxt
Definition: execnodes.h:536
bool table_filled
Definition: execnodes.h:2053
char * flag(int b)
Definition: test-ctype.c:33
static int fetch_tuple_flag(SetOpState *setopstate, TupleTableSlot *inputslot)
Definition: nodeSetOp.c:101
#define TupIsNull(slot)
Definition: tuptable.h:138
TupleHashEntry LookupTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot, bool *isnew)
Definition: execGrouping.c:351
TupleHashIterator hashiter
Definition: execnodes.h:2054
#define outerPlan(node)
Definition: plannodes.h:159
Plan * plan
Definition: execnodes.h:1047
#define ResetTupleHashIterator(htable, iter)
Definition: execnodes.h:558
int firstFlag
Definition: plannodes.h:822
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:749
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:986
static void advance_counts(SetOpStatePerGroup pergroup, int flag)
Definition: nodeSetOp.c:88
TupleHashTable hashtable
Definition: execnodes.h:2051
static TupleTableSlot * setop_retrieve_direct ( SetOpState setopstate)
static

Definition at line 217 of file nodeSetOp.c.

References advance_counts(), SetOp::dupColIdx, SetOpState::eqfunctions, ExecClearTuple(), ExecCopySlotTuple(), ExecProcNode(), ExecStoreTuple(), execTuplesMatch(), fetch_tuple_flag(), SetOpState::grp_firstTuple, initialize_counts(), InvalidBuffer, NULL, SetOp::numCols, SetOpState::numOutput, outerPlan, outerPlanState, SetOpState::pergroup, PlanState::plan, SetOpState::ps, PlanState::ps_ResultTupleSlot, set_output_count(), SetOpState::setop_done, SetOpState::tempContext, and TupIsNull.

Referenced by ExecSetOp().

218 {
219  SetOp *node = (SetOp *) setopstate->ps.plan;
221  SetOpStatePerGroup pergroup;
222  TupleTableSlot *outerslot;
223  TupleTableSlot *resultTupleSlot;
224 
225  /*
226  * get state info from node
227  */
228  outerPlan = outerPlanState(setopstate);
229  pergroup = (SetOpStatePerGroup) setopstate->pergroup;
230  resultTupleSlot = setopstate->ps.ps_ResultTupleSlot;
231 
232  /*
233  * We loop retrieving groups until we find one we should return
234  */
235  while (!setopstate->setop_done)
236  {
237  /*
238  * If we don't already have the first tuple of the new group, fetch it
239  * from the outer plan.
240  */
241  if (setopstate->grp_firstTuple == NULL)
242  {
243  outerslot = ExecProcNode(outerPlan);
244  if (!TupIsNull(outerslot))
245  {
246  /* Make a copy of the first input tuple */
247  setopstate->grp_firstTuple = ExecCopySlotTuple(outerslot);
248  }
249  else
250  {
251  /* outer plan produced no tuples at all */
252  setopstate->setop_done = true;
253  return NULL;
254  }
255  }
256 
257  /*
258  * Store the copied first input tuple in the tuple table slot reserved
259  * for it. The tuple will be deleted when it is cleared from the
260  * slot.
261  */
262  ExecStoreTuple(setopstate->grp_firstTuple,
263  resultTupleSlot,
265  true);
266  setopstate->grp_firstTuple = NULL; /* don't keep two pointers */
267 
268  /* Initialize working state for a new input tuple group */
269  initialize_counts(pergroup);
270 
271  /* Count the first input tuple */
272  advance_counts(pergroup,
273  fetch_tuple_flag(setopstate, resultTupleSlot));
274 
275  /*
276  * Scan the outer plan until we exhaust it or cross a group boundary.
277  */
278  for (;;)
279  {
280  outerslot = ExecProcNode(outerPlan);
281  if (TupIsNull(outerslot))
282  {
283  /* no more outer-plan tuples available */
284  setopstate->setop_done = true;
285  break;
286  }
287 
288  /*
289  * Check whether we've crossed a group boundary.
290  */
291  if (!execTuplesMatch(resultTupleSlot,
292  outerslot,
293  node->numCols, node->dupColIdx,
294  setopstate->eqfunctions,
295  setopstate->tempContext))
296  {
297  /*
298  * Save the first input tuple of the next group.
299  */
300  setopstate->grp_firstTuple = ExecCopySlotTuple(outerslot);
301  break;
302  }
303 
304  /* Still in same group, so count this tuple */
305  advance_counts(pergroup,
306  fetch_tuple_flag(setopstate, outerslot));
307  }
308 
309  /*
310  * Done scanning input tuple group. See if we should emit any copies
311  * of result tuple, and if so return the first copy.
312  */
313  set_output_count(setopstate, pergroup);
314 
315  if (setopstate->numOutput > 0)
316  {
317  setopstate->numOutput--;
318  return resultTupleSlot;
319  }
320  }
321 
322  /* No more groups */
323  ExecClearTuple(resultTupleSlot);
324  return NULL;
325 }
TupleTableSlot * ExecStoreTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer, bool shouldFree)
Definition: execTuples.c:320
TupleTableSlot * ExecProcNode(PlanState *node)
Definition: execProcnode.c:380
MemoryContext tempContext
Definition: execnodes.h:2046
struct SetOpStatePerGroupData * SetOpStatePerGroup
Definition: execnodes.h:2037
static void set_output_count(SetOpState *setopstate, SetOpStatePerGroup pergroup)
Definition: nodeSetOp.c:143
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
PlanState ps
Definition: execnodes.h:2041
#define InvalidBuffer
Definition: buf.h:25
bool execTuplesMatch(TupleTableSlot *slot1, TupleTableSlot *slot2, int numCols, AttrNumber *matchColIdx, FmgrInfo *eqfunctions, MemoryContext evalContext)
Definition: execGrouping.c:69
AttrNumber * dupColIdx
Definition: plannodes.h:819
HeapTuple grp_firstTuple
Definition: execnodes.h:2049
int numCols
Definition: plannodes.h:817
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1077
static void initialize_counts(SetOpStatePerGroup pergroup)
Definition: nodeSetOp.c:79
#define outerPlanState(node)
Definition: execnodes.h:1090
static int fetch_tuple_flag(SetOpState *setopstate, TupleTableSlot *inputslot)
Definition: nodeSetOp.c:101
long numOutput
Definition: execnodes.h:2045
#define TupIsNull(slot)
Definition: tuptable.h:138
#define outerPlan(node)
Definition: plannodes.h:159
HeapTuple ExecCopySlotTuple(TupleTableSlot *slot)
Definition: execTuples.c:545
Plan * plan
Definition: execnodes.h:1047
#define NULL
Definition: c.h:226
bool setop_done
Definition: execnodes.h:2044
FmgrInfo * eqfunctions
Definition: execnodes.h:2042
SetOpStatePerGroup pergroup
Definition: execnodes.h:2048
static void advance_counts(SetOpStatePerGroup pergroup, int flag)
Definition: nodeSetOp.c:88
static TupleTableSlot * setop_retrieve_hash_table ( SetOpState setopstate)
static

Definition at line 416 of file nodeSetOp.c.

References TupleHashEntryData::additional, ExecClearTuple(), ExecStoreMinimalTuple(), TupleHashEntryData::firstTuple, SetOpState::hashiter, SetOpState::hashtable, NULL, SetOpState::numOutput, SetOpState::ps, PlanState::ps_ResultTupleSlot, ScanTupleHashTable, set_output_count(), and SetOpState::setop_done.

Referenced by ExecSetOp().

417 {
418  TupleHashEntryData *entry;
419  TupleTableSlot *resultTupleSlot;
420 
421  /*
422  * get state info from node
423  */
424  resultTupleSlot = setopstate->ps.ps_ResultTupleSlot;
425 
426  /*
427  * We loop retrieving groups until we find one we should return
428  */
429  while (!setopstate->setop_done)
430  {
431  /*
432  * Find the next entry in the hash table
433  */
434  entry = ScanTupleHashTable(setopstate->hashtable, &setopstate->hashiter);
435  if (entry == NULL)
436  {
437  /* No more entries in hashtable, so done */
438  setopstate->setop_done = true;
439  return NULL;
440  }
441 
442  /*
443  * See if we should emit any copies of this tuple, and if so return
444  * the first copy.
445  */
446  set_output_count(setopstate, (SetOpStatePerGroup) entry->additional);
447 
448  if (setopstate->numOutput > 0)
449  {
450  setopstate->numOutput--;
451  return ExecStoreMinimalTuple(entry->firstTuple,
452  resultTupleSlot,
453  false);
454  }
455  }
456 
457  /* No more groups */
458  ExecClearTuple(resultTupleSlot);
459  return NULL;
460 }
#define ScanTupleHashTable(htable, iter)
Definition: execnodes.h:560
TupleTableSlot * ExecStoreMinimalTuple(MinimalTuple mtup, TupleTableSlot *slot, bool shouldFree)
Definition: execTuples.c:384
static void set_output_count(SetOpState *setopstate, SetOpStatePerGroup pergroup)
Definition: nodeSetOp.c:143
MinimalTuple firstTuple
Definition: execnodes.h:515
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
PlanState ps
Definition: execnodes.h:2041
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1077
long numOutput
Definition: execnodes.h:2045
TupleHashIterator hashiter
Definition: execnodes.h:2054
#define NULL
Definition: c.h:226
bool setop_done
Definition: execnodes.h:2044
TupleHashTable hashtable
Definition: execnodes.h:2051