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)
 
TargetEntrytlist_member_ignore_relabel (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 710 of file tlist.c.

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

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

711 {
712  /* Updating the exprs list is easy ... */
713  target->exprs = lappend(target->exprs, expr);
714  /* ... the sortgroupref data, a bit less so */
715  if (target->sortgrouprefs)
716  {
717  int nexprs = list_length(target->exprs);
718 
719  /* This might look inefficient, but actually it's usually cheap */
720  target->sortgrouprefs = (Index *)
721  repalloc(target->sortgrouprefs, nexprs * sizeof(Index));
722  target->sortgrouprefs[nexprs - 1] = sortgroupref;
723  }
724  else if (sortgroupref)
725  {
726  /* Adding sortgroupref labeling to a previously unlabeled target */
727  int nexprs = list_length(target->exprs);
728 
729  target->sortgrouprefs = (Index *) palloc0(nexprs * sizeof(Index));
730  target->sortgrouprefs[nexprs - 1] = sortgroupref;
731  }
732 }
Index * sortgrouprefs
Definition: pathnodes.h:1047
List * lappend(List *list, void *datum)
Definition: list.c:322
List * exprs
Definition: pathnodes.h:1046
void * palloc0(Size size)
Definition: mcxt.c:980
unsigned int Index
Definition: c.h:476
static int list_length(const List *l)
Definition: pg_list.h:169
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1069

◆ add_new_column_to_pathtarget()

void add_new_column_to_pathtarget ( PathTarget target,
Expr expr 
)

Definition at line 746 of file tlist.c.

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

Referenced by add_new_columns_to_pathtarget().

747 {
748  if (!list_member(target->exprs, expr))
749  add_column_to_pathtarget(target, expr, 0);
750 }
void add_column_to_pathtarget(PathTarget *target, Expr *expr, Index sortgroupref)
Definition: tlist.c:710
bool list_member(const List *list, const void *datum)
Definition: list.c:614
List * exprs
Definition: pathnodes.h:1046

◆ add_new_columns_to_pathtarget()

void add_new_columns_to_pathtarget ( PathTarget target,
List exprs 
)

Definition at line 757 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().

758 {
759  ListCell *lc;
760 
761  foreach(lc, exprs)
762  {
763  Expr *expr = (Expr *) lfirst(lc);
764 
765  add_new_column_to_pathtarget(target, expr);
766  }
767 }
#define lfirst(lc)
Definition: pg_list.h:190
void add_new_column_to_pathtarget(PathTarget *target, Expr *expr)
Definition: tlist.c:746

◆ add_to_flat_tlist()

List* add_to_flat_tlist ( List tlist,
List exprs 
)

Definition at line 154 of file tlist.c.

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

Referenced by build_tlist_to_deparse(), and foreign_grouping_ok().

155 {
156  int next_resno = list_length(tlist) + 1;
157  ListCell *lc;
158 
159  foreach(lc, exprs)
160  {
161  Expr *expr = (Expr *) lfirst(lc);
162 
163  if (!tlist_member(expr, tlist))
164  {
165  TargetEntry *tle;
166 
167  tle = makeTargetEntry(copyObject(expr), /* copy needed?? */
168  next_resno++,
169  NULL,
170  false);
171  tlist = lappend(tlist, tle);
172  }
173  }
174  return tlist;
175 }
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:236
List * lappend(List *list, void *datum)
Definition: list.c:322
TargetEntry * tlist_member(Expr *node, List *targetlist)
Definition: tlist.c:73
#define lfirst(lc)
Definition: pg_list.h:190
static int list_length(const List *l)
Definition: pg_list.h:169
#define copyObject(obj)
Definition: nodes.h:641

◆ apply_pathtarget_labeling_to_tlist()

void apply_pathtarget_labeling_to_tlist ( List tlist,
PathTarget target 
)

Definition at line 779 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().

780 {
781  int i;
782  ListCell *lc;
783 
784  /* Nothing to do if PathTarget has no sortgrouprefs data */
785  if (target->sortgrouprefs == NULL)
786  return;
787 
788  i = 0;
789  foreach(lc, target->exprs)
790  {
791  Expr *expr = (Expr *) lfirst(lc);
792  TargetEntry *tle;
793 
794  if (target->sortgrouprefs[i])
795  {
796  /*
797  * For Vars, use tlist_member_match_var's weakened matching rule;
798  * this allows us to deal with some cases where a set-returning
799  * function has been inlined, so that we now have more knowledge
800  * about what it returns than we did when the original Var was
801  * created. Otherwise, use regular equal() to find the matching
802  * TLE. (In current usage, only the Var case is actually needed;
803  * but it seems best to have sane behavior here for non-Vars too.)
804  */
805  if (expr && IsA(expr, Var))
806  tle = tlist_member_match_var((Var *) expr, tlist);
807  else
808  tle = tlist_member(expr, tlist);
809 
810  /*
811  * Complain if noplace for the sortgrouprefs label, or if we'd
812  * have to label a column twice. (The case where it already has
813  * the desired label probably can't happen, but we may as well
814  * allow for it.)
815  */
816  if (!tle)
817  elog(ERROR, "ORDER/GROUP BY expression not found in targetlist");
818  if (tle->ressortgroupref != 0 &&
819  tle->ressortgroupref != target->sortgrouprefs[i])
820  elog(ERROR, "targetlist item has multiple sortgroupref labels");
821 
822  tle->ressortgroupref = target->sortgrouprefs[i];
823  }
824  i++;
825  }
826 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
Definition: primnodes.h:167
#define ERROR
Definition: elog.h:43
Index * sortgrouprefs
Definition: pathnodes.h:1047
List * exprs
Definition: pathnodes.h:1046
TargetEntry * tlist_member(Expr *node, List *targetlist)
Definition: tlist.c:73
static TargetEntry * tlist_member_match_var(Var *var, List *targetlist)
Definition: tlist.c:124
#define lfirst(lc)
Definition: pg_list.h:190
#define elog(elevel,...)
Definition: elog.h:228
int i
Index ressortgroupref
Definition: primnodes.h:1396

◆ apply_tlist_labeling()

void apply_tlist_labeling ( List dest_tlist,
List src_tlist 
)

Definition at line 340 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().

341 {
342  ListCell *ld,
343  *ls;
344 
345  Assert(list_length(dest_tlist) == list_length(src_tlist));
346  forboth(ld, dest_tlist, ls, src_tlist)
347  {
348  TargetEntry *dest_tle = (TargetEntry *) lfirst(ld);
349  TargetEntry *src_tle = (TargetEntry *) lfirst(ls);
350 
351  Assert(dest_tle->resno == src_tle->resno);
352  dest_tle->resname = src_tle->resname;
353  dest_tle->ressortgroupref = src_tle->ressortgroupref;
354  dest_tle->resorigtbl = src_tle->resorigtbl;
355  dest_tle->resorigcol = src_tle->resorigcol;
356  dest_tle->resjunk = src_tle->resjunk;
357  }
358 }
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:419
Oid resorigtbl
Definition: primnodes.h:1398
char * resname
Definition: primnodes.h:1395
bool resjunk
Definition: primnodes.h:1400
AttrNumber resno
Definition: primnodes.h:1394
#define Assert(condition)
Definition: c.h:739
#define lfirst(lc)
Definition: pg_list.h:190
static int list_length(const List *l)
Definition: pg_list.h:169
AttrNumber resorigcol
Definition: primnodes.h:1399
Index ressortgroupref
Definition: primnodes.h:1396

◆ copy_pathtarget()

PathTarget* copy_pathtarget ( PathTarget src)

Definition at line 672 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().

673 {
675 
676  /* Copy scalar fields */
677  memcpy(dst, src, sizeof(PathTarget));
678  /* Shallow-copy the expression list */
679  dst->exprs = list_copy(src->exprs);
680  /* Duplicate sortgrouprefs if any (if not, the memcpy handled this) */
681  if (src->sortgrouprefs)
682  {
683  Size nbytes = list_length(src->exprs) * sizeof(Index);
684 
685  dst->sortgrouprefs = (Index *) palloc(nbytes);
686  memcpy(dst->sortgrouprefs, src->sortgrouprefs, nbytes);
687  }
688  return dst;
689 }
List * list_copy(const List *oldlist)
Definition: list.c:1404
Index * sortgrouprefs
Definition: pathnodes.h:1047
List * exprs
Definition: pathnodes.h:1046
unsigned int Index
Definition: c.h:476
#define makeNode(_type_)
Definition: nodes.h:573
size_t Size
Definition: c.h:467
static int list_length(const List *l)
Definition: pg_list.h:169
void * palloc(Size size)
Definition: mcxt.c:949

◆ create_empty_pathtarget()

PathTarget* create_empty_pathtarget ( void  )

Definition at line 696 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().

697 {
698  /* This is easy, but we don't want callers to hard-wire this ... */
699  return makeNode(PathTarget);
700 }
#define makeNode(_type_)
Definition: nodes.h:573

◆ extract_grouping_collations()

Oid* extract_grouping_collations ( List groupClause,
List tlist 
)

Definition at line 511 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().

512 {
513  int numCols = list_length(groupClause);
514  int colno = 0;
515  Oid *grpCollations;
516  ListCell *glitem;
517 
518  grpCollations = (Oid *) palloc(sizeof(Oid) * numCols);
519 
520  foreach(glitem, groupClause)
521  {
522  SortGroupClause *groupcl = (SortGroupClause *) lfirst(glitem);
523  TargetEntry *tle = get_sortgroupclause_tle(groupcl, tlist);
524 
525  grpCollations[colno++] = exprCollation((Node *) tle->expr);
526  }
527 
528  return grpCollations;
529 }
TargetEntry * get_sortgroupclause_tle(SortGroupClause *sgClause, List *targetList)
Definition: tlist.c:389
Definition: nodes.h:525
unsigned int Oid
Definition: postgres_ext.h:31
#define lfirst(lc)
Definition: pg_list.h:190
Expr * expr
Definition: primnodes.h:1393
static int list_length(const List *l)
Definition: pg_list.h:169
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:719
void * palloc(Size size)
Definition: mcxt.c:949

◆ extract_grouping_cols()

AttrNumber* extract_grouping_cols ( List groupClause,
List tlist 
)

Definition at line 536 of file tlist.c.

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

Referenced by create_agg_plan(), and create_group_plan().

537 {
538  AttrNumber *grpColIdx;
539  int numCols = list_length(groupClause);
540  int colno = 0;
541  ListCell *glitem;
542 
543  grpColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
544 
545  foreach(glitem, groupClause)
546  {
547  SortGroupClause *groupcl = (SortGroupClause *) lfirst(glitem);
548  TargetEntry *tle = get_sortgroupclause_tle(groupcl, tlist);
549 
550  grpColIdx[colno++] = tle->resno;
551  }
552 
553  return grpColIdx;
554 }
TargetEntry * get_sortgroupclause_tle(SortGroupClause *sgClause, List *targetList)
Definition: tlist.c:389
AttrNumber resno
Definition: primnodes.h:1394
#define lfirst(lc)
Definition: pg_list.h:190
static int list_length(const List *l)
Definition: pg_list.h:169
void * palloc(Size size)
Definition: mcxt.c:949
int16 AttrNumber
Definition: attnum.h:21

◆ extract_grouping_ops()

Oid* extract_grouping_ops ( List groupClause)

Definition at line 485 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().

486 {
487  int numCols = list_length(groupClause);
488  int colno = 0;
489  Oid *groupOperators;
490  ListCell *glitem;
491 
492  groupOperators = (Oid *) palloc(sizeof(Oid) * numCols);
493 
494  foreach(glitem, groupClause)
495  {
496  SortGroupClause *groupcl = (SortGroupClause *) lfirst(glitem);
497 
498  groupOperators[colno] = groupcl->eqop;
499  Assert(OidIsValid(groupOperators[colno]));
500  colno++;
501  }
502 
503  return groupOperators;
504 }
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:645
#define Assert(condition)
Definition: c.h:739
#define lfirst(lc)
Definition: pg_list.h:190
static int list_length(const List *l)
Definition: pg_list.h:169
void * palloc(Size size)
Definition: mcxt.c:949

◆ get_tlist_exprs()

List* get_tlist_exprs ( List tlist,
bool  includeJunk 
)

Definition at line 185 of file tlist.c.

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

Referenced by recurse_set_operations().

186 {
187  List *result = NIL;
188  ListCell *l;
189 
190  foreach(l, tlist)
191  {
192  TargetEntry *tle = (TargetEntry *) lfirst(l);
193 
194  if (tle->resjunk && !includeJunk)
195  continue;
196 
197  result = lappend(result, tle->expr);
198  }
199  return result;
200 }
#define NIL
Definition: pg_list.h:65
bool resjunk
Definition: primnodes.h:1400
List * lappend(List *list, void *datum)
Definition: list.c:322
#define lfirst(lc)
Definition: pg_list.h:190
Expr * expr
Definition: primnodes.h:1393
Definition: pg_list.h:50

◆ grouping_is_hashable()

bool grouping_is_hashable ( List groupClause)

Definition at line 582 of file tlist.c.

References SortGroupClause::hashable, and lfirst.

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

583 {
584  ListCell *glitem;
585 
586  foreach(glitem, groupClause)
587  {
588  SortGroupClause *groupcl = (SortGroupClause *) lfirst(glitem);
589 
590  if (!groupcl->hashable)
591  return false;
592  }
593  return true;
594 }
#define lfirst(lc)
Definition: pg_list.h:190

◆ grouping_is_sortable()

bool grouping_is_sortable ( List groupClause)

Definition at line 562 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().

563 {
564  ListCell *glitem;
565 
566  foreach(glitem, groupClause)
567  {
568  SortGroupClause *groupcl = (SortGroupClause *) lfirst(glitem);
569 
570  if (!OidIsValid(groupcl->sortop))
571  return false;
572  }
573  return true;
574 }
#define OidIsValid(objectId)
Definition: c.h:645
#define lfirst(lc)
Definition: pg_list.h:190

◆ make_pathtarget_from_tlist()

PathTarget* make_pathtarget_from_tlist ( List tlist)

Definition at line 613 of file tlist.c.

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

614 {
615  PathTarget *target = makeNode(PathTarget);
616  int i;
617  ListCell *lc;
618 
619  target->sortgrouprefs = (Index *) palloc(list_length(tlist) * sizeof(Index));
620 
621  i = 0;
622  foreach(lc, tlist)
623  {
624  TargetEntry *tle = (TargetEntry *) lfirst(lc);
625 
626  target->exprs = lappend(target->exprs, tle->expr);
627  target->sortgrouprefs[i] = tle->ressortgroupref;
628  i++;
629  }
630 
631  return target;
632 }
Index * sortgrouprefs
Definition: pathnodes.h:1047
List * lappend(List *list, void *datum)
Definition: list.c:322
List * exprs
Definition: pathnodes.h:1046
unsigned int Index
Definition: c.h:476
#define makeNode(_type_)
Definition: nodes.h:573
#define lfirst(lc)
Definition: pg_list.h:190
Expr * expr
Definition: primnodes.h:1393
static int list_length(const List *l)
Definition: pg_list.h:169
void * palloc(Size size)
Definition: mcxt.c:949
int i
Index ressortgroupref
Definition: primnodes.h:1396

◆ make_tlist_from_pathtarget()

List* make_tlist_from_pathtarget ( PathTarget target)

Definition at line 639 of file tlist.c.

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

Referenced by set_subquery_pathlist().

640 {
641  List *tlist = NIL;
642  int i;
643  ListCell *lc;
644 
645  i = 0;
646  foreach(lc, target->exprs)
647  {
648  Expr *expr = (Expr *) lfirst(lc);
649  TargetEntry *tle;
650 
651  tle = makeTargetEntry(expr,
652  i + 1,
653  NULL,
654  false);
655  if (target->sortgrouprefs)
656  tle->ressortgroupref = target->sortgrouprefs[i];
657  tlist = lappend(tlist, tle);
658  i++;
659  }
660 
661  return tlist;
662 }
#define NIL
Definition: pg_list.h:65
Index * sortgrouprefs
Definition: pathnodes.h:1047
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:236
List * lappend(List *list, void *datum)
Definition: list.c:322
List * exprs
Definition: pathnodes.h:1046
#define lfirst(lc)
Definition: pg_list.h:190
int i
Index ressortgroupref
Definition: primnodes.h:1396
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 886 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().

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

◆ tlist_member()

TargetEntry* tlist_member ( Expr node,
List targetlist 
)

Definition at line 73 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().

74 {
75  ListCell *temp;
76 
77  foreach(temp, targetlist)
78  {
79  TargetEntry *tlentry = (TargetEntry *) lfirst(temp);
80 
81  if (equal(node, tlentry->expr))
82  return tlentry;
83  }
84  return NULL;
85 }
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3011
#define lfirst(lc)
Definition: pg_list.h:190
Expr * expr
Definition: primnodes.h:1393

◆ tlist_member_ignore_relabel()

TargetEntry* tlist_member_ignore_relabel ( Expr node,
List targetlist 
)

Definition at line 94 of file tlist.c.

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

Referenced by prepare_sort_from_pathkeys().

95 {
96  ListCell *temp;
97 
98  while (node && IsA(node, RelabelType))
99  node = ((RelabelType *) node)->arg;
100 
101  foreach(temp, targetlist)
102  {
103  TargetEntry *tlentry = (TargetEntry *) lfirst(temp);
104  Expr *tlexpr = tlentry->expr;
105 
106  while (tlexpr && IsA(tlexpr, RelabelType))
107  tlexpr = ((RelabelType *) tlexpr)->arg;
108 
109  if (equal(node, tlexpr))
110  return tlentry;
111  }
112  return NULL;
113 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3011
#define lfirst(lc)
Definition: pg_list.h:190
Expr * expr
Definition: primnodes.h:1393
void * arg

◆ tlist_same_collations()

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

Definition at line 304 of file tlist.c.

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

Referenced by recurse_set_operations().

305 {
306  ListCell *l;
307  ListCell *curColColl = list_head(colCollations);
308 
309  foreach(l, tlist)
310  {
311  TargetEntry *tle = (TargetEntry *) lfirst(l);
312 
313  if (tle->resjunk)
314  {
315  if (!junkOK)
316  return false;
317  }
318  else
319  {
320  if (curColColl == NULL)
321  return false; /* tlist longer than colCollations */
322  if (exprCollation((Node *) tle->expr) != lfirst_oid(curColColl))
323  return false;
324  curColColl = lnext(colCollations, curColColl);
325  }
326  }
327  if (curColColl != NULL)
328  return false; /* tlist shorter than colCollations */
329  return true;
330 }
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:321
Definition: nodes.h:525
bool resjunk
Definition: primnodes.h:1400
static ListCell * list_head(const List *l)
Definition: pg_list.h:125
#define lfirst(lc)
Definition: pg_list.h:190
Expr * expr
Definition: primnodes.h:1393
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:719
#define lfirst_oid(lc)
Definition: pg_list.h:192

◆ tlist_same_datatypes()

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

Definition at line 270 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().

271 {
272  ListCell *l;
273  ListCell *curColType = list_head(colTypes);
274 
275  foreach(l, tlist)
276  {
277  TargetEntry *tle = (TargetEntry *) lfirst(l);
278 
279  if (tle->resjunk)
280  {
281  if (!junkOK)
282  return false;
283  }
284  else
285  {
286  if (curColType == NULL)
287  return false; /* tlist longer than colTypes */
288  if (exprType((Node *) tle->expr) != lfirst_oid(curColType))
289  return false;
290  curColType = lnext(colTypes, curColType);
291  }
292  }
293  if (curColType != NULL)
294  return false; /* tlist shorter than colTypes */
295  return true;
296 }
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:321
Definition: nodes.h:525
bool resjunk
Definition: primnodes.h:1400
static ListCell * list_head(const List *l)
Definition: pg_list.h:125
#define lfirst(lc)
Definition: pg_list.h:190
Expr * expr
Definition: primnodes.h:1393
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
#define lfirst_oid(lc)
Definition: pg_list.h:192

◆ tlist_same_exprs()

bool tlist_same_exprs ( List tlist1,
List tlist2 
)

Definition at line 240 of file tlist.c.

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

Referenced by change_plan_targetlist(), and create_projection_plan().

241 {
242  ListCell *lc1,
243  *lc2;
244 
245  if (list_length(tlist1) != list_length(tlist2))
246  return false; /* not same length, so can't match */
247 
248  forboth(lc1, tlist1, lc2, tlist2)
249  {
250  TargetEntry *tle1 = (TargetEntry *) lfirst(lc1);
251  TargetEntry *tle2 = (TargetEntry *) lfirst(lc2);
252 
253  if (!equal(tle1->expr, tle2->expr))
254  return false;
255  }
256 
257  return true;
258 }
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:419
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3011
#define lfirst(lc)
Definition: pg_list.h:190
Expr * expr
Definition: primnodes.h:1393
static int list_length(const List *l)
Definition: pg_list.h:169