PostgreSQL Source Code  git master
tlist.h File Reference
#include "nodes/pathnodes.h"
Include dependency graph for tlist.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define create_pathtarget(root, tlist)   set_pathtarget_cost_width(root, make_pathtarget_from_tlist(tlist))
 

Functions

TargetEntrytlist_member (Expr *node, List *targetlist)
 
Listadd_to_flat_tlist (List *tlist, List *exprs)
 
Listget_tlist_exprs (List *tlist, bool includeJunk)
 
bool tlist_same_exprs (List *tlist1, List *tlist2)
 
bool tlist_same_datatypes (List *tlist, List *colTypes, bool junkOK)
 
bool tlist_same_collations (List *tlist, List *colCollations, bool junkOK)
 
void apply_tlist_labeling (List *dest_tlist, List *src_tlist)
 
Oidextract_grouping_ops (List *groupClause)
 
Oidextract_grouping_collations (List *groupClause, List *tlist)
 
AttrNumberextract_grouping_cols (List *groupClause, List *tlist)
 
bool grouping_is_sortable (List *groupClause)
 
bool grouping_is_hashable (List *groupClause)
 
PathTargetmake_pathtarget_from_tlist (List *tlist)
 
Listmake_tlist_from_pathtarget (PathTarget *target)
 
PathTargetcopy_pathtarget (PathTarget *src)
 
PathTargetcreate_empty_pathtarget (void)
 
void add_column_to_pathtarget (PathTarget *target, Expr *expr, Index sortgroupref)
 
void add_new_column_to_pathtarget (PathTarget *target, Expr *expr)
 
void add_new_columns_to_pathtarget (PathTarget *target, List *exprs)
 
void apply_pathtarget_labeling_to_tlist (List *tlist, PathTarget *target)
 
void split_pathtarget_at_srfs (PlannerInfo *root, PathTarget *target, PathTarget *input_target, List **targets, List **targets_contain_srfs)
 

Macro Definition Documentation

◆ create_pathtarget

Function Documentation

◆ add_column_to_pathtarget()

void add_column_to_pathtarget ( PathTarget target,
Expr expr,
Index  sortgroupref 
)

Definition at line 684 of file tlist.c.

References PathTarget::exprs, PathTarget::has_volatile_expr, lappend(), list_length(), palloc0(), repalloc(), PathTarget::sortgrouprefs, VOLATILITY_NOVOLATILE, and VOLATILITY_UNKNOWN.

Referenced by add_new_column_to_pathtarget(), add_sp_item_to_pathtarget(), create_one_window_path(), make_group_input_target(), make_partial_grouping_target(), make_sort_input_target(), and make_window_input_target().

685 {
686  /* Updating the exprs list is easy ... */
687  target->exprs = lappend(target->exprs, expr);
688  /* ... the sortgroupref data, a bit less so */
689  if (target->sortgrouprefs)
690  {
691  int nexprs = list_length(target->exprs);
692 
693  /* This might look inefficient, but actually it's usually cheap */
694  target->sortgrouprefs = (Index *)
695  repalloc(target->sortgrouprefs, nexprs * sizeof(Index));
696  target->sortgrouprefs[nexprs - 1] = sortgroupref;
697  }
698  else if (sortgroupref)
699  {
700  /* Adding sortgroupref labeling to a previously unlabeled target */
701  int nexprs = list_length(target->exprs);
702 
703  target->sortgrouprefs = (Index *) palloc0(nexprs * sizeof(Index));
704  target->sortgrouprefs[nexprs - 1] = sortgroupref;
705  }
706 
707  /*
708  * Reset has_volatile_expr to UNKNOWN. We just leave it up to
709  * contain_volatile_functions to set this properly again. Technically we
710  * could save some effort here and just check the new Expr, but it seems
711  * better to keep the logic for setting this flag in one location rather
712  * than duplicating the logic here.
713  */
716 }
Index * sortgrouprefs
Definition: pathnodes.h:1103
List * lappend(List *list, void *datum)
Definition: list.c:336
List * exprs
Definition: pathnodes.h:1102
void * palloc0(Size size)
Definition: mcxt.c:1093
unsigned int Index
Definition: c.h:549
VolatileFunctionStatus has_volatile_expr
Definition: pathnodes.h:1106
static int list_length(const List *l)
Definition: pg_list.h:149
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1182

◆ add_new_column_to_pathtarget()

void add_new_column_to_pathtarget ( PathTarget target,
Expr expr 
)

Definition at line 730 of file tlist.c.

References add_column_to_pathtarget(), PathTarget::exprs, and list_member().

Referenced by add_new_columns_to_pathtarget().

