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

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

Definition at line 53 of file tlist.h.

Function Documentation

◆ add_column_to_pathtarget()

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

Definition at line 695 of file tlist.c.

696{
697 /* Updating the exprs list is easy ... */
698 target->exprs = lappend(target->exprs, expr);
699 /* ... the sortgroupref data, a bit less so */
700 if (target->sortgrouprefs)
701 {
702 int nexprs = list_length(target->exprs);
703
704 /* This might look inefficient, but actually it's usually cheap */
705 target->sortgrouprefs = (Index *)
706 repalloc(target->sortgrouprefs, nexprs * sizeof(Index));
707 target->sortgrouprefs[nexprs - 1] = sortgroupref;
708 }
709 else if (sortgroupref)
710 {
711 /* Adding sortgroupref labeling to a previously unlabeled target */
712 int nexprs = list_length(target->exprs);
713
714 target->sortgrouprefs = (Index *) palloc0(nexprs * sizeof(Index));
715 target->sortgrouprefs[nexprs - 1] = sortgroupref;
716 }
717
718 /*
719 * Reset has_volatile_expr to UNKNOWN. We just leave it up to
720 * contain_volatile_functions to set this properly again. Technically we
721 * could save some effort here and just check the new Expr, but it seems
722 * better to keep the logic for setting this flag in one location rather
723 * than duplicating the logic here.
724 */
727}
unsigned int Index
Definition: c.h:571
List * lappend(List *list, void *datum)
Definition: list.c:339
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1541
void * palloc0(Size size)
Definition: mcxt.c:1347
@ VOLATILITY_NOVOLATILE
Definition: pathnodes.h:1511
@ VOLATILITY_UNKNOWN
Definition: pathnodes.h:1509
static int list_length(const List *l)
Definition: pg_list.h:152
VolatileFunctionStatus has_volatile_expr
Definition: pathnodes.h:1556
List * exprs
Definition: pathnodes.h:1544

References PathTarget::exprs, PathTarget::has_volatile_expr, lappend(), list_length(), palloc0(), repalloc(), 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().

◆ add_new_column_to_pathtarget()

void add_new_column_to_pathtarget ( PathTarget target,
Expr expr 
)

Definition at line 741 of file tlist.c.

742{
743 if (!list_member(target->exprs, expr))
744 add_column_to_pathtarget(target, expr, 0);
745}
bool list_member(const List *list, const void *datum)
Definition: list.c:661
void add_column_to_pathtarget(PathTarget *target, Expr *expr, Index sortgroupref)
Definition: tlist.c:695

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

Referenced by add_new_columns_to_pathtarget().

◆ add_new_columns_to_pathtarget()

void add_new_columns_to_pathtarget ( PathTarget target,
List exprs 
)

Definition at line 752 of file tlist.c.

753{
754 ListCell *lc;
755
756 foreach(lc, exprs)
757 {
758 Expr *expr = (Expr *) lfirst(lc);
759
760 add_new_column_to_pathtarget(target, expr);
761 }
762}
#define lfirst(lc)
Definition: pg_list.h:172
void add_new_column_to_pathtarget(PathTarget *target, Expr *expr)
Definition: tlist.c:741

References add_new_column_to_pathtarget(), and lfirst.

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

◆ add_to_flat_tlist()

List * add_to_flat_tlist ( List tlist,
List exprs 
)

Definition at line 132 of file tlist.c.

133{
134 int next_resno = list_length(tlist) + 1;
135 ListCell *lc;
136
137 foreach(lc, exprs)
138 {
139 Expr *expr = (Expr *) lfirst(lc);
140
141 if (!tlist_member(expr, tlist))
142 {
143 TargetEntry *tle;
144
145 tle = makeTargetEntry(copyObject(expr), /* copy needed?? */
146 next_resno++,
147 NULL,
148 false);
149 tlist = lappend(tlist, tle);
150 }
151 }
152 return tlist;
153}
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:242
#define copyObject(obj)
Definition: nodes.h:224
TargetEntry * tlist_member(Expr *node, List *targetlist)
Definition: tlist.c:79

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

