PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
tlist.h File Reference
#include "nodes/relation.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 (Node *node, List *targetlist)
 
TargetEntrytlist_member_ignore_relabel (Node *node, List *targetlist)
 
Listadd_to_flat_tlist (List *tlist, List *exprs)
 
Listget_tlist_exprs (List *tlist, bool includeJunk)
 
int count_nonjunk_tlist_entries (List *tlist)
 
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)
 
TargetEntryget_sortgroupref_tle (Index sortref, List *targetList)
 
TargetEntryget_sortgroupclause_tle (SortGroupClause *sgClause, List *targetList)
 
Nodeget_sortgroupclause_expr (SortGroupClause *sgClause, List *targetList)
 
Listget_sortgrouplist_exprs (List *sgClauses, List *targetList)
 
SortGroupClauseget_sortgroupref_clause (Index sortref, List *clauses)
 
SortGroupClauseget_sortgroupref_clause_noerr (Index sortref, List *clauses)
 
Oidextract_grouping_ops (List *groupClause)
 
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

Function Documentation

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

Definition at line 667 of file tlist.c.

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

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

668 {
669  /* Updating the exprs list is easy ... */
670  target->exprs = lappend(target->exprs, expr);
671  /* ... the sortgroupref data, a bit less so */
672  if (target->sortgrouprefs)
673  {
674  int nexprs = list_length(target->exprs);
675 
676  /* This might look inefficient, but actually it's usually cheap */
677  target->sortgrouprefs = (Index *)
678  repalloc(target->sortgrouprefs, nexprs * sizeof(Index));
679  target->sortgrouprefs[nexprs - 1] = sortgroupref;
680  }
681  else if (sortgroupref)
682  {
683  /* Adding sortgroupref labeling to a previously unlabeled target */
684  int nexprs = list_length(target->exprs);
685 
686  target->sortgrouprefs = (Index *) palloc0(nexprs * sizeof(Index));
687  target->sortgrouprefs[nexprs - 1] = sortgroupref;
688  }
689 }
Index * sortgrouprefs
Definition: relation.h:829
List * lappend(List *list, void *datum)
Definition: list.c:128
List * exprs
Definition: relation.h:828
void * palloc0(Size size)
Definition: mcxt.c:878
unsigned int Index
Definition: c.h:365
static int list_length(const List *l)
Definition: pg_list.h:89
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:963
void add_new_column_to_pathtarget ( PathTarget target,
Expr expr 
)

Definition at line 703 of file tlist.c.

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

Referenced by add_new_columns_to_pathtarget(), and split_pathtarget_at_srfs().

704 {
705  if (!list_member(target->exprs, expr))
706  add_column_to_pathtarget(target, expr, 0);
707 }
void add_column_to_pathtarget(PathTarget *target, Expr *expr, Index sortgroupref)
Definition: tlist.c:667
bool list_member(const List *list, const void *datum)
Definition: list.c:444
List * exprs
Definition: relation.h:828
void add_new_columns_to_pathtarget ( PathTarget target,
List exprs 
)

Definition at line 714 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(), make_window_input_target(), and split_pathtarget_at_srfs().

715 {
716  ListCell *lc;
717 
718  foreach(lc, exprs)
719  {
720  Expr *expr = (Expr *) lfirst(lc);
721 
722  add_new_column_to_pathtarget(target, expr);
723  }
724 }
#define lfirst(lc)
Definition: pg_list.h:106
void add_new_column_to_pathtarget(PathTarget *target, Expr *expr)
Definition: tlist.c:703
List* add_to_flat_tlist ( List tlist,
List exprs 
)

Definition at line 135 of file tlist.c.

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

Referenced by build_tlist_to_deparse(), and foreign_grouping_ok().

136 {
137  int next_resno = list_length(tlist) + 1;
138  ListCell *lc;
139 
140  foreach(lc, exprs)
141  {
142  Node *expr = (Node *) lfirst(lc);
143 
144  if (!tlist_member(expr, tlist))
145  {
146  TargetEntry *tle;
147 
148  tle = makeTargetEntry(copyObject(expr), /* copy needed?? */
149  next_resno++,
150  NULL,
151  false);
152  tlist = lappend(tlist, tle);
153  }
154  }
155  return tlist;
156 }
Definition: nodes.h:519
void * copyObject(const void *from)
Definition: copyfuncs.c:4595
TargetEntry * tlist_member(Node *node, List *targetlist)
Definition: tlist.c:54
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:235
List * lappend(List *list, void *datum)
Definition: list.c:128
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
void apply_pathtarget_labeling_to_tlist ( List tlist,
PathTarget target 
)