731 {
732  if (!list_member(target->exprs, expr))
733  add_column_to_pathtarget(target, expr, 0);
734 }
void add_column_to_pathtarget(PathTarget *target, Expr *expr, Index sortgroupref)
Definition: tlist.c:684
bool list_member(const List *list, const void *datum)
Definition: list.c:628
List * exprs
Definition: pathnodes.h:1102

◆ add_new_columns_to_pathtarget()

void add_new_columns_to_pathtarget ( PathTarget target,
List exprs 
)

Definition at line 741 of file tlist.c.

References add_new_column_to_pathtarget(), and lfirst.

Referenced by make_group_input_target(), make_partial_grouping_target(), make_sort_input_target(), and make_window_input_target().

742 {
743  ListCell *lc;
744 
745  foreach(lc, exprs)
746  {
747  Expr *expr = (Expr *) lfirst(lc);
748 
749  add_new_column_to_pathtarget(target, expr);
750  }
751 }
#define lfirst(lc)
Definition: pg_list.h:169
void add_new_column_to_pathtarget(PathTarget *target, Expr *expr)
Definition: tlist.c:730

◆ add_to_flat_tlist()

List* add_to_flat_tlist ( List tlist,
List exprs 
)

Definition at line 121 of file tlist.c.

References copyObject, lappend(), lfirst, list_length(), makeTargetEntry(), and tlist_member().

Referenced by build_tlist_to_deparse(), and foreign_grouping_ok().

122 {
123  int next_resno = list_length(tlist) + 1;
124  ListCell *lc;
125 
126  foreach(lc, exprs)
127  {
128  Expr *expr = (Expr *) lfirst(lc);
129 
130  if (!tlist_member(expr, tlist))
131  {
132  TargetEntry *tle;
133 
134  tle = makeTargetEntry(copyObject(expr), /* copy needed?? */
135  next_resno++,
136  NULL,
137  false);
138  tlist = lappend(tlist, tle);
139  }
140  }
141  return tlist;
142 }
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:238
List * lappend(List *list, void *datum)
Definition: list.c:336
TargetEntry * tlist_member(Expr *node, List *targetlist)
Definition: tlist.c:68
#define lfirst(lc)
Definition: pg_list.h:169
static int list_length(const List *l)
Definition: pg_list.h:149
#define copyObject(obj)
Definition: nodes.h:655

◆ apply_pathtarget_labeling_to_tlist()

void apply_pathtarget_labeling_to_tlist ( List tlist,
PathTarget target 
)

Definition at line 763 of file tlist.c.

References elog, ERROR, PathTarget::exprs, i, IsA, lfirst, TargetEntry::ressortgroupref, PathTarget::sortgrouprefs, tlist_member(), and tlist_member_match_var().

Referenced by create_projection_plan(), and create_scan_plan().