Referenced by build_tlist_to_deparse(), and foreign_grouping_ok().

◆ apply_pathtarget_labeling_to_tlist()

void apply_pathtarget_labeling_to_tlist ( List tlist,
PathTarget target 
)

Definition at line 774 of file tlist.c.

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

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

Referenced by create_projection_plan(), and create_scan_plan().

◆ apply_tlist_labeling()

void apply_tlist_labeling ( List dest_tlist,
List src_tlist 
)

Definition at line 318 of file tlist.c.

319{
320 ListCell *ld,
321 *ls;
322
323 Assert(list_length(dest_tlist) == list_length(src_tlist));
324 forboth(ld, dest_tlist, ls, src_tlist)
325 {
326 TargetEntry *dest_tle = (TargetEntry *) lfirst(ld);
327 TargetEntry *src_tle = (TargetEntry *) lfirst(ls);
328
329 Assert(dest_tle->resno == src_tle->resno);
330 dest_tle->resname = src_tle->resname;
331 dest_tle->ressortgroupref = src_tle->ressortgroupref;
332 dest_tle->resorigtbl = src_tle->resorigtbl;
333 dest_tle->resorigcol = src_tle->resorigcol;
334 dest_tle->resjunk = src_tle->resjunk;
335 }
336}
#define Assert(condition)
Definition: c.h:815
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:518
AttrNumber resno
Definition: primnodes.h:2247

References Assert, forboth, lfirst, list_length(), TargetEntry::resno, and TargetEntry::ressortgroupref.

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

◆ copy_pathtarget()

PathTarget * copy_pathtarget ( PathTarget src)

Definition at line 657 of file tlist.c.

658{
660
661 /* Copy scalar fields */
662 memcpy(dst, src, sizeof(PathTarget));
663 /* Shallow-copy the expression list */
664 dst->exprs = list_copy(src->exprs);
665 /* Duplicate sortgrouprefs if any (if not, the memcpy handled this) */
666 if (src->sortgrouprefs)
667 {
668 Size nbytes = list_length(src->exprs) * sizeof(Index);
669
670 dst->sortgrouprefs = (Index *) palloc(nbytes);
671 memcpy(dst->sortgrouprefs, src->sortgrouprefs, nbytes);
672 }
673 return dst;
674}
size_t Size
Definition: c.h:562
List * list_copy(const List *oldlist)
Definition: list.c:1573
void * palloc(Size size)
Definition: mcxt.c:1317
#define makeNode(_type_)
Definition: nodes.h:155

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

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

◆ create_empty_pathtarget()

PathTarget * create_empty_pathtarget ( void  )

Definition at line 681 of file tlist.c.

682{
683 /* This is easy, but we don't want callers to hard-wire this ... */
684 return makeNode(PathTarget);
685}

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

◆ extract_grouping_collations()

Oid * extract_grouping_collations ( List groupClause,
List tlist 
)

Definition at line 489 of file tlist.c.

490{
491 int numCols = list_length(groupClause);
492 int colno = 0;
493 Oid *grpCollations;
494 ListCell *glitem;
495
496 grpCollations = (Oid *) palloc(sizeof(Oid) * numCols);
497
498 foreach(glitem, groupClause)
499 {
500 SortGroupClause *groupcl = (SortGroupClause *) lfirst(glitem);
501 TargetEntry *tle = get_sortgroupclause_tle(groupcl, tlist);
502
503 grpCollations[colno++] = exprCollation((Node *) tle->expr);
504 }
505
506 return grpCollations;
507}
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:821
unsigned int Oid
Definition: postgres_ext.h:32
Definition: nodes.h:129
Expr * expr
Definition: primnodes.h:2245
TargetEntry * get_sortgroupclause_tle(SortGroupClause *sgClause, List *targetList)
Definition: tlist.c:367

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

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

◆ extract_grouping_cols()

AttrNumber * extract_grouping_cols ( List groupClause,
List tlist 
)

Definition at line 514 of file tlist.c.