Definition at line 736 of file tlist.c.

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

Referenced by create_scan_plan(), and foreign_grouping_ok().

737 {
738  int i;
739  ListCell *lc;
740 
741  /* Nothing to do if PathTarget has no sortgrouprefs data */
742  if (target->sortgrouprefs == NULL)
743  return;
744 
745  i = 0;
746  foreach(lc, target->exprs)
747  {
748  Expr *expr = (Expr *) lfirst(lc);
749  TargetEntry *tle;
750 
751  if (target->sortgrouprefs[i])
752  {
753  /*
754  * For Vars, use tlist_member_match_var's weakened matching rule;
755  * this allows us to deal with some cases where a set-returning
756  * function has been inlined, so that we now have more knowledge
757  * about what it returns than we did when the original Var was
758  * created. Otherwise, use regular equal() to find the matching
759  * TLE. (In current usage, only the Var case is actually needed;
760  * but it seems best to have sane behavior here for non-Vars too.)
761  */
762  if (expr && IsA(expr, Var))
763  tle = tlist_member_match_var((Var *) expr, tlist);
764  else
765  tle = tlist_member((Node *) expr, tlist);
766 
767  /*
768  * Complain if noplace for the sortgrouprefs label, or if we'd
769  * have to label a column twice. (The case where it already has
770  * the desired label probably can't happen, but we may as well
771  * allow for it.)
772  */
773  if (!tle)
774  elog(ERROR, "ORDER/GROUP BY expression not found in targetlist");
775  if (tle->ressortgroupref != 0 &&
776  tle->ressortgroupref != target->sortgrouprefs[i])
777  elog(ERROR, "targetlist item has multiple sortgroupref labels");
778 
779  tle->ressortgroupref = target->sortgrouprefs[i];
780  }
781  i++;
782  }
783 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:570
Definition: nodes.h:519
Definition: primnodes.h:163
TargetEntry * tlist_member(Node *node, List *targetlist)
Definition: tlist.c:54
#define ERROR
Definition: elog.h:43
Index * sortgrouprefs
Definition: relation.h:829
List * exprs
Definition: relation.h:828
#define NULL
Definition: c.h:229
static TargetEntry * tlist_member_match_var(Var *var, List *targetlist)
Definition: tlist.c:105
#define lfirst(lc)
Definition: pg_list.h:106
int i
Index ressortgroupref
Definition: primnodes.h:1355
#define elog
Definition: elog.h:219
void apply_tlist_labeling ( List dest_tlist,
List src_tlist 
)

Definition at line 321 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 create_modifytable_plan(), and create_plan().

322 {
323  ListCell *ld,
324  *ls;
325 
326  Assert(list_length(dest_tlist) == list_length(src_tlist));
327  forboth(ld, dest_tlist, ls, src_tlist)
328  {
329  TargetEntry *dest_tle = (TargetEntry *) lfirst(ld);
330  TargetEntry *src_tle = (TargetEntry *) lfirst(ls);
331 
332  Assert(dest_tle->resno == src_tle->resno);
333  dest_tle->resname = src_tle->resname;
334  dest_tle->ressortgroupref = src_tle->ressortgroupref;
335  dest_tle->resorigtbl = src_tle->resorigtbl;
336  dest_tle->resorigcol = src_tle->resorigcol;
337  dest_tle->resjunk = src_tle->resjunk;
338  }
339 }
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:174
Oid resorigtbl
Definition: primnodes.h:1357
char * resname
Definition: primnodes.h:1354
bool resjunk
Definition: primnodes.h:1359
AttrNumber resno
Definition: primnodes.h:1353
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
AttrNumber resorigcol
Definition: primnodes.h:1358
Index ressortgroupref
Definition: primnodes.h:1355
PathTarget* copy_pathtarget ( PathTarget src)

Definition at line 629 of file tlist.c.

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

Referenced by create_one_window_path(), and foreign_grouping_ok().

630 {
632 
633  /* Copy scalar fields */
634  memcpy(dst, src, sizeof(PathTarget));
635  /* Shallow-copy the expression list */
636  dst->exprs = list_copy(src->exprs);
637  /* Duplicate sortgrouprefs if any (if not, the memcpy handled this) */
638  if (src->sortgrouprefs)
639  {
640  Size nbytes = list_length(src->exprs) * sizeof(Index);
641 
642  dst->sortgrouprefs = (Index *) palloc(nbytes);
643  memcpy(dst->sortgrouprefs, src->sortgrouprefs, nbytes);
644  }
645  return dst;
646 }
List * list_copy(const List *oldlist)
Definition: list.c:1160
Index * sortgrouprefs
Definition: relation.h:829
List * exprs
Definition: relation.h:828
unsigned int Index
Definition: c.h:365
#define makeNode(_type_)
Definition: nodes.h:567
size_t Size
Definition: c.h:356
static int list_length(const List *l)
Definition: pg_list.h:89
void * palloc(Size size)
Definition: mcxt.c:849
int count_nonjunk_tlist_entries ( List tlist)

Definition at line 189 of file tlist.c.

References lfirst, and TargetEntry::resjunk.

Referenced by get_update_query_targetlist_def(), transformMultiAssignRef(), and transformSubLink().

190 {
191  int len = 0;
192  ListCell *l;
193 
194  foreach(l, tlist)
195  {
196  TargetEntry *tle = (TargetEntry *) lfirst(l);
197 
198  if (!tle->resjunk)
199  len++;
200  }
201  return len;
202 }
bool resjunk
Definition: primnodes.h:1359
#define lfirst(lc)
Definition: pg_list.h:106
PathTarget* create_empty_pathtarget ( void  )

Definition at line 653 of file tlist.c.

References makeNode.

Referenced by build_empty_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().

654 {
655  /* This is easy, but we don't want callers to hard-wire this ... */
656  return makeNode(PathTarget);
657 }
#define makeNode(_type_)
Definition: nodes.h:567
AttrNumber* extract_grouping_cols ( List groupClause,
List tlist 
)

Definition at line 492 of file tlist.c.

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

Referenced by create_agg_plan(), and create_group_plan().

493 {
494  AttrNumber *grpColIdx;
495  int numCols = list_length(groupClause);
496  int colno = 0;
497  ListCell *glitem;
498 
499  grpColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
500 
501  foreach(glitem, groupClause)
502  {
503  SortGroupClause *groupcl = (SortGroupClause *) lfirst(glitem);
504  TargetEntry *tle = get_sortgroupclause_tle(groupcl, tlist);
505 
506  grpColIdx[colno++] = tle->resno;
507  }
508 
509  return grpColIdx;
510 }
TargetEntry * get_sortgroupclause_tle(SortGroupClause *sgClause, List *targetList)
Definition: tlist.c:370
AttrNumber resno
Definition: primnodes.h:1353
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
void * palloc(Size size)
Definition: mcxt.c:849
int16 AttrNumber
Definition: attnum.h:21
Oid* extract_grouping_ops ( List groupClause)

Definition at line 466 of file tlist.c.

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

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

467 {
468  int numCols = list_length(groupClause);
469  int colno = 0;
470  Oid *groupOperators;
471  ListCell *glitem;
472 
473  groupOperators = (Oid *) palloc(sizeof(Oid) * numCols);
474 
475  foreach(glitem, groupClause)
476  {
477  SortGroupClause *groupcl = (SortGroupClause *) lfirst(glitem);
478 
479  groupOperators[colno] = groupcl->eqop;
480  Assert(OidIsValid(groupOperators[colno]));
481  colno++;
482  }
483 
484  return groupOperators;
485 }
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:538
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
void * palloc(Size size)
Definition: mcxt.c:849
Node* get_sortgroupclause_expr ( SortGroupClause sgClause,
List targetList 
)

Definition at line 382 of file tlist.c.

References TargetEntry::expr, and get_sortgroupclause_tle().

Referenced by get_sortgrouplist_exprs(), make_pathkeys_for_sortclauses(), and transformAggregateCall().

383 {
384  TargetEntry *tle = get_sortgroupclause_tle(sgClause, targetList);
385 
386  return (Node *) tle->expr;
387 }
TargetEntry * get_sortgroupclause_tle(SortGroupClause *sgClause, List *targetList)
Definition: tlist.c:370
Definition: nodes.h:519
Expr * expr
Definition: primnodes.h:1352
List* get_sortgrouplist_exprs ( List sgClauses,
List targetList 
)

Definition at line 395 of file tlist.c.

References get_sortgroupclause_expr(), lappend(), lfirst, and NIL.

Referenced by create_distinct_paths(), estimate_path_cost_size(), and get_number_of_groups().

396 {
397  List *result = NIL;
398  ListCell *l;
399 
400  foreach(l, sgClauses)
401  {
402  SortGroupClause *sortcl = (SortGroupClause *) lfirst(l);
403  Node *sortexpr;
404 
405  sortexpr = get_sortgroupclause_expr(sortcl, targetList);
406  result = lappend(result, sortexpr);
407  }
408  return result;
409 }
#define NIL
Definition: pg_list.h:69
Node * get_sortgroupclause_expr(SortGroupClause *sgClause, List *targetList)
Definition: tlist.c:382
Definition: nodes.h:519
List * lappend(List *list, void *datum)
Definition: list.c:128
#define lfirst(lc)
Definition: pg_list.h:106
Definition: pg_list.h:45
SortGroupClause* get_sortgroupref_clause ( Index  sortref,
List clauses 
)

Definition at line 425 of file tlist.c.

References elog, ERROR, lfirst, NULL, and SortGroupClause::tleSortGroupRef.

Referenced by preprocess_groupclause().

426 {
427  ListCell *l;
428 
429  foreach(l, clauses)
430  {
432 
433  if (cl->tleSortGroupRef == sortref)
434  return cl;
435  }
436 
437  elog(ERROR, "ORDER/GROUP BY expression not found in list");
438  return NULL; /* keep compiler quiet */
439 }
Index tleSortGroupRef
Definition: parsenodes.h:1141
#define ERROR
Definition: elog.h:43
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
#define elog
Definition: elog.h:219
SortGroupClause* get_sortgroupref_clause_noerr ( Index  sortref,
List clauses 
)

Definition at line 446 of file tlist.c.

References lfirst, NULL, and SortGroupClause::tleSortGroupRef.

Referenced by foreign_grouping_ok(), make_group_input_target(), and make_partial_grouping_target().

447 {
448  ListCell *l;
449 
450  foreach(l, clauses)
451  {
453 
454  if (cl->tleSortGroupRef == sortref)
455  return cl;
456  }
457 
458  return NULL;
459 }
Index tleSortGroupRef
Definition: parsenodes.h:1141
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
TargetEntry* get_sortgroupref_tle ( Index  sortref,
List targetList 
)

Definition at line 348 of file tlist.c.

References elog, ERROR, lfirst, NULL, and TargetEntry::ressortgroupref.

Referenced by convert_subquery_pathkeys(), deparseSortGroupClause(), foreign_expr_walker(), get_rule_sortgroupclause(), get_sortgroupclause_tle(), make_unique_from_pathkeys(), prepare_sort_from_pathkeys(), and transformDistinctOnClause().

349 {
350  ListCell *l;
351 
352  foreach(l, targetList)
353  {
354  TargetEntry *tle = (TargetEntry *) lfirst(l);
355 
356  if (tle->ressortgroupref == sortref)
357  return tle;
358  }
359 
360  elog(ERROR, "ORDER/GROUP BY expression not found in targetlist");
361  return NULL; /* keep compiler quiet */
362 }
#define ERROR
Definition: elog.h:43
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
Index ressortgroupref
Definition: primnodes.h:1355
#define elog
Definition: elog.h:219
List* get_tlist_exprs ( List tlist,
bool  includeJunk 
)

Definition at line 166 of file tlist.c.

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

Referenced by recurse_set_operations().

167 {
168  List *result = NIL;
169  ListCell *l;
170 
171  foreach(l, tlist)
172  {
173  TargetEntry *tle = (TargetEntry *) lfirst(l);
174 
175  if (tle->resjunk && !includeJunk)
176  continue;
177 
178  result = lappend(result, tle->expr);
179  }
180  return result;
181 }
#define NIL
Definition: pg_list.h:69
bool resjunk
Definition: primnodes.h:1359
List * lappend(List *list, void *datum)
Definition: list.c:128
#define lfirst(lc)
Definition: pg_list.h:106
Expr * expr
Definition: primnodes.h:1352
Definition: pg_list.h:45
bool grouping_is_hashable ( List groupClause)

Definition at line 538 of file tlist.c.

References SortGroupClause::hashable, and lfirst.

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

539 {
540  ListCell *glitem;
541 
542  foreach(glitem, groupClause)
543  {
544  SortGroupClause *groupcl = (SortGroupClause *) lfirst(glitem);
545 
546  if (!groupcl->hashable)
547  return false;
548  }
549  return true;
550 }
#define lfirst(lc)
Definition: pg_list.h:106
bool grouping_is_sortable ( List groupClause)

Definition at line 518 of file tlist.c.

References lfirst, OidIsValid, and SortGroupClause::sortop.

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

519 {
520  ListCell *glitem;
521 
522  foreach(glitem, groupClause)
523  {
524  SortGroupClause *groupcl = (SortGroupClause *) lfirst(glitem);
525 
526  if (!OidIsValid(groupcl->sortop))
527  return false;
528  }
529  return true;
530 }
#define OidIsValid(objectId)
Definition: c.h:538
#define lfirst(lc)
Definition: pg_list.h:106
PathTarget* make_pathtarget_from_tlist ( List tlist)

Definition at line 569 of file tlist.c.

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

570 {
571  PathTarget *target = makeNode(PathTarget);
572  int i;
573  ListCell *lc;
574 
575  target->sortgrouprefs = (Index *) palloc(list_length(tlist) * sizeof(Index));
576 
577  i = 0;
578  foreach(lc, tlist)
579  {
580  TargetEntry *tle = (TargetEntry *) lfirst(lc);
581 
582  target->exprs = lappend(target->exprs, tle->expr);
583  target->sortgrouprefs[i] = tle->ressortgroupref;
584  i++;
585  }
586 
587  return target;
588 }
Index * sortgrouprefs
Definition: relation.h:829
List * lappend(List *list, void *datum)
Definition: list.c:128
List * exprs
Definition: relation.h:828
unsigned int Index
Definition: c.h:365
#define makeNode(_type_)
Definition: nodes.h:567
#define lfirst(lc)
Definition: pg_list.h:106
Expr * expr
Definition: primnodes.h:1352
static int list_length(const List *l)
Definition: pg_list.h:89
void * palloc(Size size)
Definition: mcxt.c:849
int i
Index ressortgroupref
Definition: primnodes.h:1355
List* make_tlist_from_pathtarget ( PathTarget target)

Definition at line 595 of file tlist.c.

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

Referenced by set_subquery_pathlist().

596 {
597  List *tlist = NIL;
598  int i;
599  ListCell *lc;
600 
601  i = 0;
602  foreach(lc, target->exprs)
603  {
604  Expr *expr = (Expr *) lfirst(lc);
605  TargetEntry *tle;
606 
607  tle = makeTargetEntry(expr,
608  i + 1,
609  NULL,
610  false);
611  if (target->sortgrouprefs)
612  tle->ressortgroupref = target->sortgrouprefs[i];
613  tlist = lappend(tlist, tle);
614  i++;
615  }
616 
617  return tlist;
618 }
#define NIL
Definition: pg_list.h:69
Index * sortgrouprefs
Definition: relation.h:829
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:235
List * lappend(List *list, void *datum)
Definition: list.c:128
List * exprs
Definition: relation.h:828
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
int i
Index ressortgroupref
Definition: primnodes.h:1355
Definition: pg_list.h:45
void split_pathtarget_at_srfs ( PlannerInfo root,
PathTarget target,
PathTarget input_target,
List **  targets,
List **  targets_contain_srfs 
)

Definition at line 840 of file tlist.c.

References add_new_column_to_pathtarget(), add_new_columns_to_pathtarget(), copyObject(), create_empty_pathtarget(), split_pathtarget_context::current_depth, split_pathtarget_context::current_input_srfs, split_pathtarget_context::current_input_vars, PathTarget::exprs, for_each_cell, forthree, 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, NULL, set_pathtarget_cost_width(), and split_pathtarget_walker().

Referenced by grouping_planner().

843 {
844  split_pathtarget_context context;
845  int max_depth;
846  bool need_extra_projection;
847  List *prev_level_tlist;
848  ListCell *lc,
849  *lc1,
850  *lc2,
851  *lc3;
852 
853  /*
854  * It's not unusual for planner.c to pass us two physically identical
855  * targets, in which case we can conclude without further ado that all
856  * expressions are available from the input. (The logic below would
857  * arrive at the same conclusion, but much more tediously.)
858  */
859  if (target == input_target)
860  {
861  *targets = list_make1(target);
862  *targets_contain_srfs = list_make1_int(false);
863  return;
864  }
865 
866  /* Pass any input_target exprs down to split_pathtarget_walker() */
867  context.input_target_exprs = input_target ? input_target->exprs : NIL;
868 
869  /*
870  * Initialize with empty level-zero lists, and no levels after that.
871  * (Note: we could dispense with representing level zero explicitly, since
872  * it will never receive any SRFs, but then we'd have to special-case that
873  * level when we get to building result PathTargets. Level zero describes
874  * the SRF-free PathTarget that will be given to the input plan node.)
875  */
876  context.level_srfs = list_make1(NIL);
877  context.level_input_vars = list_make1(NIL);
878  context.level_input_srfs = list_make1(NIL);
879 
880  /* Initialize data we'll accumulate across all the target expressions */
881  context.current_input_vars = NIL;
882  context.current_input_srfs = NIL;
883  max_depth = 0;
884  need_extra_projection = false;
885 
886  /* Scan each expression in the PathTarget looking for SRFs */
887  foreach(lc, target->exprs)
888  {
889  Node *node = (Node *) lfirst(lc);
890 
891  /*
892  * Find all SRFs and Vars (and Var-like nodes) in this expression, and
893  * enter them into appropriate lists within the context struct.
894  */
895  context.current_depth = 0;
896  split_pathtarget_walker(node, &context);
897 
898  /* An expression containing no SRFs is of no further interest */
899  if (context.current_depth == 0)
900  continue;
901 
902  /*
903  * Track max SRF nesting depth over the whole PathTarget. Also, if
904  * this expression establishes a new max depth, we no longer care
905  * whether previous expressions contained nested SRFs; we can handle
906  * any required projection for them in the final ProjectSet node.
907  */
908  if (max_depth < context.current_depth)
909  {
910  max_depth = context.current_depth;
911  need_extra_projection = false;
912  }
913 
914  /*
915  * If any maximum-depth SRF is not at the top level of its expression,
916  * we'll need an extra Result node to compute the top-level scalar
917  * expression.
918  */
919  if (max_depth == context.current_depth && !IS_SRF_CALL(node))
920  need_extra_projection = true;
921  }
922 
923  /*
924  * If we found no SRFs needing evaluation (maybe they were all present in
925  * input_target, or maybe they were all removed by const-simplification),
926  * then no ProjectSet is needed; fall out.
927  */
928  if (max_depth == 0)
929  {
930  *targets = list_make1(target);
931  *targets_contain_srfs = list_make1_int(false);
932  return;
933  }
934 
935  /*
936  * The Vars and SRF outputs needed at top level can be added to the last
937  * level_input lists if we don't need an extra projection step. If we do
938  * need one, add a SRF-free level to the lists.
939  */
940  if (need_extra_projection)
941  {
942  context.level_srfs = lappend(context.level_srfs, NIL);
943  context.level_input_vars = lappend(context.level_input_vars,
944  context.current_input_vars);
945  context.level_input_srfs = lappend(context.level_input_srfs,
946  context.current_input_srfs);
947  }
948  else
949  {
950  lc = list_nth_cell(context.level_input_vars, max_depth);
951  lfirst(lc) = list_concat(lfirst(lc), context.current_input_vars);
952  lc = list_nth_cell(context.level_input_srfs, max_depth);
953  lfirst(lc) = list_concat(lfirst(lc), context.current_input_srfs);
954  }
955 
956  /*
957  * Now construct the output PathTargets. The original target can be used
958  * as-is for the last one, but we need to construct a new SRF-free target
959  * representing what the preceding plan node has to emit, as well as a
960  * target for each intermediate ProjectSet node.
961  */
962  *targets = *targets_contain_srfs = NIL;
963  prev_level_tlist = NIL;
964 
965  forthree(lc1, context.level_srfs,
966  lc2, context.level_input_vars,
967  lc3, context.level_input_srfs)
968  {
969  List *level_srfs = (List *) lfirst(lc1);
970  PathTarget *ntarget;
971 
972  if (lnext(lc1) == NULL)
973  {
974  ntarget = target;
975  }
976  else
977  {
978  ntarget = create_empty_pathtarget();
979 
980  /*
981  * This target should actually evaluate any SRFs of the current
982  * level, and it needs to propagate forward any Vars needed by
983  * later levels, as well as SRFs computed earlier and needed by
984  * later levels. We rely on add_new_columns_to_pathtarget() to
985  * remove duplicate items. Also, for safety, make a separate copy
986  * of each item for each PathTarget.
987  */
988  add_new_columns_to_pathtarget(ntarget, copyObject(level_srfs));
989  for_each_cell(lc, lnext(lc2))
990  {
991  List *input_vars = (List *) lfirst(lc);
992 
993  add_new_columns_to_pathtarget(ntarget, copyObject(input_vars));
994  }
995  for_each_cell(lc, lnext(lc3))
996  {
997  List *input_srfs = (List *) lfirst(lc);
998  ListCell *lcx;
999 
1000  foreach(lcx, input_srfs)
1001  {
1002  Node *srf = (Node *) lfirst(lcx);
1003 
1004  if (list_member(prev_level_tlist, srf))
1006  }
1007  }
1008  set_pathtarget_cost_width(root, ntarget);
1009  }
1010 
1011  /*
1012  * Add current target and does-it-compute-SRFs flag to output lists.
1013  */
1014  *targets = lappend(*targets, ntarget);
1015  *targets_contain_srfs = lappend_int(*targets_contain_srfs,
1016  (level_srfs != NIL));
1017 
1018  /* Remember this level's output for next pass */
1019  prev_level_tlist = ntarget->exprs;
1020  }
1021 }
PathTarget * create_empty_pathtarget(void)
Definition: tlist.c:653
#define NIL
Definition: pg_list.h:69
List * level_input_vars
Definition: tlist.c:33
PathTarget * set_pathtarget_cost_width(PlannerInfo *root, PathTarget *target)
Definition: costsize.c:4891
#define forthree(cell1, list1, cell2, list2, cell3, list3)
Definition: pg_list.h:183
Definition: nodes.h:519
List * list_concat(List *list1, List *list2)
Definition: list.c:321
ListCell * list_nth_cell(const List *list, int n)
Definition: list.c:386
List * current_input_srfs
Definition: tlist.c:36
void * copyObject(const void *from)
Definition: copyfuncs.c:4595
#define list_make1(x1)
Definition: pg_list.h:133
bool list_member(const List *list, const void *datum)
Definition: list.c:444
List * level_input_srfs
Definition: tlist.c:34
#define list_make1_int(x1)
Definition: pg_list.h:139
#define lnext(lc)
Definition: pg_list.h:105
List * lappend_int(List *list, int datum)
Definition: list.c:146
#define IS_SRF_CALL(node)
Definition: tlist.c:24
List * lappend(List *list, void *datum)
Definition: list.c:128
List * exprs
Definition: relation.h:828
List * input_target_exprs
Definition: tlist.c:31
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
#define for_each_cell(cell, initcell)
Definition: pg_list.h:163
void add_new_column_to_pathtarget(PathTarget *target, Expr *expr)
Definition: tlist.c:703
static bool split_pathtarget_walker(Node *node, split_pathtarget_context *context)
Definition: tlist.c:1030
Definition: pg_list.h:45
List * current_input_vars
Definition: tlist.c:35
void add_new_columns_to_pathtarget(PathTarget *target, List *exprs)
Definition: tlist.c:714
TargetEntry* tlist_member ( Node node,
List targetlist 
)

Definition at line 54 of file tlist.c.

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

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

55 {
56  ListCell *temp;
57 
58  foreach(temp, targetlist)
59  {
60  TargetEntry *tlentry = (TargetEntry *) lfirst(temp);
61 
62  if (equal(node, tlentry->expr))
63  return tlentry;
64  }
65  return NULL;
66 }
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2926
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
Expr * expr
Definition: primnodes.h:1352
TargetEntry* tlist_member_ignore_relabel ( Node node,
List targetlist 
)

Definition at line 75 of file tlist.c.

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

Referenced by prepare_sort_from_pathkeys().

76 {
77  ListCell *temp;
78 
79  while (node && IsA(node, RelabelType))
80  node = (Node *) ((RelabelType *) node)->arg;
81 
82  foreach(temp, targetlist)
83  {
84  TargetEntry *tlentry = (TargetEntry *) lfirst(temp);
85  Expr *tlexpr = tlentry->expr;
86 
87  while (tlexpr && IsA(tlexpr, RelabelType))
88  tlexpr = ((RelabelType *) tlexpr)->arg;
89 
90  if (equal(node, tlexpr))
91  return tlentry;
92  }
93  return NULL;
94 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:570
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2926
Definition: nodes.h:519
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
Expr * expr
Definition: primnodes.h:1352
void * arg
bool tlist_same_collations ( List tlist,
List colCollations,
bool  junkOK 
)

Definition at line 285 of file tlist.c.

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

Referenced by recurse_set_operations().

286 {
287  ListCell *l;
288  ListCell *curColColl = list_head(colCollations);
289 
290  foreach(l, tlist)
291  {
292  TargetEntry *tle = (TargetEntry *) lfirst(l);
293 
294  if (tle->resjunk)
295  {
296  if (!junkOK)
297  return false;
298  }
299  else
300  {
301  if (curColColl == NULL)
302  return false; /* tlist longer than colCollations */
303  if (exprCollation((Node *) tle->expr) != lfirst_oid(curColColl))
304  return false;
305  curColColl = lnext(curColColl);
306  }
307  }
308  if (curColColl != NULL)
309  return false; /* tlist shorter than colCollations */
310  return true;
311 }
Definition: nodes.h:519
bool resjunk
Definition: primnodes.h:1359
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define lnext(lc)
Definition: pg_list.h:105
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
Expr * expr
Definition: primnodes.h:1352
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:745
#define lfirst_oid(lc)
Definition: pg_list.h:108
bool tlist_same_datatypes ( List tlist,
List colTypes,
bool  junkOK 
)

Definition at line 251 of file tlist.c.

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

Referenced by is_simple_union_all_recurse(), and recurse_set_operations().

252 {
253  ListCell *l;
254  ListCell *curColType = list_head(colTypes);
255 
256  foreach(l, tlist)
257  {
258  TargetEntry *tle = (TargetEntry *) lfirst(l);
259 
260  if (tle->resjunk)
261  {
262  if (!junkOK)
263  return false;
264  }
265  else
266  {
267  if (curColType == NULL)
268  return false; /* tlist longer than colTypes */
269  if (exprType((Node *) tle->expr) != lfirst_oid(curColType))
270  return false;
271  curColType = lnext(curColType);
272  }
273  }
274  if (curColType != NULL)
275  return false; /* tlist shorter than colTypes */
276  return true;
277 }
Definition: nodes.h:519
bool resjunk
Definition: primnodes.h:1359
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define lnext(lc)
Definition: pg_list.h:105
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
Expr * expr
Definition: primnodes.h:1352
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
#define lfirst_oid(lc)
Definition: pg_list.h:108
bool tlist_same_exprs ( List tlist1,
List tlist2 
)

Definition at line 221 of file tlist.c.

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

Referenced by create_projection_plan(), and create_unique_plan().

222 {
223  ListCell *lc1,
224  *lc2;
225 
226  if (list_length(tlist1) != list_length(tlist2))
227  return false; /* not same length, so can't match */
228 
229  forboth(lc1, tlist1, lc2, tlist2)
230  {
231  TargetEntry *tle1 = (TargetEntry *) lfirst(lc1);
232  TargetEntry *tle2 = (TargetEntry *) lfirst(lc2);
233 
234  if (!equal(tle1->expr, tle2->expr))
235  return false;
236  }
237 
238  return true;
239 }
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:174
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2926
#define lfirst(lc)
Definition: pg_list.h:106
Expr * expr
Definition: primnodes.h:1352
static int list_length(const List *l)
Definition: pg_list.h:89