764 {
765  int i;
766  ListCell *lc;
767 
768  /* Nothing to do if PathTarget has no sortgrouprefs data */
769  if (target->sortgrouprefs == NULL)
770  return;
771 
772  i = 0;
773  foreach(lc, target->exprs)
774  {
775  Expr *expr = (Expr *) lfirst(lc);
776  TargetEntry *tle;
777 
778  if (target->sortgrouprefs[i])
779  {
780  /*
781  * For Vars, use tlist_member_match_var's weakened matching rule;
782  * this allows us to deal with some cases where a set-returning
783  * function has been inlined, so that we now have more knowledge
784  * about what it returns than we did when the original Var was
785  * created. Otherwise, use regular equal() to find the matching
786  * TLE. (In current usage, only the Var case is actually needed;
787  * but it seems best to have sane behavior here for non-Vars too.)
788  */
789  if (expr && IsA(expr, Var))
790  tle = tlist_member_match_var((Var *) expr, tlist);
791  else
792  tle = tlist_member(expr, tlist);
793 
794  /*
795  * Complain if noplace for the sortgrouprefs label, or if we'd
796  * have to label a column twice. (The case where it already has
797  * the desired label probably can't happen, but we may as well
798  * allow for it.)
799  */
800  if (!tle)
801  elog(ERROR, "ORDER/GROUP BY expression not found in targetlist");
802  if (tle->ressortgroupref != 0 &&
803  tle->ressortgroupref != target->sortgrouprefs[i])
804  elog(ERROR, "targetlist item has multiple sortgroupref labels");
805 
806  tle->ressortgroupref = target->sortgrouprefs[i];
807  }
808  i++;
809  }
810 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
Definition: primnodes.h:186
#define ERROR
Definition: elog.h:46
Index * sortgrouprefs
Definition: pathnodes.h:1103
List * exprs
Definition: pathnodes.h:1102
TargetEntry * tlist_member(Expr *node, List *targetlist)
Definition: tlist.c:68
static TargetEntry * tlist_member_match_var(Var *var, List *targetlist)
Definition: tlist.c:91
#define lfirst(lc)
Definition: pg_list.h:169
#define elog(elevel,...)
Definition: elog.h:232
int i
Index ressortgroupref
Definition: primnodes.h:1447

◆ apply_tlist_labeling()

void apply_tlist_labeling ( List dest_tlist,
List src_tlist 
)

Definition at line 307 of file tlist.c.

References Assert, forboth, lfirst, list_length(), TargetEntry::resjunk, TargetEntry::resname, TargetEntry::resno, TargetEntry::resorigcol, TargetEntry::resorigtbl, and TargetEntry::ressortgroupref.

Referenced by clean_up_removed_plan_level(), create_modifytable_plan(), and create_plan().

308 {
309  ListCell *ld,
310  *ls;
311 
312  Assert(list_length(dest_tlist) == list_length(src_tlist));
313  forboth(ld, dest_tlist, ls, src_tlist)
314  {
315  TargetEntry *dest_tle = (TargetEntry *) lfirst(ld);
316  TargetEntry *src_tle = (TargetEntry *) lfirst(ls);
317 
318  Assert(dest_tle->resno == src_tle->resno);
319  dest_tle->resname = src_tle->resname;
320  dest_tle->ressortgroupref = src_tle->ressortgroupref;
321  dest_tle->resorigtbl = src_tle->resorigtbl;
322  dest_tle->resorigcol = src_tle->resorigcol;
323  dest_tle->resjunk = src_tle->resjunk;
324  }
325 }
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:446
Oid resorigtbl
Definition: primnodes.h:1449
char * resname
Definition: primnodes.h:1446
bool resjunk
Definition: primnodes.h:1451
AttrNumber resno
Definition: primnodes.h:1445
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
static int list_length(const List *l)
Definition: pg_list.h:149
AttrNumber resorigcol
Definition: primnodes.h:1450
Index ressortgroupref
Definition: primnodes.h:1447

◆ copy_pathtarget()

PathTarget* copy_pathtarget ( PathTarget src)

Definition at line 646 of file tlist.c.

References PathTarget::exprs, list_copy(), list_length(), makeNode, palloc(), and PathTarget::sortgrouprefs.

Referenced by apply_scanjoin_target_to_paths(), create_one_window_path(), create_partitionwise_grouping_paths(), and reparameterize_path_by_child().

647 {
649 
650  /* Copy scalar fields */
651  memcpy(dst, src, sizeof(PathTarget));
652  /* Shallow-copy the expression list */
653  dst->exprs = list_copy(src->exprs);
654  /* Duplicate sortgrouprefs if any (if not, the memcpy handled this) */
655  if (src->sortgrouprefs)
656  {
657  Size nbytes = list_length(src->exprs) * sizeof(Index);
658 
659  dst->sortgrouprefs = (Index *) palloc(nbytes);
660  memcpy(dst->sortgrouprefs, src->sortgrouprefs, nbytes);
661  }
662  return dst;
663 }
List * list_copy(const List *oldlist)
Definition: list.c:1418
Index * sortgrouprefs
Definition: pathnodes.h:1103
List * exprs
Definition: pathnodes.h:1102
unsigned int Index
Definition: c.h:549
#define makeNode(_type_)
Definition: nodes.h:587
size_t Size
Definition: c.h:540
static int list_length(const List *l)
Definition: pg_list.h:149
void * palloc(Size size)
Definition: mcxt.c:1062

◆ create_empty_pathtarget()

PathTarget* create_empty_pathtarget ( void  )

Definition at line 670 of file tlist.c.

References makeNode.

Referenced by build_child_join_rel(), build_join_rel(), build_simple_rel(), fetch_upper_rel(), make_group_input_target(), make_partial_grouping_target(), make_sort_input_target(), make_window_input_target(), and split_pathtarget_at_srfs().

671 {
672  /* This is easy, but we don't want callers to hard-wire this ... */
673  return makeNode(PathTarget);
674 }
#define makeNode(_type_)
Definition: nodes.h:587

◆ extract_grouping_collations()

Oid* extract_grouping_collations ( List groupClause,
List tlist 
)

Definition at line 478 of file tlist.c.

References TargetEntry::expr, exprCollation(), get_sortgroupclause_tle(), lfirst, list_length(), and palloc().

Referenced by create_agg_plan(), create_group_plan(), and create_groupingsets_plan().

479 {
480  int numCols = list_length(groupClause);
481  int colno = 0;
482  Oid *grpCollations;
483  ListCell *glitem;
484 
485  grpCollations = (Oid *) palloc(sizeof(Oid) * numCols);
486 
487  foreach(glitem, groupClause)
488  {
489  SortGroupClause *groupcl = (SortGroupClause *) lfirst(glitem);
490  TargetEntry *tle = get_sortgroupclause_tle(groupcl, tlist);
491 
492  grpCollations[colno++] = exprCollation((Node *) tle->expr);
493  }
494 
495  return grpCollations;
496 }
TargetEntry * get_sortgroupclause_tle(SortGroupClause *sgClause, List *targetList)
Definition: tlist.c:356
Definition: nodes.h:539
unsigned int Oid
Definition: postgres_ext.h:31
#define lfirst(lc)
Definition: pg_list.h:169
Expr * expr
Definition: primnodes.h:1444
static int list_length(const List *l)
Definition: pg_list.h:149
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:759
void * palloc(Size size)
Definition: mcxt.c:1062

◆ extract_grouping_cols()

AttrNumber* extract_grouping_cols ( List groupClause,
List tlist 
)

Definition at line 503 of file tlist.c.

References get_sortgroupclause_tle(), lfirst, list_length(), palloc(), and TargetEntry::resno.

Referenced by create_agg_plan(), and create_group_plan().

504 {
505  AttrNumber *grpColIdx;
506  int numCols = list_length(groupClause);
507  int colno = 0;
508  ListCell *glitem;
509 
510  grpColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
511 
512  foreach(glitem, groupClause)
513  {
514  SortGroupClause *groupcl = (SortGroupClause *) lfirst(glitem);
515  TargetEntry *tle = get_sortgroupclause_tle(groupcl, tlist);
516 
517  grpColIdx[colno++] = tle->resno;
518  }
519 
520  return grpColIdx;
521 }
TargetEntry * get_sortgroupclause_tle(SortGroupClause *sgClause, List *targetList)
Definition: tlist.c:356
AttrNumber resno
Definition: primnodes.h:1445
#define lfirst(lc)
Definition: pg_list.h:169
static int list_length(const List *l)
Definition: pg_list.h:149
void * palloc(Size size)
Definition: mcxt.c:1062
int16 AttrNumber
Definition: attnum.h:21

◆ extract_grouping_ops()

Oid* extract_grouping_ops ( List groupClause)

Definition at line 452 of file tlist.c.

References Assert, SortGroupClause::eqop, lfirst, list_length(), OidIsValid, and palloc().

Referenced by create_agg_plan(), create_group_plan(), and create_groupingsets_plan().

453 {
454  int numCols = list_length(groupClause);
455  int colno = 0;
456  Oid *groupOperators;
457  ListCell *glitem;
458 
459  groupOperators = (Oid *) palloc(sizeof(Oid) * numCols);
460 
461  foreach(glitem, groupClause)
462  {
463  SortGroupClause *groupcl = (SortGroupClause *) lfirst(glitem);
464 
465  groupOperators[colno] = groupcl->eqop;
466  Assert(OidIsValid(groupOperators[colno]));
467  colno++;
468  }
469 
470  return groupOperators;
471 }
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
static int list_length(const List *l)
Definition: pg_list.h:149
void * palloc(Size size)
Definition: mcxt.c:1062

◆ get_tlist_exprs()

List* get_tlist_exprs ( List tlist,
bool  includeJunk 
)

Definition at line 152 of file tlist.c.

References TargetEntry::expr, lappend(), lfirst, NIL, and TargetEntry::resjunk.

Referenced by recurse_set_operations().

153 {
154  List *result = NIL;
155  ListCell *l;
156 
157  foreach(l, tlist)
158  {
159  TargetEntry *tle = (TargetEntry *) lfirst(l);
160 
161  if (tle->resjunk && !includeJunk)
162  continue;
163 
164  result = lappend(result, tle->expr);
165  }
166  return result;
167 }
#define NIL
Definition: pg_list.h:65
bool resjunk
Definition: primnodes.h:1451
List * lappend(List *list, void *datum)
Definition: list.c:336
#define lfirst(lc)
Definition: pg_list.h:169
Expr * expr
Definition: primnodes.h:1444
Definition: pg_list.h:50

◆ grouping_is_hashable()

bool grouping_is_hashable ( List groupClause)

Definition at line 549 of file tlist.c.

References SortGroupClause::hashable, and lfirst.

Referenced by choose_hashed_setop(), create_distinct_paths(), create_grouping_paths(), and generate_recursion_path().

550 {
551  ListCell *glitem;
552 
553  foreach(glitem, groupClause)
554  {
555  SortGroupClause *groupcl = (SortGroupClause *) lfirst(glitem);
556 
557  if (!groupcl->hashable)
558  return false;
559  }
560  return true;
561 }
#define lfirst(lc)
Definition: pg_list.h:169

◆ grouping_is_sortable()

bool grouping_is_sortable ( List groupClause)

Definition at line 529 of file tlist.c.

References lfirst, OidIsValid, and SortGroupClause::sortop.

Referenced by adjust_foreign_grouping_path_cost(), choose_hashed_setop(), create_distinct_paths(), create_grouping_paths(), make_pathkeys_for_window(), and standard_qp_callback().

530 {
531  ListCell *glitem;
532 
533  foreach(glitem, groupClause)
534  {
535  SortGroupClause *groupcl = (SortGroupClause *) lfirst(glitem);
536 
537  if (!OidIsValid(groupcl->sortop))
538  return false;
539  }
540  return true;
541 }
#define OidIsValid(objectId)
Definition: c.h:710
#define lfirst(lc)
Definition: pg_list.h:169

◆ make_pathtarget_from_tlist()

PathTarget* make_pathtarget_from_tlist ( List tlist)

Definition at line 580 of file tlist.c.

References TargetEntry::expr, PathTarget::exprs, PathTarget::has_volatile_expr, i, lappend(), lfirst, list_length(), makeNode, palloc(), TargetEntry::ressortgroupref, PathTarget::sortgrouprefs, and VOLATILITY_UNKNOWN.

581 {
582  PathTarget *target = makeNode(PathTarget);
583  int i;
584  ListCell *lc;
585 
586  target->sortgrouprefs = (Index *) palloc(list_length(tlist) * sizeof(Index));
587 
588  i = 0;
589  foreach(lc, tlist)
590  {
591  TargetEntry *tle = (TargetEntry *) lfirst(lc);
592 
593  target->exprs = lappend(target->exprs, tle->expr);
594  target->sortgrouprefs[i] = tle->ressortgroupref;
595  i++;
596  }
597 
598  /*
599  * Mark volatility as unknown. The contain_volatile_functions function
600  * will determine if there are any volatile functions when called for the
601  * first time with this PathTarget.
602  */
604 
605  return target;
606 }
Index * sortgrouprefs
Definition: pathnodes.h:1103
List * lappend(List *list, void *datum)
Definition: list.c:336
List * exprs
Definition: pathnodes.h:1102
unsigned int Index
Definition: c.h:549
VolatileFunctionStatus has_volatile_expr
Definition: pathnodes.h:1106
#define makeNode(_type_)
Definition: nodes.h:587
#define lfirst(lc)
Definition: pg_list.h:169
Expr * expr
Definition: primnodes.h:1444
static int list_length(const List *l)
Definition: pg_list.h:149
void * palloc(Size size)
Definition: mcxt.c:1062
int i
Index ressortgroupref
Definition: primnodes.h:1447

◆ make_tlist_from_pathtarget()

List* make_tlist_from_pathtarget ( PathTarget target)

Definition at line 613 of file tlist.c.

References PathTarget::exprs, i, lappend(), lfirst, makeTargetEntry(), NIL, TargetEntry::ressortgroupref, and PathTarget::sortgrouprefs.

Referenced by set_subquery_pathlist().

614 {
615  List *tlist = NIL;
616  int i;
617  ListCell *lc;
618 
619  i = 0;
620  foreach(lc, target->exprs)
621  {
622  Expr *expr = (Expr *) lfirst(lc);
623  TargetEntry *tle;
624 
625  tle = makeTargetEntry(expr,
626  i + 1,
627  NULL,
628  false);
629  if (target->sortgrouprefs)
630  tle->ressortgroupref = target->sortgrouprefs[i];
631  tlist = lappend(tlist, tle);
632  i++;
633  }
634 
635  return tlist;
636 }
#define NIL
Definition: pg_list.h:65
Index * sortgrouprefs
Definition: pathnodes.h:1103
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:238
List * lappend(List *list, void *datum)
Definition: list.c:336
List * exprs
Definition: pathnodes.h:1102
#define lfirst(lc)
Definition: pg_list.h:169
int i
Index ressortgroupref
Definition: primnodes.h:1447
Definition: pg_list.h:50

◆ split_pathtarget_at_srfs()

void split_pathtarget_at_srfs ( PlannerInfo root,
PathTarget target,
PathTarget input_target,
List **  targets,
List **  targets_contain_srfs 
)

Definition at line 870 of file tlist.c.

References add_sp_item_to_pathtarget(), add_sp_items_to_pathtarget(), create_empty_pathtarget(), split_pathtarget_context::current_depth, split_pathtarget_context::current_input_srfs, split_pathtarget_context::current_input_vars, split_pathtarget_context::current_sgref, split_pathtarget_item::expr, PathTarget::exprs, for_each_cell, forthree, get_pathtarget_sortgroupref, split_pathtarget_context::input_target_exprs, IS_SRF_CALL, lappend(), lappend_int(), split_pathtarget_context::level_input_srfs, split_pathtarget_context::level_input_vars, split_pathtarget_context::level_srfs, lfirst, list_concat(), list_make1, list_make1_int, list_member(), list_nth_cell(), lnext(), NIL, set_pathtarget_cost_width(), and split_pathtarget_walker().

Referenced by grouping_planner().

873 {
874  split_pathtarget_context context;
875  int max_depth;
876  bool need_extra_projection;
877  List *prev_level_tlist;
878  int lci;
879  ListCell *lc,
880  *lc1,
881  *lc2,
882  *lc3;
883 
884  /*
885  * It's not unusual for planner.c to pass us two physically identical
886  * targets, in which case we can conclude without further ado that all
887  * expressions are available from the input. (The logic below would
888  * arrive at the same conclusion, but much more tediously.)
889  */
890  if (target == input_target)
891  {
892  *targets = list_make1(target);
893  *targets_contain_srfs = list_make1_int(false);
894  return;
895  }
896 
897  /* Pass any input_target exprs down to split_pathtarget_walker() */
898  context.input_target_exprs = input_target ? input_target->exprs : NIL;
899 
900  /*
901  * Initialize with empty level-zero lists, and no levels after that.
902  * (Note: we could dispense with representing level zero explicitly, since
903  * it will never receive any SRFs, but then we'd have to special-case that
904  * level when we get to building result PathTargets. Level zero describes
905  * the SRF-free PathTarget that will be given to the input plan node.)
906  */
907  context.level_srfs = list_make1(NIL);
908  context.level_input_vars = list_make1(NIL);
909  context.level_input_srfs = list_make1(NIL);
910 
911  /* Initialize data we'll accumulate across all the target expressions */
912  context.current_input_vars = NIL;
913  context.current_input_srfs = NIL;
914  max_depth = 0;
915  need_extra_projection = false;
916 
917  /* Scan each expression in the PathTarget looking for SRFs */
918  lci = 0;
919  foreach(lc, target->exprs)
920  {
921  Node *node = (Node *) lfirst(lc);
922 
923  /* Tell split_pathtarget_walker about this expr's sortgroupref */
924  context.current_sgref = get_pathtarget_sortgroupref(target, lci);
925  lci++;
926 
927  /*
928  * Find all SRFs and Vars (and Var-like nodes) in this expression, and
929  * enter them into appropriate lists within the context struct.
930  */
931  context.current_depth = 0;
932  split_pathtarget_walker(node, &context);
933 
934  /* An expression containing no SRFs is of no further interest */
935  if (context.current_depth == 0)
936  continue;
937 
938  /*
939  * Track max SRF nesting depth over the whole PathTarget. Also, if
940  * this expression establishes a new max depth, we no longer care
941  * whether previous expressions contained nested SRFs; we can handle
942  * any required projection for them in the final ProjectSet node.
943  */
944  if (max_depth < context.current_depth)
945  {
946  max_depth = context.current_depth;
947  need_extra_projection = false;
948  }
949 
950  /*
951  * If any maximum-depth SRF is not at the top level of its expression,
952  * we'll need an extra Result node to compute the top-level scalar
953  * expression.
954  */
955  if (max_depth == context.current_depth && !IS_SRF_CALL(node))
956  need_extra_projection = true;
957  }
958 
959  /*
960  * If we found no SRFs needing evaluation (maybe they were all present in
961  * input_target, or maybe they were all removed by const-simplification),
962  * then no ProjectSet is needed; fall out.
963  */
964  if (max_depth == 0)
965  {
966  *targets = list_make1(target);
967  *targets_contain_srfs = list_make1_int(false);
968  return;
969  }
970 
971  /*
972  * The Vars and SRF outputs needed at top level can be added to the last
973  * level_input lists if we don't need an extra projection step. If we do
974  * need one, add a SRF-free level to the lists.
975  */
976  if (need_extra_projection)
977  {
978  context.level_srfs = lappend(context.level_srfs, NIL);
979  context.level_input_vars = lappend(context.level_input_vars,
980  context.current_input_vars);
981  context.level_input_srfs = lappend(context.level_input_srfs,
982  context.current_input_srfs);
983  }
984  else
985  {
986  lc = list_nth_cell(context.level_input_vars, max_depth);
987  lfirst(lc) = list_concat(lfirst(lc), context.current_input_vars);
988  lc = list_nth_cell(context.level_input_srfs, max_depth);
989  lfirst(lc) = list_concat(lfirst(lc), context.current_input_srfs);
990  }
991 
992  /*
993  * Now construct the output PathTargets. The original target can be used
994  * as-is for the last one, but we need to construct a new SRF-free target
995  * representing what the preceding plan node has to emit, as well as a
996  * target for each intermediate ProjectSet node.
997  */
998  *targets = *targets_contain_srfs = NIL;
999  prev_level_tlist = NIL;
1000 
1001  forthree(lc1, context.level_srfs,
1002  lc2, context.level_input_vars,
1003  lc3, context.level_input_srfs)
1004  {
1005  List *level_srfs = (List *) lfirst(lc1);
1006  PathTarget *ntarget;
1007 
1008  if (lnext(context.level_srfs, lc1) == NULL)
1009  {
1010  ntarget = target;
1011  }
1012  else
1013  {
1014  ntarget = create_empty_pathtarget();
1015 
1016  /*
1017  * This target should actually evaluate any SRFs of the current
1018  * level, and it needs to propagate forward any Vars needed by
1019  * later levels, as well as SRFs computed earlier and needed by
1020  * later levels.
1021  */
1022  add_sp_items_to_pathtarget(ntarget, level_srfs);
1023  for_each_cell(lc, context.level_input_vars,
1024  lnext(context.level_input_vars, lc2))
1025  {
1026  List *input_vars = (List *) lfirst(lc);
1027 
1028  add_sp_items_to_pathtarget(ntarget, input_vars);
1029  }
1030  for_each_cell(lc, context.level_input_srfs,
1031  lnext(context.level_input_srfs, lc3))
1032  {
1033  List *input_srfs = (List *) lfirst(lc);
1034  ListCell *lcx;
1035 
1036  foreach(lcx, input_srfs)
1037  {
1038  split_pathtarget_item *item = lfirst(lcx);
1039 
1040  if (list_member(prev_level_tlist, item->expr))
1041  add_sp_item_to_pathtarget(ntarget, item);
1042  }
1043  }
1044  set_pathtarget_cost_width(root, ntarget);
1045  }
1046 
1047  /*
1048  * Add current target and does-it-compute-SRFs flag to output lists.
1049  */
1050  *targets = lappend(*targets, ntarget);
1051  *targets_contain_srfs = lappend_int(*targets_contain_srfs,
1052  (level_srfs != NIL));
1053 
1054  /* Remember this level's output for next pass */
1055  prev_level_tlist = ntarget->exprs;
1056  }
1057 }
PathTarget * create_empty_pathtarget(void)
Definition: tlist.c:670
#define NIL
Definition: pg_list.h:65
List * level_input_vars
Definition: tlist.c:41
PathTarget * set_pathtarget_cost_width(PlannerInfo *root, PathTarget *target)
Definition: costsize.c:5944
static void add_sp_item_to_pathtarget(PathTarget *target, split_pathtarget_item *item)
Definition: tlist.c:1191
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:322
static ListCell * list_nth_cell(const List *list, int n)
Definition: pg_list.h:256
#define for_each_cell(cell, lst, initcell)
Definition: pg_list.h:417
#define forthree(cell1, list1, cell2, list2, cell3, list3)
Definition: pg_list.h:491
Definition: nodes.h:539
List * list_concat(List *list1, const List *list2)
Definition: list.c:530
List * current_input_srfs
Definition: tlist.c:45
#define list_make1(x1)
Definition: pg_list.h:206
bool list_member(const List *list, const void *datum)
Definition: list.c:628
List * level_input_srfs
Definition: tlist.c:42
static void add_sp_items_to_pathtarget(PathTarget *target, List *items)
Definition: tlist.c:1237
#define list_make1_int(x1)
Definition: pg_list.h:221
List * lappend_int(List *list, int datum)
Definition: list.c:354
List * lappend(List *list, void *datum)
Definition: list.c:336
List * exprs
Definition: pathnodes.h:1102
#define get_pathtarget_sortgroupref(target, colno)
Definition: pathnodes.h:1111
List * input_target_exprs
Definition: tlist.c:38
#define lfirst(lc)
Definition: pg_list.h:169
#define IS_SRF_CALL(node)
Definition: optimizer.h:28
static bool split_pathtarget_walker(Node *node, split_pathtarget_context *context)
Definition: tlist.c:1066
Definition: pg_list.h:50
List * current_input_vars
Definition: tlist.c:44

◆ tlist_member()

TargetEntry* tlist_member ( Expr node,
List targetlist 
)

Definition at line 68 of file tlist.c.

References equal(), TargetEntry::expr, and lfirst.

Referenced by add_to_flat_tlist(), apply_pathtarget_labeling_to_tlist(), build_remote_returning(), create_unique_plan(), preprocess_targetlist(), rebuild_fdw_scan_tlist(), and search_indexed_tlist_for_non_var().

69 {
70  ListCell *temp;
71 
72  foreach(temp, targetlist)
73  {
74  TargetEntry *tlentry = (TargetEntry *) lfirst(temp);
75 
76  if (equal(node, tlentry->expr))
77  return tlentry;
78  }
79  return NULL;
80 }
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3113
#define lfirst(lc)
Definition: pg_list.h:169
Expr * expr
Definition: primnodes.h:1444

◆ tlist_same_collations()

bool tlist_same_collations ( List tlist,
List colCollations,
bool  junkOK 
)

Definition at line 271 of file tlist.c.

References TargetEntry::expr, exprCollation(), lfirst, lfirst_oid, list_head(), lnext(), and TargetEntry::resjunk.

Referenced by recurse_set_operations().

272 {
273  ListCell *l;
274  ListCell *curColColl = list_head(colCollations);
275 
276  foreach(l, tlist)
277  {
278  TargetEntry *tle = (TargetEntry *) lfirst(l);
279 
280  if (tle->resjunk)
281  {
282  if (!junkOK)
283  return false;
284  }
285  else
286  {
287  if (curColColl == NULL)
288  return false; /* tlist longer than colCollations */
289  if (exprCollation((Node *) tle->expr) != lfirst_oid(curColColl))
290  return false;
291  curColColl = lnext(colCollations, curColColl);
292  }
293  }
294  if (curColColl != NULL)
295  return false; /* tlist shorter than colCollations */
296  return true;
297 }
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:322
Definition: nodes.h:539
bool resjunk
Definition: primnodes.h:1451
static ListCell * list_head(const List *l)
Definition: pg_list.h:125
#define lfirst(lc)
Definition: pg_list.h:169
Expr * expr
Definition: primnodes.h:1444
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:759
#define lfirst_oid(lc)
Definition: pg_list.h:171

◆ tlist_same_datatypes()

bool tlist_same_datatypes ( List tlist,
List colTypes,
bool  junkOK 
)

Definition at line 237 of file tlist.c.

References TargetEntry::expr, exprType(), lfirst, lfirst_oid, list_head(), lnext(), and TargetEntry::resjunk.

Referenced by is_simple_union_all_recurse(), and recurse_set_operations().

238 {
239  ListCell *l;
240  ListCell *curColType = list_head(colTypes);
241 
242  foreach(l, tlist)
243  {
244  TargetEntry *tle = (TargetEntry *) lfirst(l);
245 
246  if (tle->resjunk)
247  {
248  if (!junkOK)
249  return false;
250  }
251  else
252  {
253  if (curColType == NULL)
254  return false; /* tlist longer than colTypes */
255  if (exprType((Node *) tle->expr) != lfirst_oid(curColType))
256  return false;
257  curColType = lnext(colTypes, curColType);
258  }
259  }
260  if (curColType != NULL)
261  return false; /* tlist shorter than colTypes */
262  return true;
263 }
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:322
Definition: nodes.h:539
bool resjunk
Definition: primnodes.h:1451
static ListCell * list_head(const List *l)
Definition: pg_list.h:125
#define lfirst(lc)
Definition: pg_list.h:169
Expr * expr
Definition: primnodes.h:1444
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
#define lfirst_oid(lc)
Definition: pg_list.h:171

◆ tlist_same_exprs()

bool tlist_same_exprs ( List tlist1,
List tlist2 
)

Definition at line 207 of file tlist.c.

References equal(), TargetEntry::expr, forboth, lfirst, and list_length().

Referenced by change_plan_targetlist(), and create_projection_plan().

208 {
209  ListCell *lc1,
210  *lc2;
211 
212  if (list_length(tlist1) != list_length(tlist2))
213  return false; /* not same length, so can't match */
214 
215  forboth(lc1, tlist1, lc2, tlist2)
216  {
217  TargetEntry *tle1 = (TargetEntry *) lfirst(lc1);
218  TargetEntry *tle2 = (TargetEntry *) lfirst(lc2);
219 
220  if (!equal(tle1->expr, tle2->expr))
221  return false;
222  }
223 
224  return true;
225 }
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:446
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3113
#define lfirst(lc)
Definition: pg_list.h:169
Expr * expr
Definition: primnodes.h:1444
static int list_length(const List *l)
Definition: pg_list.h:149