515{
516 AttrNumber *grpColIdx;
517 int numCols = list_length(groupClause);
518 int colno = 0;
519 ListCell *glitem;
520
521 grpColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
522
523 foreach(glitem, groupClause)
524 {
525 SortGroupClause *groupcl = (SortGroupClause *) lfirst(glitem);
526 TargetEntry *tle = get_sortgroupclause_tle(groupcl, tlist);
527
528 grpColIdx[colno++] = tle->resno;
529 }
530
531 return grpColIdx;
532}
int16 AttrNumber
Definition: attnum.h:21

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

Referenced by create_agg_plan(), and create_group_plan().

◆ extract_grouping_ops()

Oid * extract_grouping_ops ( List groupClause)

Definition at line 463 of file tlist.c.

464{
465 int numCols = list_length(groupClause);
466 int colno = 0;
467 Oid *groupOperators;
468 ListCell *glitem;
469
470 groupOperators = (Oid *) palloc(sizeof(Oid) * numCols);
471
472 foreach(glitem, groupClause)
473 {
474 SortGroupClause *groupcl = (SortGroupClause *) lfirst(glitem);
475
476 groupOperators[colno] = groupcl->eqop;
477 Assert(OidIsValid(groupOperators[colno]));
478 colno++;
479 }
480
481 return groupOperators;
482}
#define OidIsValid(objectId)
Definition: c.h:732

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

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

◆ get_tlist_exprs()

List * get_tlist_exprs ( List tlist,
bool  includeJunk 
)

Definition at line 163 of file tlist.c.

164{
165 List *result = NIL;
166 ListCell *l;
167
168 foreach(l, tlist)
169 {
170 TargetEntry *tle = (TargetEntry *) lfirst(l);
171
172 if (tle->resjunk && !includeJunk)
173 continue;
174
175 result = lappend(result, tle->expr);
176 }
177 return result;
178}
#define NIL
Definition: pg_list.h:68
Definition: pg_list.h:54

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

Referenced by build_setop_child_paths().

◆ grouping_is_hashable()

bool grouping_is_hashable ( List groupClause)

Definition at line 560 of file tlist.c.

561{
562 ListCell *glitem;
563
564 foreach(glitem, groupClause)
565 {
566 SortGroupClause *groupcl = (SortGroupClause *) lfirst(glitem);
567
568 if (!groupcl->hashable)
569 return false;
570 }
571 return true;
572}

References lfirst.

Referenced by create_final_distinct_paths(), create_grouping_paths(), create_partial_distinct_paths(), generate_nonunion_paths(), generate_recursion_path(), and generate_union_paths().

◆ grouping_is_sortable()

bool grouping_is_sortable ( List groupClause)

Definition at line 540 of file tlist.c.

541{
542 ListCell *glitem;
543
544 foreach(glitem, groupClause)
545 {
546 SortGroupClause *groupcl = (SortGroupClause *) lfirst(glitem);
547
548 if (!OidIsValid(groupcl->sortop))
549 return false;
550 }
551 return true;
552}

References lfirst, OidIsValid, and SortGroupClause::sortop.

Referenced by adjust_foreign_grouping_path_cost(), create_final_distinct_paths(), create_grouping_paths(), create_partial_distinct_paths(), generate_nonunion_paths(), generate_union_paths(), make_pathkeys_for_window(), and standard_qp_callback().

◆ make_pathtarget_from_tlist()

PathTarget * make_pathtarget_from_tlist ( List tlist)

Definition at line 591 of file tlist.c.

592{
593 PathTarget *target = makeNode(PathTarget);
594 int i;
595 ListCell *lc;
596
597 target->sortgrouprefs = (Index *) palloc(list_length(tlist) * sizeof(Index));
598
599 i = 0;
600 foreach(lc, tlist)
601 {
602 TargetEntry *tle = (TargetEntry *) lfirst(lc);
603
604 target->exprs = lappend(target->exprs, tle->expr);
605 target->sortgrouprefs[i] = tle->ressortgroupref;
606 i++;
607 }
608
609 /*
610 * Mark volatility as unknown. The contain_volatile_functions function
611 * will determine if there are any volatile functions when called for the
612 * first time with this PathTarget.
613 */
615
616 return target;
617}

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

◆ make_tlist_from_pathtarget()

List * make_tlist_from_pathtarget ( PathTarget target)

Definition at line 624 of file tlist.c.

625{
626 List *tlist = NIL;
627 int i;
628 ListCell *lc;
629
630 i = 0;
631 foreach(lc, target->exprs)
632 {
633 Expr *expr = (Expr *) lfirst(lc);
634 TargetEntry *tle;
635
636 tle = makeTargetEntry(expr,
637 i + 1,
638 NULL,
639 false);
640 if (target->sortgrouprefs)
641 tle->ressortgroupref = target->sortgrouprefs[i];
642 tlist = lappend(tlist, tle);
643 i++;
644 }
645
646 return tlist;
647}

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

Referenced by build_setop_child_paths(), and set_subquery_pathlist().

◆ 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 881 of file tlist.c.

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

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, root, set_pathtarget_cost_width(), and split_pathtarget_walker().

Referenced by grouping_planner().

◆ tlist_member()

TargetEntry * tlist_member ( Expr node,
List targetlist 
)

Definition at line 79 of file tlist.c.

80{
81 ListCell *temp;
82
83 foreach(temp, targetlist)
84 {
85 TargetEntry *tlentry = (TargetEntry *) lfirst(temp);
86
87 if (equal(node, tlentry->expr))
88 return tlentry;
89 }
90 return NULL;
91}
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:223

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

◆ tlist_same_collations()

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

Definition at line 282 of file tlist.c.

283{
284 ListCell *l;
285 ListCell *curColColl = list_head(colCollations);
286
287 foreach(l, tlist)
288 {
289 TargetEntry *tle = (TargetEntry *) lfirst(l);
290
291 if (tle->resjunk)
292 {
293 if (!junkOK)
294 return false;
295 }
296 else
297 {
298 if (curColColl == NULL)
299 return false; /* tlist longer than colCollations */
300 if (exprCollation((Node *) tle->expr) != lfirst_oid(curColColl))
301 return false;
302 curColColl = lnext(colCollations, curColColl);
303 }
304 }
305 if (curColColl != NULL)
306 return false; /* tlist shorter than colCollations */
307 return true;
308}
static ListCell * list_head(const List *l)
Definition: pg_list.h:128
#define lfirst_oid(lc)
Definition: pg_list.h:174

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

Referenced by recurse_set_operations().

◆ tlist_same_datatypes()

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

Definition at line 248 of file tlist.c.

249{
250 ListCell *l;
251 ListCell *curColType = list_head(colTypes);
252
253 foreach(l, tlist)
254 {
255 TargetEntry *tle = (TargetEntry *) lfirst(l);
256
257 if (tle->resjunk)
258 {
259 if (!junkOK)
260 return false;
261 }
262 else
263 {
264 if (curColType == NULL)
265 return false; /* tlist longer than colTypes */
266 if (exprType((Node *) tle->expr) != lfirst_oid(curColType))
267 return false;
268 curColType = lnext(colTypes, curColType);
269 }
270 }
271 if (curColType != NULL)
272 return false; /* tlist shorter than colTypes */
273 return true;
274}
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42

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

Referenced by is_simple_union_all_recurse(), and recurse_set_operations().

◆ tlist_same_exprs()

bool tlist_same_exprs ( List tlist1,
List tlist2 
)

Definition at line 218 of file tlist.c.

219{
220 ListCell *lc1,
221 *lc2;
222
223 if (list_length(tlist1) != list_length(tlist2))
224 return false; /* not same length, so can't match */
225
226 forboth(lc1, tlist1, lc2, tlist2)
227 {
228 TargetEntry *tle1 = (TargetEntry *) lfirst(lc1);
229 TargetEntry *tle2 = (TargetEntry *) lfirst(lc2);
230
231 if (!equal(tle1->expr, tle2->expr))
232 return false;
233 }
234
235 return true;
236}

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

Referenced by apply_scanjoin_target_to_paths(), change_plan_targetlist(), and create_projection_plan().