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

Go to the source code of this file.

Functions

int compare_path_costs (Path *path1, Path *path2, CostSelector criterion)
 
int compare_fractional_path_costs (Path *path1, Path *path2, double fraction)
 
void set_cheapest (RelOptInfo *parent_rel)
 
void add_path (RelOptInfo *parent_rel, Path *new_path)
 
bool add_path_precheck (RelOptInfo *parent_rel, Cost startup_cost, Cost total_cost, List *pathkeys, Relids required_outer)
 
void add_partial_path (RelOptInfo *parent_rel, Path *new_path)
 
bool add_partial_path_precheck (RelOptInfo *parent_rel, Cost total_cost, List *pathkeys)
 
Pathcreate_seqscan_path (PlannerInfo *root, RelOptInfo *rel, Relids required_outer, int parallel_workers)
 
Pathcreate_samplescan_path (PlannerInfo *root, RelOptInfo *rel, Relids required_outer)
 
IndexPathcreate_index_path (PlannerInfo *root, IndexOptInfo *index, List *indexclauses, List *indexorderbys, List *indexorderbycols, List *pathkeys, ScanDirection indexscandir, bool indexonly, Relids required_outer, double loop_count, bool partial_path)
 
BitmapHeapPathcreate_bitmap_heap_path (PlannerInfo *root, RelOptInfo *rel, Path *bitmapqual, Relids required_outer, double loop_count, int parallel_degree)
 
BitmapAndPathcreate_bitmap_and_path (PlannerInfo *root, RelOptInfo *rel, List *bitmapquals)
 
BitmapOrPathcreate_bitmap_or_path (PlannerInfo *root, RelOptInfo *rel, List *bitmapquals)
 
TidPathcreate_tidscan_path (PlannerInfo *root, RelOptInfo *rel, List *tidquals, Relids required_outer)
 
TidRangePathcreate_tidrangescan_path (PlannerInfo *root, RelOptInfo *rel, List *tidrangequals, Relids required_outer)
 
AppendPathcreate_append_path (PlannerInfo *root, RelOptInfo *rel, List *subpaths, List *partial_subpaths, List *pathkeys, Relids required_outer, int parallel_workers, bool parallel_aware, double rows)
 
MergeAppendPathcreate_merge_append_path (PlannerInfo *root, RelOptInfo *rel, List *subpaths, List *pathkeys, Relids required_outer)
 
GroupResultPathcreate_group_result_path (PlannerInfo *root, RelOptInfo *rel, PathTarget *target, List *havingqual)
 
MaterialPathcreate_material_path (RelOptInfo *rel, Path *subpath)
 
MemoizePathcreate_memoize_path (PlannerInfo *root, RelOptInfo *rel, Path *subpath, List *param_exprs, List *hash_operators, bool singlerow, bool binary_mode, double calls)
 
UniquePathcreate_unique_path (PlannerInfo *root, RelOptInfo *rel, Path *subpath, SpecialJoinInfo *sjinfo)
 
GatherPathcreate_gather_path (PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target, Relids required_outer, double *rows)
 
GatherMergePathcreate_gather_merge_path (PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target, List *pathkeys, Relids required_outer, double *rows)
 
SubqueryScanPathcreate_subqueryscan_path (PlannerInfo *root, RelOptInfo *rel, Path *subpath, bool trivial_pathtarget, List *pathkeys, Relids required_outer)
 
Pathcreate_functionscan_path (PlannerInfo *root, RelOptInfo *rel, List *pathkeys, Relids required_outer)
 
Pathcreate_valuesscan_path (PlannerInfo *root, RelOptInfo *rel, Relids required_outer)
 
Pathcreate_tablefuncscan_path (PlannerInfo *root, RelOptInfo *rel, Relids required_outer)
 
Pathcreate_ctescan_path (PlannerInfo *root, RelOptInfo *rel, Relids required_outer)
 
Pathcreate_namedtuplestorescan_path (PlannerInfo *root, RelOptInfo *rel, Relids required_outer)
 
Pathcreate_resultscan_path (PlannerInfo *root, RelOptInfo *rel, Relids required_outer)
 
Pathcreate_worktablescan_path (PlannerInfo *root, RelOptInfo *rel, Relids required_outer)
 
ForeignPathcreate_foreignscan_path (PlannerInfo *root, RelOptInfo *rel, PathTarget *target, double rows, Cost startup_cost, Cost total_cost, List *pathkeys, Relids required_outer, Path *fdw_outerpath, List *fdw_restrictinfo, List *fdw_private)
 
ForeignPathcreate_foreign_join_path (PlannerInfo *root, RelOptInfo *rel, PathTarget *target, double rows, Cost startup_cost, Cost total_cost, List *pathkeys, Relids required_outer, Path *fdw_outerpath, List *fdw_restrictinfo, List *fdw_private)
 
ForeignPathcreate_foreign_upper_path (PlannerInfo *root, RelOptInfo *rel, PathTarget *target, double rows, Cost startup_cost, Cost total_cost, List *pathkeys, Path *fdw_outerpath, List *fdw_restrictinfo, List *fdw_private)
 
Relids calc_nestloop_required_outer (Relids outerrelids, Relids outer_paramrels, Relids innerrelids, Relids inner_paramrels)
 
Relids calc_non_nestloop_required_outer (Path *outer_path, Path *inner_path)
 
NestPathcreate_nestloop_path (PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype, JoinCostWorkspace *workspace, JoinPathExtraData *extra, Path *outer_path, Path *inner_path, List *restrict_clauses, List *pathkeys, Relids required_outer)
 
MergePathcreate_mergejoin_path (PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype, JoinCostWorkspace *workspace, JoinPathExtraData *extra, Path *outer_path, Path *inner_path, List *restrict_clauses, List *pathkeys, Relids required_outer, List *mergeclauses, List *outersortkeys, List *innersortkeys)
 
HashPathcreate_hashjoin_path (PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype, JoinCostWorkspace *workspace, JoinPathExtraData *extra, Path *outer_path, Path *inner_path, bool parallel_hash, List *restrict_clauses, Relids required_outer, List *hashclauses)
 
ProjectionPathcreate_projection_path (PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target)
 
Pathapply_projection_to_path (PlannerInfo *root, RelOptInfo *rel, Path *path, PathTarget *target)
 
ProjectSetPathcreate_set_projection_path (PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target)
 
SortPathcreate_sort_path (PlannerInfo *root, RelOptInfo *rel, Path *subpath, List *pathkeys, double limit_tuples)
 
IncrementalSortPathcreate_incremental_sort_path (PlannerInfo *root, RelOptInfo *rel, Path *subpath, List *pathkeys, int presorted_keys, double limit_tuples)
 
GroupPathcreate_group_path (PlannerInfo *root, RelOptInfo *rel, Path *subpath, List *groupClause, List *qual, double numGroups)
 
UpperUniquePathcreate_upper_unique_path (PlannerInfo *root, RelOptInfo *rel, Path *subpath, int numCols, double numGroups)
 
AggPathcreate_agg_path (PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target, AggStrategy aggstrategy, AggSplit aggsplit, List *groupClause, List *qual, const AggClauseCosts *aggcosts, double numGroups)
 
GroupingSetsPathcreate_groupingsets_path (PlannerInfo *root, RelOptInfo *rel, Path *subpath, List *having_qual, AggStrategy aggstrategy, List *rollups, const AggClauseCosts *agg_costs)
 
MinMaxAggPathcreate_minmaxagg_path (PlannerInfo *root, RelOptInfo *rel, PathTarget *target, List *mmaggregates, List *quals)
 
WindowAggPathcreate_windowagg_path (PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target, List *windowFuncs, WindowClause *winclause, List *qual, bool topwindow)
 
SetOpPathcreate_setop_path (PlannerInfo *root, RelOptInfo *rel, Path *subpath, SetOpCmd cmd, SetOpStrategy strategy, List *distinctList, AttrNumber flagColIdx, int firstFlag, double numGroups, double outputRows)
 
RecursiveUnionPathcreate_recursiveunion_path (PlannerInfo *root, RelOptInfo *rel, Path *leftpath, Path *rightpath, PathTarget *target, List *distinctList, int wtParam, double numGroups)
 
LockRowsPathcreate_lockrows_path (PlannerInfo *root, RelOptInfo *rel, Path *subpath, List *rowMarks, int epqParam)
 
ModifyTablePathcreate_modifytable_path (PlannerInfo *root, RelOptInfo *rel, Path *subpath, CmdType operation, bool canSetTag, Index nominalRelation, Index rootRelation, bool partColsUpdated, List *resultRelations, List *updateColnosLists, List *withCheckOptionLists, List *returningLists, List *rowMarks, OnConflictExpr *onconflict, List *mergeActionLists, int epqParam)
 
LimitPathcreate_limit_path (PlannerInfo *root, RelOptInfo *rel, Path *subpath, Node *limitOffset, Node *limitCount, LimitOption limitOption, int64 offset_est, int64 count_est)
 
void adjust_limit_rows_costs (double *rows, Cost *startup_cost, Cost *total_cost, int64 offset_est, int64 count_est)
 
Pathreparameterize_path (PlannerInfo *root, Path *path, Relids required_outer, double loop_count)
 
Pathreparameterize_path_by_child (PlannerInfo *root, Path *path, RelOptInfo *child_rel)
 
void setup_simple_rel_arrays (PlannerInfo *root)
 
void expand_planner_arrays (PlannerInfo *root, int add_size)
 
RelOptInfobuild_simple_rel (PlannerInfo *root, int relid, RelOptInfo *parent)
 
RelOptInfofind_base_rel (PlannerInfo *root, int relid)
 
RelOptInfofind_base_rel_ignore_join (PlannerInfo *root, int relid)
 
RelOptInfofind_join_rel (PlannerInfo *root, Relids relids)
 
RelOptInfobuild_join_rel (PlannerInfo *root, Relids joinrelids, RelOptInfo *outer_rel, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo, List *pushed_down_joins, List **restrictlist_ptr)
 
Relids min_join_parameterization (PlannerInfo *root, Relids joinrelids, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
 
RelOptInfofetch_upper_rel (PlannerInfo *root, UpperRelationKind kind, Relids relids)
 
Relids find_childrel_parents (PlannerInfo *root, RelOptInfo *rel)
 
ParamPathInfoget_baserel_parampathinfo (PlannerInfo *root, RelOptInfo *baserel, Relids required_outer)
 
ParamPathInfoget_joinrel_parampathinfo (PlannerInfo *root, RelOptInfo *joinrel, Path *outer_path, Path *inner_path, SpecialJoinInfo *sjinfo, Relids required_outer, List **restrict_clauses)
 
ParamPathInfoget_appendrel_parampathinfo (RelOptInfo *appendrel, Relids required_outer)
 
ParamPathInfofind_param_path_info (RelOptInfo *rel, Relids required_outer)
 
Bitmapsetget_param_path_clause_serials (Path *path)
 
RelOptInfobuild_child_join_rel (PlannerInfo *root, RelOptInfo *outer_rel, RelOptInfo *inner_rel, RelOptInfo *parent_joinrel, List *restrictlist, SpecialJoinInfo *sjinfo)
 

Function Documentation

◆ add_partial_path()

void add_partial_path ( RelOptInfo parent_rel,
Path new_path 
)

Definition at line 749 of file pathnode.c.

750 {
751  bool accept_new = true; /* unless we find a superior old path */
752  int insert_at = 0; /* where to insert new item */
753  ListCell *p1;
754 
755  /* Check for query cancel. */
757 
758  /* Path to be added must be parallel safe. */
759  Assert(new_path->parallel_safe);
760 
761  /* Relation should be OK for parallelism, too. */
762  Assert(parent_rel->consider_parallel);
763 
764  /*
765  * As in add_path, throw out any paths which are dominated by the new
766  * path, but throw out the new path if some existing path dominates it.
767  */
768  foreach(p1, parent_rel->partial_pathlist)
769  {
770  Path *old_path = (Path *) lfirst(p1);
771  bool remove_old = false; /* unless new proves superior */
772  PathKeysComparison keyscmp;
773 
774  /* Compare pathkeys. */
775  keyscmp = compare_pathkeys(new_path->pathkeys, old_path->pathkeys);
776 
777  /* Unless pathkeys are incompatible, keep just one of the two paths. */
778  if (keyscmp != PATHKEYS_DIFFERENT)
779  {
780  if (new_path->total_cost > old_path->total_cost * STD_FUZZ_FACTOR)
781  {
782  /* New path costs more; keep it only if pathkeys are better. */
783  if (keyscmp != PATHKEYS_BETTER1)
784  accept_new = false;
785  }
786  else if (old_path->total_cost > new_path->total_cost
787  * STD_FUZZ_FACTOR)
788  {
789  /* Old path costs more; keep it only if pathkeys are better. */
790  if (keyscmp != PATHKEYS_BETTER2)
791  remove_old = true;
792  }
793  else if (keyscmp == PATHKEYS_BETTER1)
794  {
795  /* Costs are about the same, new path has better pathkeys. */
796  remove_old = true;
797  }
798  else if (keyscmp == PATHKEYS_BETTER2)
799  {
800  /* Costs are about the same, old path has better pathkeys. */
801  accept_new = false;
802  }
803  else if (old_path->total_cost > new_path->total_cost * 1.0000000001)
804  {
805  /* Pathkeys are the same, and the old path costs more. */
806  remove_old = true;
807  }
808  else
809  {
810  /*
811  * Pathkeys are the same, and new path isn't materially
812  * cheaper.
813  */
814  accept_new = false;
815  }
816  }
817 
818  /*
819  * Remove current element from partial_pathlist if dominated by new.
820  */
821  if (remove_old)
822  {
823  parent_rel->partial_pathlist =
824  foreach_delete_current(parent_rel->partial_pathlist, p1);
825  pfree(old_path);
826  }
827  else
828  {
829  /* new belongs after this old path if it has cost >= old's */
830  if (new_path->total_cost >= old_path->total_cost)
831  insert_at = foreach_current_index(p1) + 1;
832  }
833 
834  /*
835  * If we found an old path that dominates new_path, we can quit
836  * scanning the partial_pathlist; we will not add new_path, and we
837  * assume new_path cannot dominate any later path.
838  */
839  if (!accept_new)
840  break;
841  }
842 
843  if (accept_new)
844  {
845  /* Accept the new path: insert it at proper place */
846  parent_rel->partial_pathlist =
847  list_insert_nth(parent_rel->partial_pathlist, insert_at, new_path);
848  }
849  else
850  {
851  /* Reject and recycle the new path */
852  pfree(new_path);
853  }
854 }
Assert(fmt[strlen(fmt) - 1] !='\n')
List * list_insert_nth(List *list, int pos, void *datum)
Definition: list.c:438
void pfree(void *pointer)
Definition: mcxt.c:1456
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:121
PathKeysComparison compare_pathkeys(List *keys1, List *keys2)
Definition: pathkeys.c:301
#define STD_FUZZ_FACTOR
Definition: pathnode.c:51
PathKeysComparison
Definition: paths.h:197
@ PATHKEYS_BETTER2
Definition: paths.h:200
@ PATHKEYS_BETTER1
Definition: paths.h:199
@ PATHKEYS_DIFFERENT
Definition: paths.h:201
#define lfirst(lc)
Definition: pg_list.h:172
#define foreach_delete_current(lst, cell)
Definition: pg_list.h:390
#define foreach_current_index(cell)
Definition: pg_list.h:403
List * pathkeys
Definition: pathnodes.h:1633
Cost total_cost
Definition: pathnodes.h:1630
bool parallel_safe
Definition: pathnodes.h:1623
bool consider_parallel
Definition: pathnodes.h:872
List * partial_pathlist
Definition: pathnodes.h:885

References Assert(), CHECK_FOR_INTERRUPTS, compare_pathkeys(), RelOptInfo::consider_parallel, foreach_current_index, foreach_delete_current, lfirst, list_insert_nth(), Path::parallel_safe, RelOptInfo::partial_pathlist, Path::pathkeys, PATHKEYS_BETTER1, PATHKEYS_BETTER2, PATHKEYS_DIFFERENT, pfree(), STD_FUZZ_FACTOR, and Path::total_cost.

Referenced by add_paths_to_append_rel(), build_index_paths(), create_partial_bitmap_paths(), create_partial_distinct_paths(), create_partial_grouping_paths(), create_plain_partial_paths(), grouping_planner(), recurse_set_operations(), set_subquery_pathlist(), try_partial_hashjoin_path(), try_partial_mergejoin_path(), and try_partial_nestloop_path().

◆ add_partial_path_precheck()

bool add_partial_path_precheck ( RelOptInfo parent_rel,
Cost  total_cost,
List pathkeys 
)

Definition at line 867 of file pathnode.c.

869 {
870  ListCell *p1;
871 
872  /*
873  * Our goal here is twofold. First, we want to find out whether this path
874  * is clearly inferior to some existing partial path. If so, we want to
875  * reject it immediately. Second, we want to find out whether this path
876  * is clearly superior to some existing partial path -- at least, modulo
877  * final cost computations. If so, we definitely want to consider it.
878  *
879  * Unlike add_path(), we always compare pathkeys here. This is because we
880  * expect partial_pathlist to be very short, and getting a definitive
881  * answer at this stage avoids the need to call add_path_precheck.
882  */
883  foreach(p1, parent_rel->partial_pathlist)
884  {
885  Path *old_path = (Path *) lfirst(p1);
886  PathKeysComparison keyscmp;
887 
888  keyscmp = compare_pathkeys(pathkeys, old_path->pathkeys);
889  if (keyscmp != PATHKEYS_DIFFERENT)
890  {
891  if (total_cost > old_path->total_cost * STD_FUZZ_FACTOR &&
892  keyscmp != PATHKEYS_BETTER1)
893  return false;
894  if (old_path->total_cost > total_cost * STD_FUZZ_FACTOR &&
895  keyscmp != PATHKEYS_BETTER2)
896  return true;
897  }
898  }
899 
900  /*
901  * This path is neither clearly inferior to an existing partial path nor
902  * clearly good enough that it might replace one. Compare it to
903  * non-parallel plans. If it loses even before accounting for the cost of
904  * the Gather node, we should definitely reject it.
905  *
906  * Note that we pass the total_cost to add_path_precheck twice. This is
907  * because it's never advantageous to consider the startup cost of a
908  * partial path; the resulting plans, if run in parallel, will be run to
909  * completion.
910  */
911  if (!add_path_precheck(parent_rel, total_cost, total_cost, pathkeys,
912  NULL))
913  return false;
914 
915  return true;
916 }
bool add_path_precheck(RelOptInfo *parent_rel, Cost startup_cost, Cost total_cost, List *pathkeys, Relids required_outer)
Definition: pathnode.c:644

References add_path_precheck(), compare_pathkeys(), lfirst, RelOptInfo::partial_pathlist, Path::pathkeys, PATHKEYS_BETTER1, PATHKEYS_BETTER2, PATHKEYS_DIFFERENT, STD_FUZZ_FACTOR, and Path::total_cost.

Referenced by try_partial_hashjoin_path(), try_partial_mergejoin_path(), and try_partial_nestloop_path().

◆ add_path()

void add_path ( RelOptInfo parent_rel,
Path new_path 
)

Definition at line 422 of file pathnode.c.

423 {
424  bool accept_new = true; /* unless we find a superior old path */
425  int insert_at = 0; /* where to insert new item */
426  List *new_path_pathkeys;
427  ListCell *p1;
428 
429  /*
430  * This is a convenient place to check for query cancel --- no part of the
431  * planner goes very long without calling add_path().
432  */
434 
435  /* Pretend parameterized paths have no pathkeys, per comment above */
436  new_path_pathkeys = new_path->param_info ? NIL : new_path->pathkeys;
437 
438  /*
439  * Loop to check proposed new path against old paths. Note it is possible
440  * for more than one old path to be tossed out because new_path dominates
441  * it.
442  */
443  foreach(p1, parent_rel->pathlist)
444  {
445  Path *old_path = (Path *) lfirst(p1);
446  bool remove_old = false; /* unless new proves superior */
447  PathCostComparison costcmp;
448  PathKeysComparison keyscmp;
449  BMS_Comparison outercmp;
450 
451  /*
452  * Do a fuzzy cost comparison with standard fuzziness limit.
453  */
454  costcmp = compare_path_costs_fuzzily(new_path, old_path,
456 
457  /*
458  * If the two paths compare differently for startup and total cost,
459  * then we want to keep both, and we can skip comparing pathkeys and
460  * required_outer rels. If they compare the same, proceed with the
461  * other comparisons. Row count is checked last. (We make the tests
462  * in this order because the cost comparison is most likely to turn
463  * out "different", and the pathkeys comparison next most likely. As
464  * explained above, row count very seldom makes a difference, so even
465  * though it's cheap to compare there's not much point in checking it
466  * earlier.)
467  */
468  if (costcmp != COSTS_DIFFERENT)
469  {
470  /* Similarly check to see if either dominates on pathkeys */
471  List *old_path_pathkeys;
472 
473  old_path_pathkeys = old_path->param_info ? NIL : old_path->pathkeys;
474  keyscmp = compare_pathkeys(new_path_pathkeys,
475  old_path_pathkeys);
476  if (keyscmp != PATHKEYS_DIFFERENT)
477  {
478  switch (costcmp)
479  {
480  case COSTS_EQUAL:
481  outercmp = bms_subset_compare(PATH_REQ_OUTER(new_path),
482  PATH_REQ_OUTER(old_path));
483  if (keyscmp == PATHKEYS_BETTER1)
484  {
485  if ((outercmp == BMS_EQUAL ||
486  outercmp == BMS_SUBSET1) &&
487  new_path->rows <= old_path->rows &&
488  new_path->parallel_safe >= old_path->parallel_safe)
489  remove_old = true; /* new dominates old */
490  }
491  else if (keyscmp == PATHKEYS_BETTER2)
492  {
493  if ((outercmp == BMS_EQUAL ||
494  outercmp == BMS_SUBSET2) &&
495  new_path->rows >= old_path->rows &&
496  new_path->parallel_safe <= old_path->parallel_safe)
497  accept_new = false; /* old dominates new */
498  }
499  else /* keyscmp == PATHKEYS_EQUAL */
500  {
501  if (outercmp == BMS_EQUAL)
502  {
503  /*
504  * Same pathkeys and outer rels, and fuzzily
505  * the same cost, so keep just one; to decide
506  * which, first check parallel-safety, then
507  * rows, then do a fuzzy cost comparison with
508  * very small fuzz limit. (We used to do an
509  * exact cost comparison, but that results in
510  * annoying platform-specific plan variations
511  * due to roundoff in the cost estimates.) If
512  * things are still tied, arbitrarily keep
513  * only the old path. Notice that we will
514  * keep only the old path even if the
515  * less-fuzzy comparison decides the startup
516  * and total costs compare differently.
517  */
518  if (new_path->parallel_safe >
519  old_path->parallel_safe)
520  remove_old = true; /* new dominates old */
521  else if (new_path->parallel_safe <
522  old_path->parallel_safe)
523  accept_new = false; /* old dominates new */
524  else if (new_path->rows < old_path->rows)
525  remove_old = true; /* new dominates old */
526  else if (new_path->rows > old_path->rows)
527  accept_new = false; /* old dominates new */
528  else if (compare_path_costs_fuzzily(new_path,
529  old_path,
530  1.0000000001) == COSTS_BETTER1)
531  remove_old = true; /* new dominates old */
532  else
533  accept_new = false; /* old equals or
534  * dominates new */
535  }
536  else if (outercmp == BMS_SUBSET1 &&
537  new_path->rows <= old_path->rows &&
538  new_path->parallel_safe >= old_path->parallel_safe)
539  remove_old = true; /* new dominates old */
540  else if (outercmp == BMS_SUBSET2 &&
541  new_path->rows >= old_path->rows &&
542  new_path->parallel_safe <= old_path->parallel_safe)
543  accept_new = false; /* old dominates new */
544  /* else different parameterizations, keep both */
545  }
546  break;
547  case COSTS_BETTER1:
548  if (keyscmp != PATHKEYS_BETTER2)
549  {
550  outercmp = bms_subset_compare(PATH_REQ_OUTER(new_path),
551  PATH_REQ_OUTER(old_path));
552  if ((outercmp == BMS_EQUAL ||
553  outercmp == BMS_SUBSET1) &&
554  new_path->rows <= old_path->rows &&
555  new_path->parallel_safe >= old_path->parallel_safe)
556  remove_old = true; /* new dominates old */
557  }
558  break;
559  case COSTS_BETTER2:
560  if (keyscmp != PATHKEYS_BETTER1)
561  {
562  outercmp = bms_subset_compare(PATH_REQ_OUTER(new_path),
563  PATH_REQ_OUTER(old_path));
564  if ((outercmp == BMS_EQUAL ||
565  outercmp == BMS_SUBSET2) &&
566  new_path->rows >= old_path->rows &&
567  new_path->parallel_safe <= old_path->parallel_safe)
568  accept_new = false; /* old dominates new */
569  }
570  break;
571  case COSTS_DIFFERENT:
572 
573  /*
574  * can't get here, but keep this case to keep compiler
575  * quiet
576  */
577  break;
578  }
579  }
580  }
581 
582  /*
583  * Remove current element from pathlist if dominated by new.
584  */
585  if (remove_old)
586  {
587  parent_rel->pathlist = foreach_delete_current(parent_rel->pathlist,
588  p1);
589 
590  /*
591  * Delete the data pointed-to by the deleted cell, if possible
592  */
593  if (!IsA(old_path, IndexPath))
594  pfree(old_path);
595  }
596  else
597  {
598  /* new belongs after this old path if it has cost >= old's */
599  if (new_path->total_cost >= old_path->total_cost)
600  insert_at = foreach_current_index(p1) + 1;
601  }
602 
603  /*
604  * If we found an old path that dominates new_path, we can quit
605  * scanning the pathlist; we will not add new_path, and we assume
606  * new_path cannot dominate any other elements of the pathlist.
607  */
608  if (!accept_new)
609  break;
610  }
611 
612  if (accept_new)
613  {
614  /* Accept the new path: insert it at proper place in pathlist */
615  parent_rel->pathlist =
616  list_insert_nth(parent_rel->pathlist, insert_at, new_path);
617  }
618  else
619  {
620  /* Reject and recycle the new path */
621  if (!IsA(new_path, IndexPath))
622  pfree(new_path);
623  }
624 }
BMS_Comparison bms_subset_compare(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:396
BMS_Comparison
Definition: bitmapset.h:61
@ BMS_SUBSET1
Definition: bitmapset.h:63
@ BMS_EQUAL
Definition: bitmapset.h:62
@ BMS_SUBSET2
Definition: bitmapset.h:64
#define IsA(nodeptr, _type_)
Definition: nodes.h:179
static PathCostComparison compare_path_costs_fuzzily(Path *path1, Path *path2, double fuzz_factor)
Definition: pathnode.c:166
PathCostComparison
Definition: pathnode.c:39
@ COSTS_EQUAL
Definition: pathnode.c:40
@ COSTS_BETTER1
Definition: pathnode.c:41
@ COSTS_BETTER2
Definition: pathnode.c:42
@ COSTS_DIFFERENT
Definition: pathnode.c:43
#define PATH_REQ_OUTER(path)
Definition: pathnodes.h:1637
#define NIL
Definition: pg_list.h:68
Definition: pg_list.h:54
Cardinality rows
Definition: pathnodes.h:1628
List * pathlist
Definition: pathnodes.h:883

References BMS_EQUAL, BMS_SUBSET1, BMS_SUBSET2, bms_subset_compare(), CHECK_FOR_INTERRUPTS, compare_path_costs_fuzzily(), compare_pathkeys(), COSTS_BETTER1, COSTS_BETTER2, COSTS_DIFFERENT, COSTS_EQUAL, foreach_current_index, foreach_delete_current, IsA, lfirst, list_insert_nth(), NIL, Path::parallel_safe, PATH_REQ_OUTER, Path::pathkeys, PATHKEYS_BETTER1, PATHKEYS_BETTER2, PATHKEYS_DIFFERENT, RelOptInfo::pathlist, pfree(), Path::rows, STD_FUZZ_FACTOR, and Path::total_cost.

Referenced by add_foreign_final_paths(), add_foreign_grouping_paths(), add_foreign_ordered_paths(), add_paths_to_append_rel(), add_paths_to_grouping_rel(), add_paths_with_pathkeys_for_rel(), BuildParameterizedTidPaths(), consider_groupingsets_paths(), create_degenerate_grouping_paths(), create_final_distinct_paths(), create_index_paths(), create_one_window_path(), create_ordered_paths(), create_partial_grouping_paths(), create_tidscan_paths(), fileGetForeignPaths(), gather_grouping_paths(), generate_gather_paths(), generate_nonunion_paths(), generate_orderedappend_paths(), generate_recursion_path(), generate_union_paths(), generate_useful_gather_paths(), get_index_paths(), grouping_planner(), mark_dummy_rel(), postgresGetForeignJoinPaths(), postgresGetForeignPaths(), preprocess_minmax_aggregates(), query_planner(), recurse_set_operations(), set_cte_pathlist(), set_dummy_rel_pathlist(), set_function_pathlist(), set_namedtuplestore_pathlist(), set_plain_rel_pathlist(), set_result_pathlist(), set_subquery_pathlist(), set_tablefunc_pathlist(), set_tablesample_rel_pathlist(), set_values_pathlist(), set_worktable_pathlist(), try_hashjoin_path(), try_mergejoin_path(), and try_nestloop_path().

◆ add_path_precheck()

bool add_path_precheck ( RelOptInfo parent_rel,
Cost  startup_cost,
Cost  total_cost,
List pathkeys,
Relids  required_outer 
)

Definition at line 644 of file pathnode.c.

647 {
648  List *new_path_pathkeys;
649  bool consider_startup;
650  ListCell *p1;
651 
652  /* Pretend parameterized paths have no pathkeys, per add_path policy */
653  new_path_pathkeys = required_outer ? NIL : pathkeys;
654 
655  /* Decide whether new path's startup cost is interesting */
656  consider_startup = required_outer ? parent_rel->consider_param_startup : parent_rel->consider_startup;
657 
658  foreach(p1, parent_rel->pathlist)
659  {
660  Path *old_path = (Path *) lfirst(p1);
661  PathKeysComparison keyscmp;
662 
663  /*
664  * We are looking for an old_path with the same parameterization (and
665  * by assumption the same rowcount) that dominates the new path on
666  * pathkeys as well as both cost metrics. If we find one, we can
667  * reject the new path.
668  *
669  * Cost comparisons here should match compare_path_costs_fuzzily.
670  */
671  if (total_cost > old_path->total_cost * STD_FUZZ_FACTOR)
672  {
673  /* new path can win on startup cost only if consider_startup */
674  if (startup_cost > old_path->startup_cost * STD_FUZZ_FACTOR ||
675  !consider_startup)
676  {
677  /* new path loses on cost, so check pathkeys... */
678  List *old_path_pathkeys;
679 
680  old_path_pathkeys = old_path->param_info ? NIL : old_path->pathkeys;
681  keyscmp = compare_pathkeys(new_path_pathkeys,
682  old_path_pathkeys);
683  if (keyscmp == PATHKEYS_EQUAL ||
684  keyscmp == PATHKEYS_BETTER2)
685  {
686  /* new path does not win on pathkeys... */
687  if (bms_equal(required_outer, PATH_REQ_OUTER(old_path)))
688  {
689  /* Found an old path that dominates the new one */
690  return false;
691  }
692  }
693  }
694  }
695  else
696  {
697  /*
698  * Since the pathlist is sorted by total_cost, we can stop looking
699  * once we reach a path with a total_cost larger than the new
700  * path's.
701  */
702  break;
703  }
704  }
705 
706  return true;
707 }
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:97
@ PATHKEYS_EQUAL
Definition: paths.h:198
Cost startup_cost
Definition: pathnodes.h:1629
bool consider_param_startup
Definition: pathnodes.h:870
bool consider_startup
Definition: pathnodes.h:868

References bms_equal(), compare_pathkeys(), RelOptInfo::consider_param_startup, RelOptInfo::consider_startup, lfirst, NIL, PATH_REQ_OUTER, Path::pathkeys, PATHKEYS_BETTER2, PATHKEYS_EQUAL, RelOptInfo::pathlist, Path::startup_cost, STD_FUZZ_FACTOR, and Path::total_cost.

Referenced by add_partial_path_precheck(), try_hashjoin_path(), try_mergejoin_path(), and try_nestloop_path().

◆ adjust_limit_rows_costs()

void adjust_limit_rows_costs ( double *  rows,
Cost startup_cost,
Cost total_cost,
int64  offset_est,
int64  count_est 
)

Definition at line 3834 of file pathnode.c.

3839 {
3840  double input_rows = *rows;
3841  Cost input_startup_cost = *startup_cost;
3842  Cost input_total_cost = *total_cost;
3843 
3844  if (offset_est != 0)
3845  {
3846  double offset_rows;
3847 
3848  if (offset_est > 0)
3849  offset_rows = (double) offset_est;
3850  else
3851  offset_rows = clamp_row_est(input_rows * 0.10);
3852  if (offset_rows > *rows)
3853  offset_rows = *rows;
3854  if (input_rows > 0)
3855  *startup_cost +=
3856  (input_total_cost - input_startup_cost)
3857  * offset_rows / input_rows;
3858  *rows -= offset_rows;
3859  if (*rows < 1)
3860  *rows = 1;
3861  }
3862 
3863  if (count_est != 0)
3864  {
3865  double count_rows;
3866 
3867  if (count_est > 0)
3868  count_rows = (double) count_est;
3869  else
3870  count_rows = clamp_row_est(input_rows * 0.10);
3871  if (count_rows > *rows)
3872  count_rows = *rows;
3873  if (input_rows > 0)
3874  *total_cost = *startup_cost +
3875  (input_total_cost - input_startup_cost)
3876  * count_rows / input_rows;
3877  *rows = count_rows;
3878  if (*rows < 1)
3879  *rows = 1;
3880  }
3881 }
double clamp_row_est(double nrows)
Definition: costsize.c:203
double Cost
Definition: nodes.h:262

References clamp_row_est().

Referenced by create_limit_path(), and estimate_path_cost_size().

◆ apply_projection_to_path()

Path* apply_projection_to_path ( PlannerInfo root,
RelOptInfo rel,
Path path,
PathTarget target 
)

Definition at line 2752 of file pathnode.c.

2756 {
2757  QualCost oldcost;
2758 
2759  /*
2760  * If given path can't project, we might need a Result node, so make a
2761  * separate ProjectionPath.
2762  */
2763  if (!is_projection_capable_path(path))
2764  return (Path *) create_projection_path(root, rel, path, target);
2765 
2766  /*
2767  * We can just jam the desired tlist into the existing path, being sure to
2768  * update its cost estimates appropriately.
2769  */
2770  oldcost = path->pathtarget->cost;
2771  path->pathtarget = target;
2772 
2773  path->startup_cost += target->cost.startup - oldcost.startup;
2774  path->total_cost += target->cost.startup - oldcost.startup +
2775  (target->cost.per_tuple - oldcost.per_tuple) * path->rows;
2776 
2777  /*
2778  * If the path happens to be a Gather or GatherMerge path, we'd like to
2779  * arrange for the subpath to return the required target list so that
2780  * workers can help project. But if there is something that is not
2781  * parallel-safe in the target expressions, then we can't.
2782  */
2783  if ((IsA(path, GatherPath) || IsA(path, GatherMergePath)) &&
2784  is_parallel_safe(root, (Node *) target->exprs))
2785  {
2786  /*
2787  * We always use create_projection_path here, even if the subpath is
2788  * projection-capable, so as to avoid modifying the subpath in place.
2789  * It seems unlikely at present that there could be any other
2790  * references to the subpath, but better safe than sorry.
2791  *
2792  * Note that we don't change the parallel path's cost estimates; it
2793  * might be appropriate to do so, to reflect the fact that the bulk of
2794  * the target evaluation will happen in workers.
2795  */
2796  if (IsA(path, GatherPath))
2797  {
2798  GatherPath *gpath = (GatherPath *) path;
2799 
2800  gpath->subpath = (Path *)
2802  gpath->subpath->parent,
2803  gpath->subpath,
2804  target);
2805  }
2806  else
2807  {
2808  GatherMergePath *gmpath = (GatherMergePath *) path;
2809 
2810  gmpath->subpath = (Path *)
2812  gmpath->subpath->parent,
2813  gmpath->subpath,
2814  target);
2815  }
2816  }
2817  else if (path->parallel_safe &&
2818  !is_parallel_safe(root, (Node *) target->exprs))
2819  {
2820  /*
2821  * We're inserting a parallel-restricted target list into a path
2822  * currently marked parallel-safe, so we have to mark it as no longer
2823  * safe.
2824  */
2825  path->parallel_safe = false;
2826  }
2827 
2828  return path;
2829 }
bool is_parallel_safe(PlannerInfo *root, Node *node)
Definition: clauses.c:736
bool is_projection_capable_path(Path *path)
Definition: createplan.c:7177
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
ProjectionPath * create_projection_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target)
Definition: pathnode.c:2644
Path * subpath
Definition: pathnodes.h:2010
Definition: nodes.h:129
List * exprs
Definition: pathnodes.h:1501
QualCost cost
Definition: pathnodes.h:1507
Cost per_tuple
Definition: pathnodes.h:48
Cost startup
Definition: pathnodes.h:47

References PathTarget::cost, create_projection_path(), PathTarget::exprs, if(), is_parallel_safe(), is_projection_capable_path(), IsA, Path::parallel_safe, QualCost::per_tuple, Path::rows, QualCost::startup, Path::startup_cost, GatherPath::subpath, GatherMergePath::subpath, and Path::total_cost.

Referenced by adjust_paths_for_srfs(), build_minmax_path(), create_ordered_paths(), and recurse_set_operations().

◆ build_child_join_rel()

RelOptInfo* build_child_join_rel ( PlannerInfo root,
RelOptInfo outer_rel,
RelOptInfo inner_rel,
RelOptInfo parent_joinrel,
List restrictlist,
SpecialJoinInfo sjinfo 
)

Definition at line 858 of file relnode.c.

861 {
862  RelOptInfo *joinrel = makeNode(RelOptInfo);
863  AppendRelInfo **appinfos;
864  int nappinfos;
865 
866  /* Only joins between "other" relations land here. */
867  Assert(IS_OTHER_REL(outer_rel) && IS_OTHER_REL(inner_rel));
868 
869  /* The parent joinrel should have consider_partitionwise_join set. */
870  Assert(parent_joinrel->consider_partitionwise_join);
871 
872  /*
873  * Find the AppendRelInfo structures for the child baserels. We'll need
874  * these for computing the child join's relid set, and later for mapping
875  * Vars to the child rel.
876  */
877  appinfos = find_appinfos_by_relids(root,
878  bms_union(outer_rel->relids,
879  inner_rel->relids),
880  &nappinfos);
881 
882  joinrel->reloptkind = RELOPT_OTHER_JOINREL;
883  joinrel->relids = adjust_child_relids(parent_joinrel->relids,
884  nappinfos, appinfos);
885  joinrel->rows = 0;
886  /* cheap startup cost is interesting iff not all tuples to be retrieved */
887  joinrel->consider_startup = (root->tuple_fraction > 0);
888  joinrel->consider_param_startup = false;
889  joinrel->consider_parallel = false;
890  joinrel->reltarget = create_empty_pathtarget();
891  joinrel->pathlist = NIL;
892  joinrel->ppilist = NIL;
893  joinrel->partial_pathlist = NIL;
894  joinrel->cheapest_startup_path = NULL;
895  joinrel->cheapest_total_path = NULL;
896  joinrel->cheapest_unique_path = NULL;
898  joinrel->direct_lateral_relids = NULL;
899  joinrel->lateral_relids = NULL;
900  joinrel->relid = 0; /* indicates not a baserel */
901  joinrel->rtekind = RTE_JOIN;
902  joinrel->min_attr = 0;
903  joinrel->max_attr = 0;
904  joinrel->attr_needed = NULL;
905  joinrel->attr_widths = NULL;
906  joinrel->nulling_relids = NULL;
907  joinrel->lateral_vars = NIL;
908  joinrel->lateral_referencers = NULL;
909  joinrel->indexlist = NIL;
910  joinrel->pages = 0;
911  joinrel->tuples = 0;
912  joinrel->allvisfrac = 0;
913  joinrel->eclass_indexes = NULL;
914  joinrel->subroot = NULL;
915  joinrel->subplan_params = NIL;
916  joinrel->amflags = 0;
917  joinrel->serverid = InvalidOid;
918  joinrel->userid = InvalidOid;
919  joinrel->useridiscurrent = false;
920  joinrel->fdwroutine = NULL;
921  joinrel->fdw_private = NULL;
922  joinrel->baserestrictinfo = NIL;
923  joinrel->baserestrictcost.startup = 0;
924  joinrel->baserestrictcost.per_tuple = 0;
925  joinrel->joininfo = NIL;
926  joinrel->has_eclass_joins = false;
927  joinrel->consider_partitionwise_join = false; /* might get changed later */
928  joinrel->parent = parent_joinrel;
929  joinrel->top_parent = parent_joinrel->top_parent ? parent_joinrel->top_parent : parent_joinrel;
930  joinrel->top_parent_relids = joinrel->top_parent->relids;
931  joinrel->part_scheme = NULL;
932  joinrel->nparts = -1;
933  joinrel->boundinfo = NULL;
934  joinrel->partbounds_merged = false;
935  joinrel->partition_qual = NIL;
936  joinrel->part_rels = NULL;
937  joinrel->live_parts = NULL;
938  joinrel->all_partrels = NULL;
939  joinrel->partexprs = NULL;
940  joinrel->nullable_partexprs = NULL;
941 
942  /* Compute information relevant to foreign relations. */
943  set_foreign_rel_properties(joinrel, outer_rel, inner_rel);
944 
945  /* Set up reltarget struct */
946  build_child_join_reltarget(root, parent_joinrel, joinrel,
947  nappinfos, appinfos);
948 
949  /* Construct joininfo list. */
950  joinrel->joininfo = (List *) adjust_appendrel_attrs(root,
951  (Node *) parent_joinrel->joininfo,
952  nappinfos,
953  appinfos);
954 
955  /*
956  * Lateral relids referred in child join will be same as that referred in
957  * the parent relation.
958  */
959  joinrel->direct_lateral_relids = (Relids) bms_copy(parent_joinrel->direct_lateral_relids);
960  joinrel->lateral_relids = (Relids) bms_copy(parent_joinrel->lateral_relids);
961 
962  /*
963  * If the parent joinrel has pending equivalence classes, so does the
964  * child.
965  */
966  joinrel->has_eclass_joins = parent_joinrel->has_eclass_joins;
967 
968  /* Is the join between partitions itself partitioned? */
969  build_joinrel_partition_info(root, joinrel, outer_rel, inner_rel, sjinfo,
970  restrictlist);
971 
972  /* Child joinrel is parallel safe if parent is parallel safe. */
973  joinrel->consider_parallel = parent_joinrel->consider_parallel;
974 
975  /* Set estimates of the child-joinrel's size. */
976  set_joinrel_size_estimates(root, joinrel, outer_rel, inner_rel,
977  sjinfo, restrictlist);
978 
979  /* We build the join only once. */
980  Assert(!find_join_rel(root, joinrel->relids));
981 
982  /* Add the relation to the PlannerInfo. */
983  add_join_rel(root, joinrel);
984 
985  /*
986  * We might need EquivalenceClass members corresponding to the child join,
987  * so that we can represent sort pathkeys for it. As with children of
988  * baserels, we shouldn't need this unless there are relevant eclass joins
989  * (implying that a merge join might be possible) or pathkeys to sort by.
990  */
991  if (joinrel->has_eclass_joins || has_useful_pathkeys(root, parent_joinrel))
993  nappinfos, appinfos,
994  parent_joinrel, joinrel);
995 
996  pfree(appinfos);
997 
998  return joinrel;
999 }
AppendRelInfo ** find_appinfos_by_relids(PlannerInfo *root, Relids relids, int *nappinfos)
Definition: appendinfo.c:733
Node * adjust_appendrel_attrs(PlannerInfo *root, Node *node, int nappinfos, AppendRelInfo **appinfos)
Definition: appendinfo.c:196
Relids adjust_child_relids(Relids relids, int nappinfos, AppendRelInfo **appinfos)
Definition: appendinfo.c:554
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:211
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:80
void set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo, List *restrictlist)
Definition: costsize.c:5320
void add_child_join_rel_equivalences(PlannerInfo *root, int nappinfos, AppendRelInfo **appinfos, RelOptInfo *parent_joinrel, RelOptInfo *child_joinrel)
Definition: equivclass.c:2743
#define makeNode(_type_)
Definition: nodes.h:176
@ RTE_JOIN
Definition: parsenodes.h:1008
bool has_useful_pathkeys(PlannerInfo *root, RelOptInfo *rel)
Definition: pathkeys.c:1987
Bitmapset * Relids
Definition: pathnodes.h:30
@ RELOPT_OTHER_JOINREL
Definition: pathnodes.h:815
#define IS_OTHER_REL(rel)
Definition: pathnodes.h:839
#define InvalidOid
Definition: postgres_ext.h:36
static void build_joinrel_partition_info(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo, List *restrictlist)
Definition: relnode.c:1978
RelOptInfo * find_join_rel(PlannerInfo *root, Relids relids)
Definition: relnode.c:505
static void build_child_join_reltarget(PlannerInfo *root, RelOptInfo *parentrel, RelOptInfo *childrel, int nappinfos, AppendRelInfo **appinfos)
Definition: relnode.c:2386
static void set_foreign_rel_properties(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
Definition: relnode.c:567
static void add_join_rel(PlannerInfo *root, RelOptInfo *joinrel)
Definition: relnode.c:605
Selectivity tuple_fraction
Definition: pathnodes.h:478
List * baserestrictinfo
Definition: pathnodes.h:964
List * subplan_params
Definition: pathnodes.h:933
List * ppilist
Definition: pathnodes.h:884
bool useridiscurrent
Definition: pathnodes.h:947
uint32 amflags
Definition: pathnodes.h:937
List * joininfo
Definition: pathnodes.h:970
List * partition_qual
Definition: pathnodes.h:1006
Relids relids
Definition: pathnodes.h:856
struct PathTarget * reltarget
Definition: pathnodes.h:878
Index relid
Definition: pathnodes.h:903
List * lateral_vars
Definition: pathnodes.h:919
Cardinality tuples
Definition: pathnodes.h:928
Relids top_parent_relids
Definition: pathnodes.h:988
bool partbounds_merged
Definition: pathnodes.h:1004
BlockNumber pages
Definition: pathnodes.h:927
Relids lateral_relids
Definition: pathnodes.h:898
List * cheapest_parameterized_paths
Definition: pathnodes.h:889
RelOptKind reloptkind
Definition: pathnodes.h:850
List * indexlist
Definition: pathnodes.h:923
struct Path * cheapest_unique_path
Definition: pathnodes.h:888
Relids lateral_referencers
Definition: pathnodes.h:921
struct Path * cheapest_startup_path
Definition: pathnodes.h:886
QualCost baserestrictcost
Definition: pathnodes.h:966
struct Path * cheapest_total_path
Definition: pathnodes.h:887
Oid userid
Definition: pathnodes.h:945
Bitmapset * eclass_indexes
Definition: pathnodes.h:931
Relids all_partrels
Definition: pathnodes.h:1020
Relids direct_lateral_relids
Definition: pathnodes.h:896
bool has_eclass_joins
Definition: pathnodes.h:972
Oid serverid
Definition: pathnodes.h:943
Bitmapset * live_parts
Definition: pathnodes.h:1018
bool consider_partitionwise_join
Definition: pathnodes.h:978
PlannerInfo * subroot
Definition: pathnodes.h:932
AttrNumber max_attr
Definition: pathnodes.h:911
Relids nulling_relids
Definition: pathnodes.h:917
double allvisfrac
Definition: pathnodes.h:929
Cardinality rows
Definition: pathnodes.h:862
AttrNumber min_attr
Definition: pathnodes.h:909
RTEKind rtekind
Definition: pathnodes.h:907
PathTarget * create_empty_pathtarget(void)
Definition: tlist.c:681

References add_child_join_rel_equivalences(), add_join_rel(), adjust_appendrel_attrs(), adjust_child_relids(), RelOptInfo::all_partrels, RelOptInfo::allvisfrac, RelOptInfo::amflags, Assert(), RelOptInfo::baserestrictcost, RelOptInfo::baserestrictinfo, bms_copy(), bms_union(), build_child_join_reltarget(), build_joinrel_partition_info(), RelOptInfo::cheapest_parameterized_paths, RelOptInfo::cheapest_startup_path, RelOptInfo::cheapest_total_path, RelOptInfo::cheapest_unique_path, RelOptInfo::consider_parallel, RelOptInfo::consider_param_startup, RelOptInfo::consider_partitionwise_join, RelOptInfo::consider_startup, create_empty_pathtarget(), RelOptInfo::direct_lateral_relids, RelOptInfo::eclass_indexes, find_appinfos_by_relids(), find_join_rel(), RelOptInfo::has_eclass_joins, has_useful_pathkeys(), RelOptInfo::indexlist, InvalidOid, IS_OTHER_REL, RelOptInfo::joininfo, RelOptInfo::lateral_referencers, RelOptInfo::lateral_relids, RelOptInfo::lateral_vars, RelOptInfo::live_parts, makeNode, RelOptInfo::max_attr, RelOptInfo::min_attr, NIL, RelOptInfo::nparts, RelOptInfo::nulling_relids, RelOptInfo::pages, RelOptInfo::partbounds_merged, RelOptInfo::partial_pathlist, RelOptInfo::partition_qual, RelOptInfo::pathlist, QualCost::per_tuple, pfree(), RelOptInfo::ppilist, RelOptInfo::relid, RelOptInfo::relids, RELOPT_OTHER_JOINREL, RelOptInfo::reloptkind, RelOptInfo::reltarget, RelOptInfo::rows, RTE_JOIN, RelOptInfo::rtekind, RelOptInfo::serverid, set_foreign_rel_properties(), set_joinrel_size_estimates(), QualCost::startup, RelOptInfo::subplan_params, RelOptInfo::subroot, RelOptInfo::top_parent_relids, PlannerInfo::tuple_fraction, RelOptInfo::tuples, RelOptInfo::userid, and RelOptInfo::useridiscurrent.

Referenced by try_partitionwise_join().

◆ build_join_rel()

RelOptInfo* build_join_rel ( PlannerInfo root,
Relids  joinrelids,
RelOptInfo outer_rel,
RelOptInfo inner_rel,
SpecialJoinInfo sjinfo,
List pushed_down_joins,
List **  restrictlist_ptr 
)

Definition at line 643 of file relnode.c.

650 {
651  RelOptInfo *joinrel;
652  List *restrictlist;
653 
654  /* This function should be used only for join between parents. */
655  Assert(!IS_OTHER_REL(outer_rel) && !IS_OTHER_REL(inner_rel));
656 
657  /*
658  * See if we already have a joinrel for this set of base rels.
659  */
660  joinrel = find_join_rel(root, joinrelids);
661 
662  if (joinrel)
663  {
664  /*
665  * Yes, so we only need to figure the restrictlist for this particular
666  * pair of component relations.
667  */
668  if (restrictlist_ptr)
669  *restrictlist_ptr = build_joinrel_restrictlist(root,
670  joinrel,
671  outer_rel,
672  inner_rel,
673  sjinfo);
674  return joinrel;
675  }
676 
677  /*
678  * Nope, so make one.
679  */
680  joinrel = makeNode(RelOptInfo);
681  joinrel->reloptkind = RELOPT_JOINREL;
682  joinrel->relids = bms_copy(joinrelids);
683  joinrel->rows = 0;
684  /* cheap startup cost is interesting iff not all tuples to be retrieved */
685  joinrel->consider_startup = (root->tuple_fraction > 0);
686  joinrel->consider_param_startup = false;
687  joinrel->consider_parallel = false;
688  joinrel->reltarget = create_empty_pathtarget();
689  joinrel->pathlist = NIL;
690  joinrel->ppilist = NIL;
691  joinrel->partial_pathlist = NIL;
692  joinrel->cheapest_startup_path = NULL;
693  joinrel->cheapest_total_path = NULL;
694  joinrel->cheapest_unique_path = NULL;
696  /* init direct_lateral_relids from children; we'll finish it up below */
697  joinrel->direct_lateral_relids =
698  bms_union(outer_rel->direct_lateral_relids,
699  inner_rel->direct_lateral_relids);
700  joinrel->lateral_relids = min_join_parameterization(root, joinrel->relids,
701  outer_rel, inner_rel);
702  joinrel->relid = 0; /* indicates not a baserel */
703  joinrel->rtekind = RTE_JOIN;
704  joinrel->min_attr = 0;
705  joinrel->max_attr = 0;
706  joinrel->attr_needed = NULL;
707  joinrel->attr_widths = NULL;
708  joinrel->nulling_relids = NULL;
709  joinrel->lateral_vars = NIL;
710  joinrel->lateral_referencers = NULL;
711  joinrel->indexlist = NIL;
712  joinrel->statlist = NIL;
713  joinrel->pages = 0;
714  joinrel->tuples = 0;
715  joinrel->allvisfrac = 0;
716  joinrel->eclass_indexes = NULL;
717  joinrel->subroot = NULL;
718  joinrel->subplan_params = NIL;
719  joinrel->rel_parallel_workers = -1;
720  joinrel->amflags = 0;
721  joinrel->serverid = InvalidOid;
722  joinrel->userid = InvalidOid;
723  joinrel->useridiscurrent = false;
724  joinrel->fdwroutine = NULL;
725  joinrel->fdw_private = NULL;
726  joinrel->unique_for_rels = NIL;
727  joinrel->non_unique_for_rels = NIL;
728  joinrel->baserestrictinfo = NIL;
729  joinrel->baserestrictcost.startup = 0;
730  joinrel->baserestrictcost.per_tuple = 0;
731  joinrel->baserestrict_min_security = UINT_MAX;
732  joinrel->joininfo = NIL;
733  joinrel->has_eclass_joins = false;
734  joinrel->consider_partitionwise_join = false; /* might get changed later */
735  joinrel->parent = NULL;
736  joinrel->top_parent = NULL;
737  joinrel->top_parent_relids = NULL;
738  joinrel->part_scheme = NULL;
739  joinrel->nparts = -1;
740  joinrel->boundinfo = NULL;
741  joinrel->partbounds_merged = false;
742  joinrel->partition_qual = NIL;
743  joinrel->part_rels = NULL;
744  joinrel->live_parts = NULL;
745  joinrel->all_partrels = NULL;
746  joinrel->partexprs = NULL;
747  joinrel->nullable_partexprs = NULL;
748 
749  /* Compute information relevant to the foreign relations. */
750  set_foreign_rel_properties(joinrel, outer_rel, inner_rel);
751 
752  /*
753  * Fill the joinrel's tlist with just the Vars and PHVs that need to be
754  * output from this join (ie, are needed for higher joinclauses or final
755  * output).
756  *
757  * NOTE: the tlist order for a join rel will depend on which pair of outer
758  * and inner rels we first try to build it from. But the contents should
759  * be the same regardless.
760  */
761  build_joinrel_tlist(root, joinrel, outer_rel, sjinfo, pushed_down_joins,
762  (sjinfo->jointype == JOIN_FULL));
763  build_joinrel_tlist(root, joinrel, inner_rel, sjinfo, pushed_down_joins,
764  (sjinfo->jointype != JOIN_INNER));
765  add_placeholders_to_joinrel(root, joinrel, outer_rel, inner_rel, sjinfo);
766 
767  /*
768  * add_placeholders_to_joinrel also took care of adding the ph_lateral
769  * sets of any PlaceHolderVars computed here to direct_lateral_relids, so
770  * now we can finish computing that. This is much like the computation of
771  * the transitively-closed lateral_relids in min_join_parameterization,
772  * except that here we *do* have to consider the added PHVs.
773  */
774  joinrel->direct_lateral_relids =
775  bms_del_members(joinrel->direct_lateral_relids, joinrel->relids);
776 
777  /*
778  * Construct restrict and join clause lists for the new joinrel. (The
779  * caller might or might not need the restrictlist, but I need it anyway
780  * for set_joinrel_size_estimates().)
781  */
782  restrictlist = build_joinrel_restrictlist(root, joinrel,
783  outer_rel, inner_rel,
784  sjinfo);
785  if (restrictlist_ptr)
786  *restrictlist_ptr = restrictlist;
787  build_joinrel_joinlist(joinrel, outer_rel, inner_rel);
788 
789  /*
790  * This is also the right place to check whether the joinrel has any
791  * pending EquivalenceClass joins.
792  */
793  joinrel->has_eclass_joins = has_relevant_eclass_joinclause(root, joinrel);
794 
795  /* Store the partition information. */
796  build_joinrel_partition_info(root, joinrel, outer_rel, inner_rel, sjinfo,
797  restrictlist);
798 
799  /*
800  * Set estimates of the joinrel's size.
801  */
802  set_joinrel_size_estimates(root, joinrel, outer_rel, inner_rel,
803  sjinfo, restrictlist);
804 
805  /*
806  * Set the consider_parallel flag if this joinrel could potentially be
807  * scanned within a parallel worker. If this flag is false for either
808  * inner_rel or outer_rel, then it must be false for the joinrel also.
809  * Even if both are true, there might be parallel-restricted expressions
810  * in the targetlist or quals.
811  *
812  * Note that if there are more than two rels in this relation, they could
813  * be divided between inner_rel and outer_rel in any arbitrary way. We
814  * assume this doesn't matter, because we should hit all the same baserels
815  * and joinclauses while building up to this joinrel no matter which we
816  * take; therefore, we should make the same decision here however we get
817  * here.
818  */
819  if (inner_rel->consider_parallel && outer_rel->consider_parallel &&
820  is_parallel_safe(root, (Node *) restrictlist) &&
821  is_parallel_safe(root, (Node *) joinrel->reltarget->exprs))
822  joinrel->consider_parallel = true;
823 
824  /* Add the joinrel to the PlannerInfo. */
825  add_join_rel(root, joinrel);
826 
827  /*
828  * Also, if dynamic-programming join search is active, add the new joinrel
829  * to the appropriate sublist. Note: you might think the Assert on number
830  * of members should be for equality, but some of the level 1 rels might
831  * have been joinrels already, so we can only assert <=.
832  */
833  if (root->join_rel_level)
834  {
835  Assert(root->join_cur_level > 0);
836  Assert(root->join_cur_level <= bms_num_members(joinrel->relids));
837  root->join_rel_level[root->join_cur_level] =
838  lappend(root->join_rel_level[root->join_cur_level], joinrel);
839  }
840 
841  return joinrel;
842 }
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:685
Bitmapset * bms_del_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:993
bool has_relevant_eclass_joinclause(PlannerInfo *root, RelOptInfo *rel1)
Definition: equivclass.c:3092
List * lappend(List *list, void *datum)
Definition: list.c:338
@ JOIN_FULL
Definition: nodes.h:306
@ JOIN_INNER
Definition: nodes.h:304
@ RELOPT_JOINREL
Definition: pathnodes.h:813
void add_placeholders_to_joinrel(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo)
Definition: placeholder.c:373
static void build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *input_rel, SpecialJoinInfo *sjinfo, List *pushed_down_joins, bool can_null)
Definition: relnode.c:1088
Relids min_join_parameterization(PlannerInfo *root, Relids joinrelids, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
Definition: relnode.c:1010
static List * build_joinrel_restrictlist(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo)
Definition: relnode.c:1270
static void build_joinrel_joinlist(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
Definition: relnode.c:1307
int join_cur_level
Definition: pathnodes.h:293
List * statlist
Definition: pathnodes.h:925
List * unique_for_rels
Definition: pathnodes.h:956
List * non_unique_for_rels
Definition: pathnodes.h:958
int rel_parallel_workers
Definition: pathnodes.h:935
Index baserestrict_min_security
Definition: pathnodes.h:968
JoinType jointype
Definition: pathnodes.h:2857

References add_join_rel(), add_placeholders_to_joinrel(), RelOptInfo::all_partrels, RelOptInfo::allvisfrac, RelOptInfo::amflags, Assert(), RelOptInfo::baserestrict_min_security, RelOptInfo::baserestrictcost, RelOptInfo::baserestrictinfo, bms_copy(), bms_del_members(), bms_num_members(), bms_union(), build_joinrel_joinlist(), build_joinrel_partition_info(), build_joinrel_restrictlist(), build_joinrel_tlist(), RelOptInfo::cheapest_parameterized_paths, RelOptInfo::cheapest_startup_path, RelOptInfo::cheapest_total_path, RelOptInfo::cheapest_unique_path, RelOptInfo::consider_parallel, RelOptInfo::consider_param_startup, RelOptInfo::consider_partitionwise_join, RelOptInfo::consider_startup, create_empty_pathtarget(), RelOptInfo::direct_lateral_relids, RelOptInfo::eclass_indexes, PathTarget::exprs, find_join_rel(), RelOptInfo::has_eclass_joins, has_relevant_eclass_joinclause(), RelOptInfo::indexlist, InvalidOid, IS_OTHER_REL, is_parallel_safe(), PlannerInfo::join_cur_level, JOIN_FULL, JOIN_INNER, RelOptInfo::joininfo, SpecialJoinInfo::jointype, lappend(), RelOptInfo::lateral_referencers, RelOptInfo::lateral_relids, RelOptInfo::lateral_vars, RelOptInfo::live_parts, makeNode, RelOptInfo::max_attr, RelOptInfo::min_attr, min_join_parameterization(), NIL, RelOptInfo::non_unique_for_rels, RelOptInfo::nparts, RelOptInfo::nulling_relids, RelOptInfo::pages, RelOptInfo::partbounds_merged, RelOptInfo::partial_pathlist, RelOptInfo::partition_qual, RelOptInfo::pathlist, QualCost::per_tuple, RelOptInfo::ppilist, RelOptInfo::rel_parallel_workers, RelOptInfo::relid, RelOptInfo::relids, RELOPT_JOINREL, RelOptInfo::reloptkind, RelOptInfo::reltarget, RelOptInfo::rows, RTE_JOIN, RelOptInfo::rtekind, RelOptInfo::serverid, set_foreign_rel_properties(), set_joinrel_size_estimates(), QualCost::startup, RelOptInfo::statlist, RelOptInfo::subplan_params, RelOptInfo::subroot, RelOptInfo::top_parent_relids, PlannerInfo::tuple_fraction, RelOptInfo::tuples, RelOptInfo::unique_for_rels, RelOptInfo::userid, and RelOptInfo::useridiscurrent.

Referenced by make_join_rel().

◆ build_simple_rel()

RelOptInfo* build_simple_rel ( PlannerInfo root,
int  relid,
RelOptInfo parent 
)

Definition at line 191 of file relnode.c.

192 {
193  RelOptInfo *rel;
194  RangeTblEntry *rte;
195 
196  /* Rel should not exist already */
197  Assert(relid > 0 && relid < root->simple_rel_array_size);
198  if (root->simple_rel_array[relid] != NULL)
199  elog(ERROR, "rel %d already exists", relid);
200 
201  /* Fetch RTE for relation */
202  rte = root->simple_rte_array[relid];
203  Assert(rte != NULL);
204 
205  rel = makeNode(RelOptInfo);
207  rel->relids = bms_make_singleton(relid);
208  rel->rows = 0;
209  /* cheap startup cost is interesting iff not all tuples to be retrieved */
210  rel->consider_startup = (root->tuple_fraction > 0);
211  rel->consider_param_startup = false; /* might get changed later */
212  rel->consider_parallel = false; /* might get changed later */
214  rel->pathlist = NIL;
215  rel->ppilist = NIL;
216  rel->partial_pathlist = NIL;
217  rel->cheapest_startup_path = NULL;
218  rel->cheapest_total_path = NULL;
219  rel->cheapest_unique_path = NULL;
221  rel->relid = relid;
222  rel->rtekind = rte->rtekind;
223  /* min_attr, max_attr, attr_needed, attr_widths are set below */
224  rel->lateral_vars = NIL;
225  rel->indexlist = NIL;
226  rel->statlist = NIL;
227  rel->pages = 0;
228  rel->tuples = 0;
229  rel->allvisfrac = 0;
230  rel->eclass_indexes = NULL;
231  rel->subroot = NULL;
232  rel->subplan_params = NIL;
233  rel->rel_parallel_workers = -1; /* set up in get_relation_info */
234  rel->amflags = 0;
235  rel->serverid = InvalidOid;
236  if (rte->rtekind == RTE_RELATION)
237  {
238  Assert(parent == NULL ||
239  parent->rtekind == RTE_RELATION ||
240  parent->rtekind == RTE_SUBQUERY);
241 
242  /*
243  * For any RELATION rte, we need a userid with which to check
244  * permission access. Baserels simply use their own
245  * RTEPermissionInfo's checkAsUser.
246  *
247  * For otherrels normally there's no RTEPermissionInfo, so we use the
248  * parent's, which normally has one. The exceptional case is that the
249  * parent is a subquery, in which case the otherrel will have its own.
250  */
251  if (rel->reloptkind == RELOPT_BASEREL ||
253  parent->rtekind == RTE_SUBQUERY))
254  {
255  RTEPermissionInfo *perminfo;
256 
257  perminfo = getRTEPermissionInfo(root->parse->rteperminfos, rte);
258  rel->userid = perminfo->checkAsUser;
259  }
260  else
261  rel->userid = parent->userid;
262  }
263  else
264  rel->userid = InvalidOid;
265  rel->useridiscurrent = false;
266  rel->fdwroutine = NULL;
267  rel->fdw_private = NULL;
268  rel->unique_for_rels = NIL;
269  rel->non_unique_for_rels = NIL;
270  rel->baserestrictinfo = NIL;
271  rel->baserestrictcost.startup = 0;
272  rel->baserestrictcost.per_tuple = 0;
273  rel->baserestrict_min_security = UINT_MAX;
274  rel->joininfo = NIL;
275  rel->has_eclass_joins = false;
276  rel->consider_partitionwise_join = false; /* might get changed later */
277  rel->part_scheme = NULL;
278  rel->nparts = -1;
279  rel->boundinfo = NULL;
280  rel->partbounds_merged = false;
281  rel->partition_qual = NIL;
282  rel->part_rels = NULL;
283  rel->live_parts = NULL;
284  rel->all_partrels = NULL;
285  rel->partexprs = NULL;
286  rel->nullable_partexprs = NULL;
287 
288  /*
289  * Pass assorted information down the inheritance hierarchy.
290  */
291  if (parent)
292  {
293  /* We keep back-links to immediate parent and topmost parent. */
294  rel->parent = parent;
295  rel->top_parent = parent->top_parent ? parent->top_parent : parent;
296  rel->top_parent_relids = rel->top_parent->relids;
297 
298  /*
299  * A child rel is below the same outer joins as its parent. (We
300  * presume this info was already calculated for the parent.)
301  */
302  rel->nulling_relids = parent->nulling_relids;
303 
304  /*
305  * Also propagate lateral-reference information from appendrel parent
306  * rels to their child rels. We intentionally give each child rel the
307  * same minimum parameterization, even though it's quite possible that
308  * some don't reference all the lateral rels. This is because any
309  * append path for the parent will have to have the same
310  * parameterization for every child anyway, and there's no value in
311  * forcing extra reparameterize_path() calls. Similarly, a lateral
312  * reference to the parent prevents use of otherwise-movable join rels
313  * for each child.
314  *
315  * It's possible for child rels to have their own children, in which
316  * case the topmost parent's lateral info propagates all the way down.
317  */
319  rel->lateral_relids = parent->lateral_relids;
321  }
322  else
323  {
324  rel->parent = NULL;
325  rel->top_parent = NULL;
326  rel->top_parent_relids = NULL;
327  rel->nulling_relids = NULL;
328  rel->direct_lateral_relids = NULL;
329  rel->lateral_relids = NULL;
330  rel->lateral_referencers = NULL;
331  }
332 
333  /* Check type of rtable entry */
334  switch (rte->rtekind)
335  {
336  case RTE_RELATION:
337  /* Table --- retrieve statistics from the system catalogs */
338  get_relation_info(root, rte->relid, rte->inh, rel);
339  break;
340  case RTE_SUBQUERY:
341  case RTE_FUNCTION:
342  case RTE_TABLEFUNC:
343  case RTE_VALUES:
344  case RTE_CTE:
345  case RTE_NAMEDTUPLESTORE:
346 
347  /*
348  * Subquery, function, tablefunc, values list, CTE, or ENR --- set
349  * up attr range and arrays
350  *
351  * Note: 0 is included in range to support whole-row Vars
352  */
353  rel->min_attr = 0;
354  rel->max_attr = list_length(rte->eref->colnames);
355  rel->attr_needed = (Relids *)
356  palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(Relids));
357  rel->attr_widths = (int32 *)
358  palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(int32));
359  break;
360  case RTE_RESULT:
361  /* RTE_RESULT has no columns, nor could it have whole-row Var */
362  rel->min_attr = 0;
363  rel->max_attr = -1;
364  rel->attr_needed = NULL;
365  rel->attr_widths = NULL;
366  break;
367  default:
368  elog(ERROR, "unrecognized RTE kind: %d",
369  (int) rte->rtekind);
370  break;
371  }
372 
373  /*
374  * Copy the parent's quals to the child, with appropriate substitution of
375  * variables. If any constant false or NULL clauses turn up, we can mark
376  * the child as dummy right away. (We must do this immediately so that
377  * pruning works correctly when recursing in expand_partitioned_rtentry.)
378  */
379  if (parent)
380  {
381  AppendRelInfo *appinfo = root->append_rel_array[relid];
382 
383  Assert(appinfo != NULL);
384  if (!apply_child_basequals(root, parent, rel, rte, appinfo))
385  {
386  /*
387  * Some restriction clause reduced to constant FALSE or NULL after
388  * substitution, so this child need not be scanned.
389  */
390  mark_dummy_rel(rel);
391  }
392  }
393 
394  /* Save the finished struct in the query's simple_rel_array */
395  root->simple_rel_array[relid] = rel;
396 
397  return rel;
398 }
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:171
signed int int32
Definition: c.h:483
#define ERROR
Definition: elog.h:39
bool apply_child_basequals(PlannerInfo *root, RelOptInfo *parentrel, RelOptInfo *childrel, RangeTblEntry *childRTE, AppendRelInfo *appinfo)
Definition: inherit.c:832
void mark_dummy_rel(RelOptInfo *rel)
Definition: joinrels.c:1363
void * palloc0(Size size)
Definition: mcxt.c:1257
RTEPermissionInfo * getRTEPermissionInfo(List *rteperminfos, RangeTblEntry *rte)
@ RTE_CTE
Definition: parsenodes.h:1012
@ RTE_NAMEDTUPLESTORE
Definition: parsenodes.h:1013
@ RTE_VALUES
Definition: parsenodes.h:1011
@ RTE_SUBQUERY
Definition: parsenodes.h:1007
@ RTE_RESULT
Definition: parsenodes.h:1014
@ RTE_FUNCTION
Definition: parsenodes.h:1009
@ RTE_TABLEFUNC
Definition: parsenodes.h:1010
@ RTE_RELATION
Definition: parsenodes.h:1006
@ RELOPT_BASEREL
Definition: pathnodes.h:812
@ RELOPT_OTHER_MEMBER_REL
Definition: pathnodes.h:814
static int list_length(const List *l)
Definition: pg_list.h:152
void get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, RelOptInfo *rel)
Definition: plancat.c:117
List * colnames
Definition: primnodes.h:51
Query * parse
Definition: pathnodes.h:199
Alias * eref
Definition: parsenodes.h:1192
RTEKind rtekind
Definition: parsenodes.h:1025

References RelOptInfo::all_partrels, RelOptInfo::allvisfrac, RelOptInfo::amflags, apply_child_basequals(), Assert(), RelOptInfo::baserestrict_min_security, RelOptInfo::baserestrictcost, RelOptInfo::baserestrictinfo, bms_make_singleton(), RelOptInfo::cheapest_parameterized_paths, RelOptInfo::cheapest_startup_path, RelOptInfo::cheapest_total_path, RelOptInfo::cheapest_unique_path, RTEPermissionInfo::checkAsUser, Alias::colnames, RelOptInfo::consider_parallel, RelOptInfo::consider_param_startup, RelOptInfo::consider_partitionwise_join, RelOptInfo::consider_startup, create_empty_pathtarget(), RelOptInfo::direct_lateral_relids, RelOptInfo::eclass_indexes, elog(), RangeTblEntry::eref, ERROR, get_relation_info(), getRTEPermissionInfo(), RelOptInfo::has_eclass_joins, RelOptInfo::indexlist, RangeTblEntry::inh, InvalidOid, RelOptInfo::joininfo, RelOptInfo::lateral_referencers, RelOptInfo::lateral_relids, RelOptInfo::lateral_vars, list_length(), RelOptInfo::live_parts, makeNode, mark_dummy_rel(), RelOptInfo::max_attr, RelOptInfo::min_attr, NIL, RelOptInfo::non_unique_for_rels, RelOptInfo::nparts, RelOptInfo::nulling_relids, RelOptInfo::pages, palloc0(), PlannerInfo::parse, RelOptInfo::partbounds_merged, RelOptInfo::partial_pathlist, RelOptInfo::partition_qual, RelOptInfo::pathlist, QualCost::per_tuple, RelOptInfo::ppilist, RelOptInfo::rel_parallel_workers, RangeTblEntry::relid, RelOptInfo::relid, RelOptInfo::relids, RELOPT_BASEREL, RELOPT_OTHER_MEMBER_REL, RelOptInfo::reloptkind, RelOptInfo::reltarget, RelOptInfo::rows, RTE_CTE, RTE_FUNCTION, RTE_NAMEDTUPLESTORE, RTE_RELATION, RTE_RESULT, RTE_SUBQUERY, RTE_TABLEFUNC, RTE_VALUES, RangeTblEntry::rtekind, RelOptInfo::rtekind, RelOptInfo::serverid, QualCost::startup, RelOptInfo::statlist, RelOptInfo::subplan_params, RelOptInfo::subroot, RelOptInfo::top_parent_relids, PlannerInfo::tuple_fraction, RelOptInfo::tuples, RelOptInfo::unique_for_rels, RelOptInfo::userid, and RelOptInfo::useridiscurrent.

Referenced by add_base_rels_to_query(), expand_appendrel_subquery(), expand_inherited_rtentry(), expand_partitioned_rtentry(), plan_cluster_use_sort(), plan_create_index_workers(), query_planner(), and recurse_set_operations().

◆ calc_nestloop_required_outer()

Relids calc_nestloop_required_outer ( Relids  outerrelids,
Relids  outer_paramrels,
Relids  innerrelids,
Relids  inner_paramrels 
)

Definition at line 2366 of file pathnode.c.

2370 {
2371  Relids required_outer;
2372 
2373  /* inner_path can require rels from outer path, but not vice versa */
2374  Assert(!bms_overlap(outer_paramrels, innerrelids));
2375  /* easy case if inner path is not parameterized */
2376  if (!inner_paramrels)
2377  return bms_copy(outer_paramrels);
2378  /* else, form the union ... */
2379  required_outer = bms_union(outer_paramrels, inner_paramrels);
2380  /* ... and remove any mention of now-satisfied outer rels */
2381  required_outer = bms_del_members(required_outer,
2382  outerrelids);
2383  return required_outer;
2384 }
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:527

References Assert(), bms_copy(), bms_del_members(), bms_overlap(), and bms_union().

Referenced by try_nestloop_path().

◆ calc_non_nestloop_required_outer()

Relids calc_non_nestloop_required_outer ( Path outer_path,
Path inner_path 
)

Definition at line 2393 of file pathnode.c.

2394 {
2395  Relids outer_paramrels = PATH_REQ_OUTER(outer_path);
2396  Relids inner_paramrels = PATH_REQ_OUTER(inner_path);
2397  Relids required_outer;
2398 
2399  /* neither path can require rels from the other */
2400  Assert(!bms_overlap(outer_paramrels, inner_path->parent->relids));
2401  Assert(!bms_overlap(inner_paramrels, outer_path->parent->relids));
2402  /* form the union ... */
2403  required_outer = bms_union(outer_paramrels, inner_paramrels);
2404  /* we do not need an explicit test for empty; bms_union gets it right */
2405  return required_outer;
2406 }

References Assert(), bms_overlap(), bms_union(), and PATH_REQ_OUTER.

Referenced by try_hashjoin_path(), and try_mergejoin_path().

◆ compare_fractional_path_costs()

int compare_fractional_path_costs ( Path path1,
Path path2,
double  fraction 
)

Definition at line 117 of file pathnode.c.

119 {
120  Cost cost1,
121  cost2;
122 
123  if (fraction <= 0.0 || fraction >= 1.0)
124  return compare_path_costs(path1, path2, TOTAL_COST);
125  cost1 = path1->startup_cost +
126  fraction * (path1->total_cost - path1->startup_cost);
127  cost2 = path2->startup_cost +
128  fraction * (path2->total_cost - path2->startup_cost);
129  if (cost1 < cost2)
130  return -1;
131  if (cost1 > cost2)
132  return +1;
133  return 0;
134 }
int compare_path_costs(Path *path1, Path *path2, CostSelector criterion)
Definition: pathnode.c:71
@ TOTAL_COST
Definition: pathnodes.h:38

References compare_path_costs(), Path::startup_cost, TOTAL_COST, and Path::total_cost.

Referenced by choose_hashed_setop(), get_cheapest_fractional_path(), and get_cheapest_fractional_path_for_pathkeys().

◆ compare_path_costs()

int compare_path_costs ( Path path1,
Path path2,
CostSelector  criterion 
)

Definition at line 71 of file pathnode.c.

72 {
73  if (criterion == STARTUP_COST)
74  {
75  if (path1->startup_cost < path2->startup_cost)
76  return -1;
77  if (path1->startup_cost > path2->startup_cost)
78  return +1;
79 
80  /*
81  * If paths have the same startup cost (not at all unlikely), order
82  * them by total cost.
83  */
84  if (path1->total_cost < path2->total_cost)
85  return -1;
86  if (path1->total_cost > path2->total_cost)
87  return +1;
88  }
89  else
90  {
91  if (path1->total_cost < path2->total_cost)
92  return -1;
93  if (path1->total_cost > path2->total_cost)
94  return +1;
95 
96  /*
97  * If paths have the same total cost, order them by startup cost.
98  */
99  if (path1->startup_cost < path2->startup_cost)
100  return -1;
101  if (path1->startup_cost > path2->startup_cost)
102  return +1;
103  }
104  return 0;
105 }
@ STARTUP_COST
Definition: pathnodes.h:38

References STARTUP_COST, Path::startup_cost, and Path::total_cost.

Referenced by append_startup_cost_compare(), append_total_cost_compare(), compare_fractional_path_costs(), generate_mergejoin_paths(), get_cheapest_parameterized_child_path(), get_cheapest_path_for_pathkeys(), and set_cheapest().

◆ create_agg_path()

AggPath* create_agg_path ( PlannerInfo root,
RelOptInfo rel,
Path subpath,
PathTarget target,
AggStrategy  aggstrategy,
AggSplit  aggsplit,
List groupClause,
List qual,
const AggClauseCosts aggcosts,
double  numGroups 
)

Definition at line 3114 of file pathnode.c.

3124 {
3125  AggPath *pathnode = makeNode(AggPath);
3126 
3127  pathnode->path.pathtype = T_Agg;
3128  pathnode->path.parent = rel;
3129  pathnode->path.pathtarget = target;
3130  /* For now, assume we are above any joins, so no parameterization */
3131  pathnode->path.param_info = NULL;
3132  pathnode->path.parallel_aware = false;
3133  pathnode->path.parallel_safe = rel->consider_parallel &&
3134  subpath->parallel_safe;
3135  pathnode->path.parallel_workers = subpath->parallel_workers;
3136 
3137  if (aggstrategy == AGG_SORTED)
3138  {
3139  /*
3140  * Attempt to preserve the order of the subpath. Additional pathkeys
3141  * may have been added in adjust_group_pathkeys_for_groupagg() to
3142  * support ORDER BY / DISTINCT aggregates. Pathkeys added there
3143  * belong to columns within the aggregate function, so we must strip
3144  * these additional pathkeys off as those columns are unavailable
3145  * above the aggregate node.
3146  */
3147  if (list_length(subpath->pathkeys) > root->num_groupby_pathkeys)
3148  pathnode->path.pathkeys = list_copy_head(subpath->pathkeys,
3149  root->num_groupby_pathkeys);
3150  else
3151  pathnode->path.pathkeys = subpath->pathkeys; /* preserves order */
3152  }
3153  else
3154  pathnode->path.pathkeys = NIL; /* output is unordered */
3155 
3156  pathnode->subpath = subpath;
3157 
3158  pathnode->aggstrategy = aggstrategy;
3159  pathnode->aggsplit = aggsplit;
3160  pathnode->numGroups = numGroups;
3161  pathnode->transitionSpace = aggcosts ? aggcosts->transitionSpace : 0;
3162  pathnode->groupClause = groupClause;
3163  pathnode->qual = qual;
3164 
3165  cost_agg(&pathnode->path, root,
3166  aggstrategy, aggcosts,
3167  list_length(groupClause), numGroups,
3168  qual,
3169  subpath->startup_cost, subpath->total_cost,
3170  subpath->rows, subpath->pathtarget->width);
3171 
3172  /* add tlist eval cost for each output row */
3173  pathnode->path.startup_cost += target->cost.startup;
3174  pathnode->path.total_cost += target->cost.startup +
3175  target->cost.per_tuple * pathnode->path.rows;
3176 
3177  return pathnode;
3178 }
void cost_agg(Path *path, PlannerInfo *root, AggStrategy aggstrategy, const AggClauseCosts *aggcosts, int numGroupCols, double numGroups, List *quals, Cost input_startup_cost, Cost input_total_cost, double input_tuples, double input_width)
Definition: costsize.c:2622
List * list_copy_head(const List *oldlist, int len)
Definition: list.c:1592
Datum subpath(PG_FUNCTION_ARGS)
Definition: ltree_op.c:241
@ AGG_SORTED
Definition: nodes.h:365
Size transitionSpace
Definition: pathnodes.h:62
Path * subpath
Definition: pathnodes.h:2222
Cardinality numGroups
Definition: pathnodes.h:2225
AggSplit aggsplit
Definition: pathnodes.h:2224
List * groupClause
Definition: pathnodes.h:2227
uint64 transitionSpace
Definition: pathnodes.h:2226
AggStrategy aggstrategy
Definition: pathnodes.h:2223
Path path
Definition: pathnodes.h:2221
List * qual
Definition: pathnodes.h:2228
NodeTag pathtype
Definition: pathnodes.h:1594
int parallel_workers
Definition: pathnodes.h:1625
bool parallel_aware
Definition: pathnodes.h:1621
int num_groupby_pathkeys
Definition: pathnodes.h:392

References AGG_SORTED, AggPath::aggsplit, AggPath::aggstrategy, RelOptInfo::consider_parallel, PathTarget::cost, cost_agg(), AggPath::groupClause, list_copy_head(), list_length(), makeNode, NIL, PlannerInfo::num_groupby_pathkeys, AggPath::numGroups, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, AggPath::path, Path::pathkeys, Path::pathtype, QualCost::per_tuple, AggPath::qual, Path::rows, QualCost::startup, Path::startup_cost, subpath(), AggPath::subpath, Path::total_cost, AggClauseCosts::transitionSpace, and AggPath::transitionSpace.

Referenced by add_paths_to_grouping_rel(), create_final_distinct_paths(), create_partial_distinct_paths(), create_partial_grouping_paths(), and make_union_unique().

◆ create_append_path()

AppendPath* create_append_path ( PlannerInfo root,
RelOptInfo rel,
List subpaths,
List partial_subpaths,
List pathkeys,
Relids  required_outer,
int  parallel_workers,
bool  parallel_aware,
double  rows 
)

Definition at line 1242 of file pathnode.c.

1248 {
1249  AppendPath *pathnode = makeNode(AppendPath);
1250  ListCell *l;
1251 
1252  Assert(!parallel_aware || parallel_workers > 0);
1253 
1254  pathnode->path.pathtype = T_Append;
1255  pathnode->path.parent = rel;
1256  pathnode->path.pathtarget = rel->reltarget;
1257 
1258  /*
1259  * If this is for a baserel (not a join or non-leaf partition), we prefer
1260  * to apply get_baserel_parampathinfo to construct a full ParamPathInfo
1261  * for the path. This supports building a Memoize path atop this path,
1262  * and if this is a partitioned table the info may be useful for run-time
1263  * pruning (cf make_partition_pruneinfo()).
1264  *
1265  * However, if we don't have "root" then that won't work and we fall back
1266  * on the simpler get_appendrel_parampathinfo. There's no point in doing
1267  * the more expensive thing for a dummy path, either.
1268  */
1269  if (rel->reloptkind == RELOPT_BASEREL && root && subpaths != NIL)
1270  pathnode->path.param_info = get_baserel_parampathinfo(root,
1271  rel,
1272  required_outer);
1273  else
1274  pathnode->path.param_info = get_appendrel_parampathinfo(rel,
1275  required_outer);
1276 
1277  pathnode->path.parallel_aware = parallel_aware;
1278  pathnode->path.parallel_safe = rel->consider_parallel;
1279  pathnode->path.parallel_workers = parallel_workers;
1280  pathnode->path.pathkeys = pathkeys;
1281 
1282  /*
1283  * For parallel append, non-partial paths are sorted by descending total
1284  * costs. That way, the total time to finish all non-partial paths is
1285  * minimized. Also, the partial paths are sorted by descending startup
1286  * costs. There may be some paths that require to do startup work by a
1287  * single worker. In such case, it's better for workers to choose the
1288  * expensive ones first, whereas the leader should choose the cheapest
1289  * startup plan.
1290  */
1291  if (pathnode->path.parallel_aware)
1292  {
1293  /*
1294  * We mustn't fiddle with the order of subpaths when the Append has
1295  * pathkeys. The order they're listed in is critical to keeping the
1296  * pathkeys valid.
1297  */
1298  Assert(pathkeys == NIL);
1299 
1301  list_sort(partial_subpaths, append_startup_cost_compare);
1302  }
1303  pathnode->first_partial_path = list_length(subpaths);
1304  pathnode->subpaths = list_concat(subpaths, partial_subpaths);
1305 
1306  /*
1307  * Apply query-wide LIMIT if known and path is for sole base relation.
1308  * (Handling this at this low level is a bit klugy.)
1309  */
1310  if (root != NULL && bms_equal(rel->relids, root->all_query_rels))
1311  pathnode->limit_tuples = root->limit_tuples;
1312  else
1313  pathnode->limit_tuples = -1.0;
1314 
1315  foreach(l, pathnode->subpaths)
1316  {
1317  Path *subpath = (Path *) lfirst(l);
1318 
1319  pathnode->path.parallel_safe = pathnode->path.parallel_safe &&
1320  subpath->parallel_safe;
1321 
1322  /* All child paths must have same parameterization */
1323  Assert(bms_equal(PATH_REQ_OUTER(subpath), required_outer));
1324  }
1325 
1326  Assert(!parallel_aware || pathnode->path.parallel_safe);
1327 
1328  /*
1329  * If there's exactly one child path then the output of the Append is
1330  * necessarily ordered the same as the child's, so we can inherit the
1331  * child's pathkeys if any, overriding whatever the caller might've said.
1332  * Furthermore, if the child's parallel awareness matches the Append's,
1333  * then the Append is a no-op and will be discarded later (in setrefs.c).
1334  * Then we can inherit the child's size and cost too, effectively charging
1335  * zero for the Append. Otherwise, we must do the normal costsize
1336  * calculation.
1337  */
1338  if (list_length(pathnode->subpaths) == 1)
1339  {
1340  Path *child = (Path *) linitial(pathnode->subpaths);
1341 
1342  if (child->parallel_aware == parallel_aware)
1343  {
1344  pathnode->path.rows = child->rows;
1345  pathnode->path.startup_cost = child->startup_cost;
1346  pathnode->path.total_cost = child->total_cost;
1347  }
1348  else
1349  cost_append(pathnode);
1350  /* Must do this last, else cost_append complains */
1351  pathnode->path.pathkeys = child->pathkeys;
1352  }
1353  else
1354  cost_append(pathnode);
1355 
1356  /* If the caller provided a row estimate, override the computed value. */
1357  if (rows >= 0)
1358  pathnode->path.rows = rows;
1359 
1360  return pathnode;
1361 }
void cost_append(AppendPath *apath)
Definition: costsize.c:2203
void list_sort(List *list, list_sort_comparator cmp)
Definition: list.c:1673
List * list_concat(List *list1, const List *list2)
Definition: list.c:560
static int append_startup_cost_compare(const ListCell *a, const ListCell *b)
Definition: pathnode.c:1395
static int append_total_cost_compare(const ListCell *a, const ListCell *b)
Definition: pathnode.c:1373
#define linitial(l)
Definition: pg_list.h:178
ParamPathInfo * get_baserel_parampathinfo(PlannerInfo *root, RelOptInfo *baserel, Relids required_outer)
Definition: relnode.c:1530
ParamPathInfo * get_appendrel_parampathinfo(RelOptInfo *appendrel, Relids required_outer)
Definition: relnode.c:1829
int first_partial_path
Definition: pathnodes.h:1902
Cardinality limit_tuples
Definition: pathnodes.h:1903
List * subpaths
Definition: pathnodes.h:1900
Relids all_query_rels
Definition: pathnodes.h:266
Cardinality limit_tuples
Definition: pathnodes.h:480

References PlannerInfo::all_query_rels, append_startup_cost_compare(), append_total_cost_compare(), Assert(), bms_equal(), RelOptInfo::consider_parallel, cost_append(), AppendPath::first_partial_path, get_appendrel_parampathinfo(), get_baserel_parampathinfo(), lfirst, PlannerInfo::limit_tuples, AppendPath::limit_tuples, linitial, list_concat(), list_length(), list_sort(), makeNode, NIL, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, AppendPath::path, PATH_REQ_OUTER, Path::pathkeys, Path::pathtype, RelOptInfo::relids, RELOPT_BASEREL, RelOptInfo::reloptkind, RelOptInfo::reltarget, Path::rows, Path::startup_cost, subpath(), AppendPath::subpaths, and Path::total_cost.

Referenced by add_paths_to_append_rel(), create_degenerate_grouping_paths(), generate_nonunion_paths(), generate_orderedappend_paths(), generate_union_paths(), mark_dummy_rel(), reparameterize_path(), and set_dummy_rel_pathlist().

◆ create_bitmap_and_path()

BitmapAndPath* create_bitmap_and_path ( PlannerInfo root,
RelOptInfo rel,
List bitmapquals 
)

Definition at line 1077 of file pathnode.c.

1080 {
1081  BitmapAndPath *pathnode = makeNode(BitmapAndPath);
1082  Relids required_outer = NULL;
1083  ListCell *lc;
1084 
1085  pathnode->path.pathtype = T_BitmapAnd;
1086  pathnode->path.parent = rel;
1087  pathnode->path.pathtarget = rel->reltarget;
1088 
1089  /*
1090  * Identify the required outer rels as the union of what the child paths
1091  * depend on. (Alternatively, we could insist that the caller pass this
1092  * in, but it's more convenient and reliable to compute it here.)
1093  */
1094  foreach(lc, bitmapquals)
1095  {
1096  Path *bitmapqual = (Path *) lfirst(lc);
1097 
1098  required_outer = bms_add_members(required_outer,
1099  PATH_REQ_OUTER(bitmapqual));
1100  }
1101  pathnode->path.param_info = get_baserel_parampathinfo(root, rel,
1102  required_outer);
1103 
1104  /*
1105  * Currently, a BitmapHeapPath, BitmapAndPath, or BitmapOrPath will be
1106  * parallel-safe if and only if rel->consider_parallel is set. So, we can
1107  * set the flag for this path based only on the relation-level flag,
1108  * without actually iterating over the list of children.
1109  */
1110  pathnode->path.parallel_aware = false;
1111  pathnode->path.parallel_safe = rel->consider_parallel;
1112  pathnode->path.parallel_workers = 0;
1113 
1114  pathnode->path.pathkeys = NIL; /* always unordered */
1115 
1116  pathnode->bitmapquals = bitmapquals;
1117 
1118  /* this sets bitmapselectivity as well as the regular cost fields: */
1119  cost_bitmap_and_node(pathnode, root);
1120 
1121  return pathnode;
1122 }
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:835
void cost_bitmap_and_node(BitmapAndPath *path, PlannerInfo *root)
Definition: costsize.c:1129
List * bitmapquals
Definition: pathnodes.h:1765

References BitmapAndPath::bitmapquals, bms_add_members(), RelOptInfo::consider_parallel, cost_bitmap_and_node(), get_baserel_parampathinfo(), lfirst, makeNode, NIL, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, BitmapAndPath::path, PATH_REQ_OUTER, Path::pathkeys, Path::pathtype, and RelOptInfo::reltarget.

Referenced by bitmap_and_cost_est(), and choose_bitmap_and().

◆ create_bitmap_heap_path()

BitmapHeapPath* create_bitmap_heap_path ( PlannerInfo root,
RelOptInfo rel,
Path bitmapqual,
Relids  required_outer,
double  loop_count,
int  parallel_degree 
)

Definition at line 1044 of file pathnode.c.

1050 {
1051  BitmapHeapPath *pathnode = makeNode(BitmapHeapPath);
1052 
1053  pathnode->path.pathtype = T_BitmapHeapScan;
1054  pathnode->path.parent = rel;
1055  pathnode->path.pathtarget = rel->reltarget;
1056  pathnode->path.param_info = get_baserel_parampathinfo(root, rel,
1057  required_outer);
1058  pathnode->path.parallel_aware = (parallel_degree > 0);
1059  pathnode->path.parallel_safe = rel->consider_parallel;
1060  pathnode->path.parallel_workers = parallel_degree;
1061  pathnode->path.pathkeys = NIL; /* always unordered */
1062 
1063  pathnode->bitmapqual = bitmapqual;
1064 
1065  cost_bitmap_heap_scan(&pathnode->path, root, rel,
1066  pathnode->path.param_info,
1067  bitmapqual, loop_count);
1068 
1069  return pathnode;
1070 }
void cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel, ParamPathInfo *param_info, Path *bitmapqual, double loop_count)
Definition: costsize.c:985
Path * bitmapqual
Definition: pathnodes.h:1753

References BitmapHeapPath::bitmapqual, RelOptInfo::consider_parallel, cost_bitmap_heap_scan(), get_baserel_parampathinfo(), makeNode, NIL, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, BitmapHeapPath::path, Path::pathkeys, Path::pathtype, and RelOptInfo::reltarget.

Referenced by create_index_paths(), create_partial_bitmap_paths(), and reparameterize_path().

◆ create_bitmap_or_path()

BitmapOrPath* create_bitmap_or_path ( PlannerInfo root,
RelOptInfo rel,
List bitmapquals 
)

Definition at line 1129 of file pathnode.c.

1132 {
1133  BitmapOrPath *pathnode = makeNode(BitmapOrPath);
1134  Relids required_outer = NULL;
1135  ListCell *lc;
1136 
1137  pathnode->path.pathtype = T_BitmapOr;
1138  pathnode->path.parent = rel;
1139  pathnode->path.pathtarget = rel->reltarget;
1140 
1141  /*
1142  * Identify the required outer rels as the union of what the child paths
1143  * depend on. (Alternatively, we could insist that the caller pass this
1144  * in, but it's more convenient and reliable to compute it here.)
1145  */
1146  foreach(lc, bitmapquals)
1147  {
1148  Path *bitmapqual = (Path *) lfirst(lc);
1149 
1150  required_outer = bms_add_members(required_outer,
1151  PATH_REQ_OUTER(bitmapqual));
1152  }
1153  pathnode->path.param_info = get_baserel_parampathinfo(root, rel,
1154  required_outer);
1155 
1156  /*
1157  * Currently, a BitmapHeapPath, BitmapAndPath, or BitmapOrPath will be
1158  * parallel-safe if and only if rel->consider_parallel is set. So, we can
1159  * set the flag for this path based only on the relation-level flag,
1160  * without actually iterating over the list of children.
1161  */
1162  pathnode->path.parallel_aware = false;
1163  pathnode->path.parallel_safe = rel->consider_parallel;
1164  pathnode->path.parallel_workers = 0;
1165 
1166  pathnode->path.pathkeys = NIL; /* always unordered */
1167 
1168  pathnode->bitmapquals = bitmapquals;
1169 
1170  /* this sets bitmapselectivity as well as the regular cost fields: */
1171  cost_bitmap_or_node(pathnode, root);
1172 
1173  return pathnode;
1174 }
void cost_bitmap_or_node(BitmapOrPath *path, PlannerInfo *root)
Definition: costsize.c:1173
List * bitmapquals
Definition: pathnodes.h:1778

References BitmapOrPath::bitmapquals, bms_add_members(), RelOptInfo::consider_parallel, cost_bitmap_or_node(), get_baserel_parampathinfo(), lfirst, makeNode, NIL, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, BitmapOrPath::path, PATH_REQ_OUTER, Path::pathkeys, Path::pathtype, and RelOptInfo::reltarget.

Referenced by generate_bitmap_or_paths().

◆ create_ctescan_path()

Path* create_ctescan_path ( PlannerInfo root,
RelOptInfo rel,
Relids  required_outer 
)

Definition at line 2116 of file pathnode.c.

2117 {
2118  Path *pathnode = makeNode(Path);
2119 
2120  pathnode->pathtype = T_CteScan;
2121  pathnode->parent = rel;
2122  pathnode->pathtarget = rel->reltarget;
2123  pathnode->param_info = get_baserel_parampathinfo(root, rel,
2124  required_outer);
2125  pathnode->parallel_aware = false;
2126  pathnode->parallel_safe = rel->consider_parallel;
2127  pathnode->parallel_workers = 0;
2128  pathnode->pathkeys = NIL; /* XXX for now, result is always unordered */
2129 
2130  cost_ctescan(pathnode, root, rel, pathnode->param_info);
2131 
2132  return pathnode;
2133 }
void cost_ctescan(Path *path, PlannerInfo *root, RelOptInfo *baserel, ParamPathInfo *param_info)
Definition: costsize.c:1670

References RelOptInfo::consider_parallel, cost_ctescan(), get_baserel_parampathinfo(), makeNode, NIL, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, Path::pathkeys, Path::pathtype, and RelOptInfo::reltarget.

Referenced by set_cte_pathlist().

◆ create_foreign_join_path()

ForeignPath* create_foreign_join_path ( PlannerInfo root,
RelOptInfo rel,
PathTarget target,
double  rows,
Cost  startup_cost,
Cost  total_cost,
List pathkeys,
Relids  required_outer,
Path fdw_outerpath,
List fdw_restrictinfo,
List fdw_private 
)

Definition at line 2272 of file pathnode.c.

2280 {
2281  ForeignPath *pathnode = makeNode(ForeignPath);
2282 
2283  /*
2284  * We should use get_joinrel_parampathinfo to handle parameterized paths,
2285  * but the API of this function doesn't support it, and existing
2286  * extensions aren't yet trying to build such paths anyway. For the
2287  * moment just throw an error if someone tries it; eventually we should
2288  * revisit this.
2289  */
2290  if (!bms_is_empty(required_outer) || !bms_is_empty(rel->lateral_relids))
2291  elog(ERROR, "parameterized foreign joins are not supported yet");
2292 
2293  pathnode->path.pathtype = T_ForeignScan;
2294  pathnode->path.parent = rel;
2295  pathnode->path.pathtarget = target ? target : rel->reltarget;
2296  pathnode->path.param_info = NULL; /* XXX see above */
2297  pathnode->path.parallel_aware = false;
2298  pathnode->path.parallel_safe = rel->consider_parallel;
2299  pathnode->path.parallel_workers = 0;
2300  pathnode->path.rows = rows;
2301  pathnode->path.startup_cost = startup_cost;
2302  pathnode->path.total_cost = total_cost;
2303  pathnode->path.pathkeys = pathkeys;
2304 
2305  pathnode->fdw_outerpath = fdw_outerpath;
2306  pathnode->fdw_restrictinfo = fdw_restrictinfo;
2307  pathnode->fdw_private = fdw_private;
2308 
2309  return pathnode;
2310 }
#define bms_is_empty(a)
Definition: bitmapset.h:105
Path * fdw_outerpath
Definition: pathnodes.h:1838
List * fdw_restrictinfo
Definition: pathnodes.h:1839
List * fdw_private
Definition: pathnodes.h:1840

References bms_is_empty, RelOptInfo::consider_parallel, elog(), ERROR, ForeignPath::fdw_outerpath, ForeignPath::fdw_private, ForeignPath::fdw_restrictinfo, RelOptInfo::lateral_relids, makeNode, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, ForeignPath::path, Path::pathkeys, Path::pathtype, RelOptInfo::reltarget, Path::rows, Path::startup_cost, and Path::total_cost.

Referenced by add_paths_with_pathkeys_for_rel(), and postgresGetForeignJoinPaths().

◆ create_foreign_upper_path()

ForeignPath* create_foreign_upper_path ( PlannerInfo root,
RelOptInfo rel,
PathTarget target,
double  rows,
Cost  startup_cost,
Cost  total_cost,
List pathkeys,
Path fdw_outerpath,
List fdw_restrictinfo,
List fdw_private 
)

Definition at line 2324 of file pathnode.c.

2331 {
2332  ForeignPath *pathnode = makeNode(ForeignPath);
2333 
2334  /*
2335  * Upper relations should never have any lateral references, since joining
2336  * is complete.
2337  */
2339 
2340  pathnode->path.pathtype = T_ForeignScan;
2341  pathnode->path.parent = rel;
2342  pathnode->path.pathtarget = target ? target : rel->reltarget;
2343  pathnode->path.param_info = NULL;
2344  pathnode->path.parallel_aware = false;
2345  pathnode->path.parallel_safe = rel->consider_parallel;
2346  pathnode->path.parallel_workers = 0;
2347  pathnode->path.rows = rows;
2348  pathnode->path.startup_cost = startup_cost;
2349  pathnode->path.total_cost = total_cost;
2350  pathnode->path.pathkeys = pathkeys;
2351 
2352  pathnode->fdw_outerpath = fdw_outerpath;
2353  pathnode->fdw_restrictinfo = fdw_restrictinfo;
2354  pathnode->fdw_private = fdw_private;
2355 
2356  return pathnode;
2357 }

References Assert(), bms_is_empty, RelOptInfo::consider_parallel, ForeignPath::fdw_outerpath, ForeignPath::fdw_private, ForeignPath::fdw_restrictinfo, RelOptInfo::lateral_relids, makeNode, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, ForeignPath::path, Path::pathkeys, Path::pathtype, RelOptInfo::reltarget, Path::rows, Path::startup_cost, and Path::total_cost.

Referenced by add_foreign_final_paths(), add_foreign_grouping_paths(), and add_foreign_ordered_paths().

◆ create_foreignscan_path()

ForeignPath* create_foreignscan_path ( PlannerInfo root,
RelOptInfo rel,
PathTarget target,
double  rows,
Cost  startup_cost,
Cost  total_cost,
List pathkeys,
Relids  required_outer,
Path fdw_outerpath,
List fdw_restrictinfo,
List fdw_private 
)

Definition at line 2226 of file pathnode.c.

2234 {
2235  ForeignPath *pathnode = makeNode(ForeignPath);
2236 
2237  /* Historically some FDWs were confused about when to use this */
2238  Assert(IS_SIMPLE_REL(rel));
2239 
2240  pathnode->path.pathtype = T_ForeignScan;
2241  pathnode->path.parent = rel;
2242  pathnode->path.pathtarget = target ? target : rel->reltarget;
2243  pathnode->path.param_info = get_baserel_parampathinfo(root, rel,
2244  required_outer);
2245  pathnode->path.parallel_aware = false;
2246  pathnode->path.parallel_safe = rel->consider_parallel;
2247  pathnode->path.parallel_workers = 0;
2248  pathnode->path.rows = rows;
2249  pathnode->path.startup_cost = startup_cost;
2250  pathnode->path.total_cost = total_cost;
2251  pathnode->path.pathkeys = pathkeys;
2252 
2253  pathnode->fdw_outerpath = fdw_outerpath;
2254  pathnode->fdw_restrictinfo = fdw_restrictinfo;
2255  pathnode->fdw_private = fdw_private;
2256 
2257  return pathnode;
2258 }
#define IS_SIMPLE_REL(rel)
Definition: pathnodes.h:824

References Assert(), RelOptInfo::consider_parallel, ForeignPath::fdw_outerpath, ForeignPath::fdw_private, ForeignPath::fdw_restrictinfo, get_baserel_parampathinfo(), IS_SIMPLE_REL, makeNode, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, ForeignPath::path, Path::pathkeys, Path::pathtype, RelOptInfo::reltarget, Path::rows, Path::startup_cost, and Path::total_cost.

Referenced by add_paths_with_pathkeys_for_rel(), fileGetForeignPaths(), and postgresGetForeignPaths().

◆ create_functionscan_path()

Path* create_functionscan_path ( PlannerInfo root,
RelOptInfo rel,
List pathkeys,
Relids  required_outer 
)

Definition at line 2038 of file pathnode.c.

2040 {
2041  Path *pathnode = makeNode(Path);
2042 
2043  pathnode->pathtype = T_FunctionScan;
2044  pathnode->parent = rel;
2045  pathnode->pathtarget = rel->reltarget;
2046  pathnode->param_info = get_baserel_parampathinfo(root, rel,
2047  required_outer);
2048  pathnode->parallel_aware = false;
2049  pathnode->parallel_safe = rel->consider_parallel;
2050  pathnode->parallel_workers = 0;
2051  pathnode->pathkeys = pathkeys;
2052 
2053  cost_functionscan(pathnode, root, rel, pathnode->param_info);
2054 
2055  return pathnode;
2056 }
void cost_functionscan(Path *path, PlannerInfo *root, RelOptInfo *baserel, ParamPathInfo *param_info)
Definition: costsize.c:1503

References RelOptInfo::consider_parallel, cost_functionscan(), get_baserel_parampathinfo(), makeNode, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, Path::pathkeys, Path::pathtype, and RelOptInfo::reltarget.

Referenced by set_function_pathlist().

◆ create_gather_merge_path()

GatherMergePath* create_gather_merge_path ( PlannerInfo root,
RelOptInfo rel,
Path subpath,
PathTarget target,
List pathkeys,
Relids  required_outer,
double *  rows 
)

Definition at line 1873 of file pathnode.c.

1876 {
1878  Cost input_startup_cost = 0;
1879  Cost input_total_cost = 0;
1880 
1881  Assert(subpath->parallel_safe);
1882  Assert(pathkeys);
1883 
1884  pathnode->path.pathtype = T_GatherMerge;
1885  pathnode->path.parent = rel;
1886  pathnode->path.param_info = get_baserel_parampathinfo(root, rel,
1887  required_outer);
1888  pathnode->path.parallel_aware = false;
1889 
1890  pathnode->subpath = subpath;
1891  pathnode->num_workers = subpath->parallel_workers;
1892  pathnode->path.pathkeys = pathkeys;
1893  pathnode->path.pathtarget = target ? target : rel->reltarget;
1894  pathnode->path.rows += subpath->rows;
1895 
1896  if (pathkeys_contained_in(pathkeys, subpath->pathkeys))
1897  {
1898  /* Subpath is adequately ordered, we won't need to sort it */
1899  input_startup_cost += subpath->startup_cost;
1900  input_total_cost += subpath->total_cost;
1901  }
1902  else
1903  {
1904  /* We'll need to insert a Sort node, so include cost for that */
1905  Path sort_path; /* dummy for result of cost_sort */
1906 
1907  cost_sort(&sort_path,
1908  root,
1909  pathkeys,
1910  subpath->total_cost,
1911  subpath->rows,
1912  subpath->pathtarget->width,
1913  0.0,
1914  work_mem,
1915  -1);
1916  input_startup_cost += sort_path.startup_cost;
1917  input_total_cost += sort_path.total_cost;
1918  }
1919 
1920  cost_gather_merge(pathnode, root, rel, pathnode->path.param_info,
1921  input_startup_cost, input_total_cost, rows);
1922 
1923  return pathnode;
1924 }
void cost_gather_merge(GatherMergePath *path, PlannerInfo *root, RelOptInfo *rel, ParamPathInfo *param_info, Cost input_startup_cost, Cost input_total_cost, double *rows)
Definition: costsize.c:446
void cost_sort(Path *path, PlannerInfo *root, List *pathkeys, Cost input_cost, double tuples, int width, Cost comparison_cost, int sort_mem, double limit_tuples)
Definition: costsize.c:2096
int work_mem
Definition: globals.c:127
bool pathkeys_contained_in(List *keys1, List *keys2)
Definition: pathkeys.c:340

References Assert(), cost_gather_merge(), cost_sort(), get_baserel_parampathinfo(), makeNode, GatherMergePath::num_workers, Path::parallel_aware, GatherMergePath::path, Path::pathkeys, pathkeys_contained_in(), Path::pathtype, RelOptInfo::reltarget, Path::rows, Path::startup_cost, subpath(), GatherMergePath::subpath, Path::total_cost, and work_mem.

Referenced by create_ordered_paths(), gather_grouping_paths(), generate_gather_paths(), and generate_useful_gather_paths().

◆ create_gather_path()

GatherPath* create_gather_path ( PlannerInfo root,
RelOptInfo rel,
Path subpath,
PathTarget target,
Relids  required_outer,
double *  rows 
)

Definition at line 1964 of file pathnode.c.

1966 {
1967  GatherPath *pathnode = makeNode(GatherPath);
1968 
1969  Assert(subpath->parallel_safe);
1970 
1971  pathnode->path.pathtype = T_Gather;
1972  pathnode->path.parent = rel;
1973  pathnode->path.pathtarget = target;
1974  pathnode->path.param_info = get_baserel_parampathinfo(root, rel,
1975  required_outer);
1976  pathnode->path.parallel_aware = false;
1977  pathnode->path.parallel_safe = false;
1978  pathnode->path.parallel_workers = 0;
1979  pathnode->path.pathkeys = NIL; /* Gather has unordered result */
1980 
1981  pathnode->subpath = subpath;
1982  pathnode->num_workers = subpath->parallel_workers;
1983  pathnode->single_copy = false;
1984 
1985  if (pathnode->num_workers == 0)
1986  {
1987  pathnode->path.pathkeys = subpath->pathkeys;
1988  pathnode->num_workers = 1;
1989  pathnode->single_copy = true;
1990  }
1991 
1992  cost_gather(pathnode, root, rel, pathnode->path.param_info, rows);
1993 
1994  return pathnode;
1995 }
void cost_gather(GatherPath *path, PlannerInfo *root, RelOptInfo *rel, ParamPathInfo *param_info, double *rows)
Definition: costsize.c:408
bool single_copy
Definition: pathnodes.h:2011
int num_workers
Definition: pathnodes.h:2012

References Assert(), cost_gather(), get_baserel_parampathinfo(), makeNode, NIL, GatherPath::num_workers, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, GatherPath::path, Path::pathkeys, Path::pathtype, GatherPath::single_copy, subpath(), and GatherPath::subpath.

Referenced by generate_gather_paths(), and generate_union_paths().

◆ create_group_path()

GroupPath* create_group_path ( PlannerInfo root,
RelOptInfo rel,
Path subpath,
List groupClause,
List qual,
double  numGroups 
)

Definition at line 3003 of file pathnode.c.

3009 {
3010  GroupPath *pathnode = makeNode(GroupPath);
3011  PathTarget *target = rel->reltarget;
3012 
3013  pathnode->path.pathtype = T_Group;
3014  pathnode->path.parent = rel;
3015  pathnode->path.pathtarget = target;
3016  /* For now, assume we are above any joins, so no parameterization */
3017  pathnode->path.param_info = NULL;
3018  pathnode->path.parallel_aware = false;
3019  pathnode->path.parallel_safe = rel->consider_parallel &&
3020  subpath->parallel_safe;
3021  pathnode->path.parallel_workers = subpath->parallel_workers;
3022  /* Group doesn't change sort ordering */
3023  pathnode->path.pathkeys = subpath->pathkeys;
3024 
3025  pathnode->subpath = subpath;
3026 
3027  pathnode->groupClause = groupClause;
3028  pathnode->qual = qual;
3029 
3030  cost_group(&pathnode->path, root,
3031  list_length(groupClause),
3032  numGroups,
3033  qual,
3034  subpath->startup_cost, subpath->total_cost,
3035  subpath->rows);
3036 
3037  /* add tlist eval cost for each output row */
3038  pathnode->path.startup_cost += target->cost.startup;
3039  pathnode->path.total_cost += target->cost.startup +
3040  target->cost.per_tuple * pathnode->path.rows;
3041 
3042  return pathnode;
3043 }
void cost_group(Path *path, PlannerInfo *root, int numGroupCols, double numGroups, List *quals, Cost input_startup_cost, Cost input_total_cost, double input_tuples)
Definition: costsize.c:3135
List * qual
Definition: pathnodes.h:2196
List * groupClause
Definition: pathnodes.h:2195
Path * subpath
Definition: pathnodes.h:2194
Path path
Definition: pathnodes.h:2193

References RelOptInfo::consider_parallel, PathTarget::cost, cost_group(), GroupPath::groupClause, list_length(), makeNode, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, GroupPath::path, Path::pathkeys, Path::pathtype, QualCost::per_tuple, GroupPath::qual, RelOptInfo::reltarget, Path::rows, QualCost::startup, Path::startup_cost, subpath(), GroupPath::subpath, and Path::total_cost.

Referenced by add_paths_to_grouping_rel(), and create_partial_grouping_paths().

◆ create_group_result_path()

GroupResultPath* create_group_result_path ( PlannerInfo root,
RelOptInfo rel,
PathTarget target,
List havingqual 
)

Definition at line 1516 of file pathnode.c.

1518 {
1520 
1521  pathnode->path.pathtype = T_Result;
1522  pathnode->path.parent = rel;
1523  pathnode->path.pathtarget = target;
1524  pathnode->path.param_info = NULL; /* there are no other rels... */
1525  pathnode->path.parallel_aware = false;
1526  pathnode->path.parallel_safe = rel->consider_parallel;
1527  pathnode->path.parallel_workers = 0;
1528  pathnode->path.pathkeys = NIL;
1529  pathnode->quals = havingqual;
1530 
1531  /*
1532  * We can't quite use cost_resultscan() because the quals we want to
1533  * account for are not baserestrict quals of the rel. Might as well just
1534  * hack it here.
1535  */
1536  pathnode->path.rows = 1;
1537  pathnode->path.startup_cost = target->cost.startup;
1538  pathnode->path.total_cost = target->cost.startup +
1539  cpu_tuple_cost + target->cost.per_tuple;
1540 
1541  /*
1542  * Add cost of qual, if any --- but we ignore its selectivity, since our
1543  * rowcount estimate should be 1 no matter what the qual is.
1544  */
1545  if (havingqual)
1546  {
1547  QualCost qual_cost;
1548 
1549  cost_qual_eval(&qual_cost, havingqual, root);
1550  /* havingqual is evaluated once at startup */
1551  pathnode->path.startup_cost += qual_cost.startup + qual_cost.per_tuple;
1552  pathnode->path.total_cost += qual_cost.startup + qual_cost.per_tuple;
1553  }
1554 
1555  return pathnode;
1556 }
double cpu_tuple_cost
Definition: costsize.c:122
void cost_qual_eval(QualCost *cost, List *quals, PlannerInfo *root)
Definition: costsize.c:4612

References RelOptInfo::consider_parallel, PathTarget::cost, cost_qual_eval(), cpu_tuple_cost, makeNode, NIL, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, GroupResultPath::path, Path::pathkeys, Path::pathtype, QualCost::per_tuple, GroupResultPath::quals, Path::rows, QualCost::startup, Path::startup_cost, and Path::total_cost.

Referenced by create_degenerate_grouping_paths(), and query_planner().

◆ create_groupingsets_path()

GroupingSetsPath* create_groupingsets_path ( PlannerInfo root,
RelOptInfo rel,
Path subpath,
List having_qual,
AggStrategy  aggstrategy,
List rollups,
const AggClauseCosts agg_costs 
)

Definition at line 3196 of file pathnode.c.

3203 {
3205  PathTarget *target = rel->reltarget;
3206  ListCell *lc;
3207  bool is_first = true;
3208  bool is_first_sort = true;
3209 
3210  /* The topmost generated Plan node will be an Agg */
3211  pathnode->path.pathtype = T_Agg;
3212  pathnode->path.parent = rel;
3213  pathnode->path.pathtarget = target;
3214  pathnode->path.param_info = subpath->param_info;
3215  pathnode->path.parallel_aware = false;
3216  pathnode->path.parallel_safe = rel->consider_parallel &&
3217  subpath->parallel_safe;
3218  pathnode->path.parallel_workers = subpath->parallel_workers;
3219  pathnode->subpath = subpath;
3220 
3221  /*
3222  * Simplify callers by downgrading AGG_SORTED to AGG_PLAIN, and AGG_MIXED
3223  * to AGG_HASHED, here if possible.
3224  */
3225  if (aggstrategy == AGG_SORTED &&
3226  list_length(rollups) == 1 &&
3227  ((RollupData *) linitial(rollups))->groupClause == NIL)
3228  aggstrategy = AGG_PLAIN;
3229 
3230  if (aggstrategy == AGG_MIXED &&
3231  list_length(rollups) == 1)
3232  aggstrategy = AGG_HASHED;
3233 
3234  /*
3235  * Output will be in sorted order by group_pathkeys if, and only if, there
3236  * is a single rollup operation on a non-empty list of grouping
3237  * expressions.
3238  */
3239  if (aggstrategy == AGG_SORTED && list_length(rollups) == 1)
3240  pathnode->path.pathkeys = root->group_pathkeys;
3241  else
3242  pathnode->path.pathkeys = NIL;
3243 
3244  pathnode->aggstrategy = aggstrategy;
3245  pathnode->rollups = rollups;
3246  pathnode->qual = having_qual;
3247  pathnode->transitionSpace = agg_costs ? agg_costs->transitionSpace : 0;
3248 
3249  Assert(rollups != NIL);
3250  Assert(aggstrategy != AGG_PLAIN || list_length(rollups) == 1);
3251  Assert(aggstrategy != AGG_MIXED || list_length(rollups) > 1);
3252 
3253  foreach(lc, rollups)
3254  {
3255  RollupData *rollup = lfirst(lc);
3256  List *gsets = rollup->gsets;
3257  int numGroupCols = list_length(linitial(gsets));
3258 
3259  /*
3260  * In AGG_SORTED or AGG_PLAIN mode, the first rollup takes the
3261  * (already-sorted) input, and following ones do their own sort.
3262  *
3263  * In AGG_HASHED mode, there is one rollup for each grouping set.
3264  *
3265  * In AGG_MIXED mode, the first rollups are hashed, the first
3266  * non-hashed one takes the (already-sorted) input, and following ones
3267  * do their own sort.
3268  */
3269  if (is_first)
3270  {
3271  cost_agg(&pathnode->path, root,
3272  aggstrategy,
3273  agg_costs,
3274  numGroupCols,
3275  rollup->numGroups,
3276  having_qual,
3277  subpath->startup_cost,
3278  subpath->total_cost,
3279  subpath->rows,
3280  subpath->pathtarget->width);
3281  is_first = false;
3282  if (!rollup->is_hashed)
3283  is_first_sort = false;
3284  }
3285  else
3286  {
3287  Path sort_path; /* dummy for result of cost_sort */
3288  Path agg_path; /* dummy for result of cost_agg */
3289 
3290  if (rollup->is_hashed || is_first_sort)
3291  {
3292  /*
3293  * Account for cost of aggregation, but don't charge input
3294  * cost again
3295  */
3296  cost_agg(&agg_path, root,
3297  rollup->is_hashed ? AGG_HASHED : AGG_SORTED,
3298  agg_costs,
3299  numGroupCols,
3300  rollup->numGroups,
3301  having_qual,
3302  0.0, 0.0,
3303  subpath->rows,
3304  subpath->pathtarget->width);
3305  if (!rollup->is_hashed)
3306  is_first_sort = false;
3307  }
3308  else
3309  {
3310  /* Account for cost of sort, but don't charge input cost again */
3311  cost_sort(&sort_path, root, NIL,
3312  0.0,
3313  subpath->rows,
3314  subpath->pathtarget->width,
3315  0.0,
3316  work_mem,
3317  -1.0);
3318 
3319  /* Account for cost of aggregation */
3320 
3321  cost_agg(&agg_path, root,
3322  AGG_SORTED,
3323  agg_costs,
3324  numGroupCols,
3325  rollup->numGroups,
3326  having_qual,
3327  sort_path.startup_cost,
3328  sort_path.total_cost,
3329  sort_path.rows,
3330  subpath->pathtarget->width);
3331  }
3332 
3333  pathnode->path.total_cost += agg_path.total_cost;
3334  pathnode->path.rows += agg_path.rows;
3335  }
3336  }
3337 
3338  /* add tlist eval cost for each output row */
3339  pathnode->path.startup_cost += target->cost.startup;
3340  pathnode->path.total_cost += target->cost.startup +
3341  target->cost.per_tuple * pathnode->path.rows;
3342 
3343  return pathnode;
3344 }
@ AGG_HASHED
Definition: nodes.h:366
@ AGG_MIXED
Definition: nodes.h:367
@ AGG_PLAIN
Definition: nodes.h:364
uint64 transitionSpace
Definition: pathnodes.h:2268
AggStrategy aggstrategy
Definition: pathnodes.h:2265
List * group_pathkeys
Definition: pathnodes.h:385
Cardinality numGroups
Definition: pathnodes.h:2252
List * gsets
Definition: pathnodes.h:2250
bool is_hashed
Definition: pathnodes.h:2254

References AGG_HASHED, AGG_MIXED, AGG_PLAIN, AGG_SORTED, GroupingSetsPath::aggstrategy, Assert(), RelOptInfo::consider_parallel, PathTarget::cost, cost_agg(), cost_sort(), PlannerInfo::group_pathkeys, RollupData::gsets, RollupData::is_hashed, lfirst, linitial, list_length(), makeNode, NIL, RollupData::numGroups, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, GroupingSetsPath::path, Path::pathkeys, Path::pathtype, QualCost::per_tuple, GroupingSetsPath::qual, RelOptInfo::reltarget, GroupingSetsPath::rollups, Path::rows, QualCost::startup, Path::startup_cost, subpath(), GroupingSetsPath::subpath, Path::total_cost, AggClauseCosts::transitionSpace, GroupingSetsPath::transitionSpace, and work_mem.

Referenced by consider_groupingsets_paths().

◆ create_hashjoin_path()

HashPath* create_hashjoin_path ( PlannerInfo root,
RelOptInfo joinrel,
JoinType  jointype,
JoinCostWorkspace workspace,
JoinPathExtraData extra,
Path outer_path,
Path inner_path,
bool  parallel_hash,
List restrict_clauses,
Relids  required_outer,
List hashclauses 
)

Definition at line 2578 of file pathnode.c.

2589 {
2590  HashPath *pathnode = makeNode(HashPath);
2591 
2592  pathnode->jpath.path.pathtype = T_HashJoin;
2593  pathnode->jpath.path.parent = joinrel;
2594  pathnode->jpath.path.pathtarget = joinrel->reltarget;
2595  pathnode->jpath.path.param_info =
2597  joinrel,
2598  outer_path,
2599  inner_path,
2600  extra->sjinfo,
2601  required_outer,
2602  &restrict_clauses);
2603  pathnode->jpath.path.parallel_aware =
2604  joinrel->consider_parallel && parallel_hash;
2605  pathnode->jpath.path.parallel_safe = joinrel->consider_parallel &&
2606  outer_path->parallel_safe && inner_path->parallel_safe;
2607  /* This is a foolish way to estimate parallel_workers, but for now... */
2608  pathnode->jpath.path.parallel_workers = outer_path->parallel_workers;
2609 
2610  /*
2611  * A hashjoin never has pathkeys, since its output ordering is
2612  * unpredictable due to possible batching. XXX If the inner relation is
2613  * small enough, we could instruct the executor that it must not batch,
2614  * and then we could assume that the output inherits the outer relation's
2615  * ordering, which might save a sort step. However there is considerable
2616  * downside if our estimate of the inner relation size is badly off. For
2617  * the moment we don't risk it. (Note also that if we wanted to take this
2618  * seriously, joinpath.c would have to consider many more paths for the
2619  * outer rel than it does now.)
2620  */
2621  pathnode->jpath.path.pathkeys = NIL;
2622  pathnode->jpath.jointype = jointype;
2623  pathnode->jpath.inner_unique = extra->inner_unique;
2624  pathnode->jpath.outerjoinpath = outer_path;
2625  pathnode->jpath.innerjoinpath = inner_path;
2626  pathnode->jpath.joinrestrictinfo = restrict_clauses;
2627  pathnode->path_hashclauses = hashclauses;
2628  /* final_cost_hashjoin will fill in pathnode->num_batches */
2629 
2630  final_cost_hashjoin(root, pathnode, workspace, extra);
2631 
2632  return pathnode;
2633 }
void final_cost_hashjoin(PlannerInfo *root, HashPath *path, JoinCostWorkspace *workspace, JoinPathExtraData *extra)
Definition: costsize.c:4153
ParamPathInfo * get_joinrel_parampathinfo(PlannerInfo *root, RelOptInfo *joinrel, Path *outer_path, Path *inner_path, SpecialJoinInfo *sjinfo, Relids required_outer, List **restrict_clauses)
Definition: relnode.c:1632
List * path_hashclauses
Definition: pathnodes.h:2120
JoinPath jpath
Definition: pathnodes.h:2119
SpecialJoinInfo * sjinfo
Definition: pathnodes.h:3192
Path * outerjoinpath
Definition: pathnodes.h:2042
Path * innerjoinpath
Definition: pathnodes.h:2043
JoinType jointype
Definition: pathnodes.h:2037
bool inner_unique
Definition: pathnodes.h:2039
List * joinrestrictinfo
Definition: pathnodes.h:2045

References RelOptInfo::consider_parallel, final_cost_hashjoin(), get_joinrel_parampathinfo(), JoinPath::inner_unique, JoinPathExtraData::inner_unique, JoinPath::innerjoinpath, JoinPath::joinrestrictinfo, JoinPath::jointype, HashPath::jpath, makeNode, NIL, JoinPath::outerjoinpath, Path::parallel_safe, Path::parallel_workers, HashPath::path_hashclauses, RelOptInfo::reltarget, and JoinPathExtraData::sjinfo.

Referenced by try_hashjoin_path(), and try_partial_hashjoin_path().

◆ create_incremental_sort_path()

IncrementalSortPath* create_incremental_sort_path ( PlannerInfo root,
RelOptInfo rel,
Path subpath,
List pathkeys,
int  presorted_keys,
double  limit_tuples 
)

Definition at line 2910 of file pathnode.c.

2916 {
2918  SortPath *pathnode = &sort->spath;
2919 
2920  pathnode->path.pathtype = T_IncrementalSort;
2921  pathnode->path.parent = rel;
2922  /* Sort doesn't project, so use source path's pathtarget */
2923  pathnode->path.pathtarget = subpath->pathtarget;
2924  /* For now, assume we are above any joins, so no parameterization */
2925  pathnode->path.param_info = NULL;
2926  pathnode->path.parallel_aware = false;
2927  pathnode->path.parallel_safe = rel->consider_parallel &&
2928  subpath->parallel_safe;
2929  pathnode->path.parallel_workers = subpath->parallel_workers;
2930  pathnode->path.pathkeys = pathkeys;
2931 
2932  pathnode->subpath = subpath;
2933 
2934  cost_incremental_sort(&pathnode->path,
2935  root, pathkeys, presorted_keys,
2936  subpath->startup_cost,
2937  subpath->total_cost,
2938  subpath->rows,
2939  subpath->pathtarget->width,
2940  0.0, /* XXX comparison_cost shouldn't be 0? */
2941  work_mem, limit_tuples);
2942 
2943  sort->nPresortedCols = presorted_keys;
2944 
2945  return sort;
2946 }
Datum sort(PG_FUNCTION_ARGS)
Definition: _int_op.c:195
void cost_incremental_sort(Path *path, PlannerInfo *root, List *pathkeys, int presorted_keys, Cost input_startup_cost, Cost input_total_cost, double input_tuples, int width, Cost comparison_cost, int sort_mem, double limit_tuples)
Definition: costsize.c:1958
Path path
Definition: pathnodes.h:2167
Path * subpath
Definition: pathnodes.h:2168

References RelOptInfo::consider_parallel, cost_incremental_sort(), makeNode, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, SortPath::path, Path::pathkeys, Path::pathtype, sort(), subpath(), SortPath::subpath, and work_mem.

Referenced by add_paths_to_grouping_rel(), create_final_distinct_paths(), create_one_window_path(), create_ordered_paths(), create_partial_distinct_paths(), create_partial_grouping_paths(), gather_grouping_paths(), and generate_useful_gather_paths().

◆ create_index_path()

IndexPath* create_index_path ( PlannerInfo root,
IndexOptInfo index,
List indexclauses,
List indexorderbys,
List indexorderbycols,
List pathkeys,
ScanDirection  indexscandir,
bool  indexonly,
Relids  required_outer,
double  loop_count,
bool  partial_path 
)

Definition at line 995 of file pathnode.c.

1006 {
1007  IndexPath *pathnode = makeNode(IndexPath);
1008  RelOptInfo *rel = index->rel;
1009 
1010  pathnode->path.pathtype = indexonly ? T_IndexOnlyScan : T_IndexScan;
1011  pathnode->path.parent = rel;
1012  pathnode->path.pathtarget = rel->reltarget;
1013  pathnode->path.param_info = get_baserel_parampathinfo(root, rel,
1014  required_outer);
1015  pathnode->path.parallel_aware = false;
1016  pathnode->path.parallel_safe = rel->consider_parallel;
1017  pathnode->path.parallel_workers = 0;
1018  pathnode->path.pathkeys = pathkeys;
1019 
1020  pathnode->indexinfo = index;
1021  pathnode->indexclauses = indexclauses;
1022  pathnode->indexorderbys = indexorderbys;
1023  pathnode->indexorderbycols = indexorderbycols;
1024  pathnode->indexscandir = indexscandir;
1025 
1026  cost_index(pathnode, root, loop_count, partial_path);
1027 
1028  return pathnode;
1029 }
void cost_index(IndexPath *path, PlannerInfo *root, double loop_count, bool partial_path)
Definition: costsize.c:521
List * indexclauses
Definition: pathnodes.h:1679
ScanDirection indexscandir
Definition: pathnodes.h:1682
Path path
Definition: pathnodes.h:1677
List * indexorderbycols
Definition: pathnodes.h:1681
List * indexorderbys
Definition: pathnodes.h:1680
IndexOptInfo * indexinfo
Definition: pathnodes.h:1678
Definition: type.h:95

References RelOptInfo::consider_parallel, cost_index(), get_baserel_parampathinfo(), IndexPath::indexclauses, IndexPath::indexinfo, IndexPath::indexorderbycols, IndexPath::indexorderbys, IndexPath::indexscandir, makeNode, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, IndexPath::path, Path::pathkeys, Path::pathtype, and RelOptInfo::reltarget.

Referenced by build_index_paths(), and plan_cluster_use_sort().

◆ create_limit_path()

LimitPath* create_limit_path ( PlannerInfo root,
RelOptInfo rel,
Path subpath,
Node limitOffset,
Node limitCount,
LimitOption  limitOption,
int64  offset_est,
int64  count_est 
)

Definition at line 3779 of file pathnode.c.

3784 {
3785  LimitPath *pathnode = makeNode(LimitPath);
3786 
3787  pathnode->path.pathtype = T_Limit;
3788  pathnode->path.parent = rel;
3789  /* Limit doesn't project, so use source path's pathtarget */
3790  pathnode->path.pathtarget = subpath->pathtarget;
3791  /* For now, assume we are above any joins, so no parameterization */
3792  pathnode->path.param_info = NULL;
3793  pathnode->path.parallel_aware = false;
3794  pathnode->path.parallel_safe = rel->consider_parallel &&
3795  subpath->parallel_safe;
3796  pathnode->path.parallel_workers = subpath->parallel_workers;
3797  pathnode->path.rows = subpath->rows;
3798  pathnode->path.startup_cost = subpath->startup_cost;
3799  pathnode->path.total_cost = subpath->total_cost;
3800  pathnode->path.pathkeys = subpath->pathkeys;
3801  pathnode->subpath = subpath;
3802  pathnode->limitOffset = limitOffset;
3803  pathnode->limitCount = limitCount;
3804  pathnode->limitOption = limitOption;
3805 
3806  /*
3807  * Adjust the output rows count and costs according to the offset/limit.
3808  */
3809  adjust_limit_rows_costs(&pathnode->path.rows,
3810  &pathnode->path.startup_cost,
3811  &pathnode->path.total_cost,
3812  offset_est, count_est);
3813 
3814  return pathnode;
3815 }
void adjust_limit_rows_costs(double *rows, Cost *startup_cost, Cost *total_cost, int64 offset_est, int64 count_est)
Definition: pathnode.c:3834
Path path
Definition: pathnodes.h:2365
Path * subpath
Definition: pathnodes.h:2366
LimitOption limitOption
Definition: pathnodes.h:2369
Node * limitOffset
Definition: pathnodes.h:2367
Node * limitCount
Definition: pathnodes.h:2368

References adjust_limit_rows_costs(), RelOptInfo::consider_parallel, LimitPath::limitCount, LimitPath::limitOffset, LimitPath::limitOption, makeNode, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, LimitPath::path, Path::pathkeys, Path::pathtype, Path::rows, Path::startup_cost, subpath(), LimitPath::subpath, and Path::total_cost.

Referenced by create_final_distinct_paths(), and grouping_planner().

◆ create_lockrows_path()

LockRowsPath* create_lockrows_path ( PlannerInfo root,
RelOptInfo rel,
Path subpath,
List rowMarks,
int  epqParam 
)

Definition at line 3618 of file pathnode.c.

3620 {
3621  LockRowsPath *pathnode = makeNode(LockRowsPath);
3622 
3623  pathnode->path.pathtype = T_LockRows;
3624  pathnode->path.parent = rel;
3625  /* LockRows doesn't project, so use source path's pathtarget */
3626  pathnode->path.pathtarget = subpath->pathtarget;
3627  /* For now, assume we are above any joins, so no parameterization */
3628  pathnode->path.param_info = NULL;
3629  pathnode->path.parallel_aware = false;
3630  pathnode->path.parallel_safe = false;
3631  pathnode->path.parallel_workers = 0;
3632  pathnode->path.rows = subpath->rows;
3633 
3634  /*
3635  * The result cannot be assumed sorted, since locking might cause the sort
3636  * key columns to be replaced with new values.
3637  */
3638  pathnode->path.pathkeys = NIL;
3639 
3640  pathnode->subpath = subpath;
3641  pathnode->rowMarks = rowMarks;
3642  pathnode->epqParam = epqParam;
3643 
3644  /*
3645  * We should charge something extra for the costs of row locking and
3646  * possible refetches, but it's hard to say how much. For now, use
3647  * cpu_tuple_cost per row.
3648  */
3649  pathnode->path.startup_cost = subpath->startup_cost;
3650  pathnode->path.total_cost = subpath->total_cost +
3651  cpu_tuple_cost * subpath->rows;
3652 
3653  return pathnode;
3654 }
Path * subpath
Definition: pathnodes.h:2328
List * rowMarks
Definition: pathnodes.h:2329

References cpu_tuple_cost, LockRowsPath::epqParam, makeNode, NIL, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, LockRowsPath::path, Path::pathkeys, Path::pathtype, LockRowsPath::rowMarks, Path::rows, Path::startup_cost, subpath(), LockRowsPath::subpath, and Path::total_cost.

Referenced by grouping_planner().

◆ create_material_path()

MaterialPath* create_material_path ( RelOptInfo rel,
Path subpath 
)

Definition at line 1564 of file pathnode.c.

1565 {
1566  MaterialPath *pathnode = makeNode(MaterialPath);
1567 
1568  Assert(subpath->parent == rel);
1569 
1570  pathnode->path.pathtype = T_Material;
1571  pathnode->path.parent = rel;
1572  pathnode->path.pathtarget = rel->reltarget;
1573  pathnode->path.param_info = subpath->param_info;
1574  pathnode->path.parallel_aware = false;
1575  pathnode->path.parallel_safe = rel->consider_parallel &&
1576  subpath->parallel_safe;
1577  pathnode->path.parallel_workers = subpath->parallel_workers;
1578  pathnode->path.pathkeys = subpath->pathkeys;
1579 
1580  pathnode->subpath = subpath;
1581 
1582  cost_material(&pathnode->path,
1583  subpath->startup_cost,
1584  subpath->total_cost,
1585  subpath->rows,
1586  subpath->pathtarget->width);
1587 
1588  return pathnode;
1589 }
void cost_material(Path *path, Cost input_startup_cost, Cost input_total_cost, double tuples, int width)
Definition: costsize.c:2425
Path * subpath
Definition: pathnodes.h:1950

References Assert(), RelOptInfo::consider_parallel, cost_material(), makeNode, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, MaterialPath::path, Path::pathkeys, Path::pathtype, RelOptInfo::reltarget, subpath(), and MaterialPath::subpath.

Referenced by match_unsorted_outer(), reparameterize_path(), and set_tablesample_rel_pathlist().

◆ create_memoize_path()

MemoizePath* create_memoize_path ( PlannerInfo root,
RelOptInfo rel,
Path subpath,
List param_exprs,
List hash_operators,
bool  singlerow,
bool  binary_mode,
double  calls 
)

Definition at line 1596 of file pathnode.c.

1599 {
1600  MemoizePath *pathnode = makeNode(MemoizePath);
1601 
1602  Assert(subpath->parent == rel);
1603 
1604  pathnode->path.pathtype = T_Memoize;
1605  pathnode->path.parent = rel;
1606  pathnode->path.pathtarget = rel->reltarget;
1607  pathnode->path.param_info = subpath->param_info;
1608  pathnode->path.parallel_aware = false;
1609  pathnode->path.parallel_safe = rel->consider_parallel &&
1610  subpath->parallel_safe;
1611  pathnode->path.parallel_workers = subpath->parallel_workers;
1612  pathnode->path.pathkeys = subpath->pathkeys;
1613 
1614  pathnode->subpath = subpath;
1615  pathnode->hash_operators = hash_operators;
1616  pathnode->param_exprs = param_exprs;
1617  pathnode->singlerow = singlerow;
1618  pathnode->binary_mode = binary_mode;
1619  pathnode->calls = calls;
1620 
1621  /*
1622  * For now we set est_entries to 0. cost_memoize_rescan() does all the
1623  * hard work to determine how many cache entries there are likely to be,
1624  * so it seems best to leave it up to that function to fill this field in.
1625  * If left at 0, the executor will make a guess at a good value.
1626  */
1627  pathnode->est_entries = 0;
1628 
1629  /*
1630  * Add a small additional charge for caching the first entry. All the
1631  * harder calculations for rescans are performed in cost_memoize_rescan().
1632  */
1633  pathnode->path.startup_cost = subpath->startup_cost + cpu_tuple_cost;
1634  pathnode->path.total_cost = subpath->total_cost + cpu_tuple_cost;
1635  pathnode->path.rows = subpath->rows;
1636 
1637  return pathnode;
1638 }
bool singlerow
Definition: pathnodes.h:1964
List * hash_operators
Definition: pathnodes.h:1962
uint32 est_entries
Definition: pathnodes.h:1969
bool binary_mode
Definition: pathnodes.h:1966
Cardinality calls
Definition: pathnodes.h:1968
Path * subpath
Definition: pathnodes.h:1961
List * param_exprs
Definition: pathnodes.h:1963

References Assert(), MemoizePath::binary_mode, MemoizePath::calls, RelOptInfo::consider_parallel, cpu_tuple_cost, MemoizePath::est_entries, MemoizePath::hash_operators, makeNode, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, MemoizePath::param_exprs, MemoizePath::path, Path::pathkeys, Path::pathtype, RelOptInfo::reltarget, Path::rows, MemoizePath::singlerow, Path::startup_cost, subpath(), MemoizePath::subpath, and Path::total_cost.

Referenced by get_memoize_path(), and reparameterize_path().

◆ create_merge_append_path()

MergeAppendPath* create_merge_append_path ( PlannerInfo root,
RelOptInfo rel,
List subpaths,
List pathkeys,
Relids  required_outer 
)

Definition at line 1413 of file pathnode.c.

1418 {
1420  Cost input_startup_cost;
1421  Cost input_total_cost;
1422  ListCell *l;
1423 
1424  pathnode->path.pathtype = T_MergeAppend;
1425  pathnode->path.parent = rel;
1426  pathnode->path.pathtarget = rel->reltarget;
1427  pathnode->path.param_info = get_appendrel_parampathinfo(rel,
1428  required_outer);
1429  pathnode->path.parallel_aware = false;
1430  pathnode->path.parallel_safe = rel->consider_parallel;
1431  pathnode->path.parallel_workers = 0;
1432  pathnode->path.pathkeys = pathkeys;
1433  pathnode->subpaths = subpaths;
1434 
1435  /*
1436  * Apply query-wide LIMIT if known and path is for sole base relation.
1437  * (Handling this at this low level is a bit klugy.)
1438  */
1439  if (bms_equal(rel->relids, root->all_query_rels))
1440  pathnode->limit_tuples = root->limit_tuples;
1441  else
1442  pathnode->limit_tuples = -1.0;
1443 
1444  /*
1445  * Add up the sizes and costs of the input paths.
1446  */
1447  pathnode->path.rows = 0;
1448  input_startup_cost = 0;
1449  input_total_cost = 0;
1450  foreach(l, subpaths)
1451  {
1452  Path *subpath = (Path *) lfirst(l);
1453 
1454  pathnode->path.rows += subpath->rows;
1455  pathnode->path.parallel_safe = pathnode->path.parallel_safe &&
1456  subpath->parallel_safe;
1457 
1458  if (pathkeys_contained_in(pathkeys, subpath->pathkeys))
1459  {
1460  /* Subpath is adequately ordered, we won't need to sort it */
1461  input_startup_cost += subpath->startup_cost;
1462  input_total_cost += subpath->total_cost;
1463  }
1464  else
1465  {
1466  /* We'll need to insert a Sort node, so include cost for that */
1467  Path sort_path; /* dummy for result of cost_sort */
1468 
1469  cost_sort(&sort_path,
1470  root,
1471  pathkeys,
1472  subpath->total_cost,
1473  subpath->parent->tuples,
1474  subpath->pathtarget->width,
1475  0.0,
1476  work_mem,
1477  pathnode->limit_tuples);
1478  input_startup_cost += sort_path.startup_cost;
1479  input_total_cost += sort_path.total_cost;
1480  }
1481 
1482  /* All child paths must have same parameterization */
1483  Assert(bms_equal(PATH_REQ_OUTER(subpath), required_outer));
1484  }
1485 
1486  /*
1487  * Now we can compute total costs of the MergeAppend. If there's exactly
1488  * one child path and its parallel awareness matches that of the
1489  * MergeAppend, then the MergeAppend is a no-op and will be discarded
1490  * later (in setrefs.c); otherwise we do the normal cost calculation.
1491  */
1492  if (list_length(subpaths) == 1 &&
1493  ((Path *) linitial(subpaths))->parallel_aware ==
1494  pathnode->path.parallel_aware)
1495  {
1496  pathnode->path.startup_cost = input_startup_cost;
1497  pathnode->path.total_cost = input_total_cost;
1498  }
1499  else
1500  cost_merge_append(&pathnode->path, root,
1501  pathkeys, list_length(subpaths),
1502  input_startup_cost, input_total_cost,
1503  pathnode->path.rows);
1504 
1505  return pathnode;
1506 }
void cost_merge_append(Path *path, PlannerInfo *root, List *pathkeys, int n_streams, Cost input_startup_cost, Cost input_total_cost, double tuples)
Definition: costsize.c:2376
Cardinality limit_tuples
Definition: pathnodes.h:1925

References PlannerInfo::all_query_rels, Assert(), bms_equal(), RelOptInfo::consider_parallel, cost_merge_append(), cost_sort(), get_appendrel_parampathinfo(), lfirst, PlannerInfo::limit_tuples, MergeAppendPath::limit_tuples, linitial, list_length(), makeNode, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, MergeAppendPath::path, PATH_REQ_OUTER, Path::pathkeys, pathkeys_contained_in(), Path::pathtype, RelOptInfo::relids, RelOptInfo::reltarget, Path::rows, Path::startup_cost, subpath(), MergeAppendPath::subpaths, Path::total_cost, and work_mem.

Referenced by generate_orderedappend_paths().

◆ create_mergejoin_path()

MergePath* create_mergejoin_path ( PlannerInfo root,
RelOptInfo joinrel,
JoinType  jointype,
JoinCostWorkspace workspace,
JoinPathExtraData extra,
Path outer_path,
Path inner_path,
List restrict_clauses,
List pathkeys,
Relids  required_outer,
List mergeclauses,
List outersortkeys,
List innersortkeys 
)

Definition at line 2512 of file pathnode.c.

2525 {
2526  MergePath *pathnode = makeNode(MergePath);
2527 
2528  pathnode->jpath.path.pathtype = T_MergeJoin;
2529  pathnode->jpath.path.parent = joinrel;
2530  pathnode->jpath.path.pathtarget = joinrel->reltarget;
2531  pathnode->jpath.path.param_info =
2533  joinrel,
2534  outer_path,
2535  inner_path,
2536  extra->sjinfo,
2537  required_outer,
2538  &restrict_clauses);
2539  pathnode->jpath.path.parallel_aware = false;
2540  pathnode->jpath.path.parallel_safe = joinrel->consider_parallel &&
2541  outer_path->parallel_safe && inner_path->parallel_safe;
2542  /* This is a foolish way to estimate parallel_workers, but for now... */
2543  pathnode->jpath.path.parallel_workers = outer_path->parallel_workers;
2544  pathnode->jpath.path.pathkeys = pathkeys;
2545  pathnode->jpath.jointype = jointype;
2546  pathnode->jpath.inner_unique = extra->inner_unique;
2547  pathnode->jpath.outerjoinpath = outer_path;
2548  pathnode->jpath.innerjoinpath = inner_path;
2549  pathnode->jpath.joinrestrictinfo = restrict_clauses;
2550  pathnode->path_mergeclauses = mergeclauses;
2551  pathnode->outersortkeys = outersortkeys;
2552  pathnode->innersortkeys = innersortkeys;
2553  /* pathnode->skip_mark_restore will be set by final_cost_mergejoin */
2554  /* pathnode->materialize_inner will be set by final_cost_mergejoin */
2555 
2556  final_cost_mergejoin(root, pathnode, workspace, extra);
2557 
2558  return pathnode;
2559 }
void final_cost_mergejoin(PlannerInfo *root, MergePath *path, JoinCostWorkspace *workspace, JoinPathExtraData *extra)
Definition: costsize.c:3717
List * outersortkeys
Definition: pathnodes.h:2102
List * innersortkeys
Definition: pathnodes.h:2103
JoinPath jpath
Definition: pathnodes.h:2100
List * path_mergeclauses
Definition: pathnodes.h:2101

References RelOptInfo::consider_parallel, final_cost_mergejoin(), get_joinrel_parampathinfo(), JoinPath::inner_unique, JoinPathExtraData::inner_unique, JoinPath::innerjoinpath, MergePath::innersortkeys, JoinPath::joinrestrictinfo, JoinPath::jointype, MergePath::jpath, makeNode, JoinPath::outerjoinpath, MergePath::outersortkeys, Path::parallel_safe, Path::parallel_workers, MergePath::path_mergeclauses, RelOptInfo::reltarget, and JoinPathExtraData::sjinfo.

Referenced by try_mergejoin_path(), and try_partial_mergejoin_path().

◆ create_minmaxagg_path()

MinMaxAggPath* create_minmaxagg_path ( PlannerInfo root,
RelOptInfo rel,
PathTarget target,
List mmaggregates,
List quals 
)

Definition at line 3356 of file pathnode.c.

3361 {
3362  MinMaxAggPath *pathnode = makeNode(MinMaxAggPath);
3363  Cost initplan_cost;
3364  ListCell *lc;
3365 
3366  /* The topmost generated Plan node will be a Result */
3367  pathnode->path.pathtype = T_Result;
3368  pathnode->path.parent = rel;
3369  pathnode->path.pathtarget = target;
3370  /* For now, assume we are above any joins, so no parameterization */
3371  pathnode->path.param_info = NULL;
3372  pathnode->path.parallel_aware = false;
3373  pathnode->path.parallel_safe = true; /* might change below */
3374  pathnode->path.parallel_workers = 0;
3375  /* Result is one unordered row */
3376  pathnode->path.rows = 1;
3377  pathnode->path.pathkeys = NIL;
3378 
3379  pathnode->mmaggregates = mmaggregates;
3380  pathnode->quals = quals;
3381 
3382  /* Calculate cost of all the initplans, and check parallel safety */
3383  initplan_cost = 0;
3384  foreach(lc, mmaggregates)
3385  {
3386  MinMaxAggInfo *mminfo = (MinMaxAggInfo *) lfirst(lc);
3387 
3388  initplan_cost += mminfo->pathcost;
3389  if (!mminfo->path->parallel_safe)
3390  pathnode->path.parallel_safe = false;
3391  }
3392 
3393  /* add tlist eval cost for each output row, plus cpu_tuple_cost */
3394  pathnode->path.startup_cost = initplan_cost + target->cost.startup;
3395  pathnode->path.total_cost = initplan_cost + target->cost.startup +
3396  target->cost.per_tuple + cpu_tuple_cost;
3397 
3398  /*
3399  * Add cost of qual, if any --- but we ignore its selectivity, since our
3400  * rowcount estimate should be 1 no matter what the qual is.
3401  */
3402  if (quals)
3403  {
3404  QualCost qual_cost;
3405 
3406  cost_qual_eval(&qual_cost, quals, root);
3407  pathnode->path.startup_cost += qual_cost.startup;
3408  pathnode->path.total_cost += qual_cost.startup + qual_cost.per_tuple;
3409  }
3410 
3411  /*
3412  * If the initplans were all parallel-safe, also check safety of the
3413  * target and quals. (The Result node itself isn't parallelizable, but if
3414  * we are in a subquery then it can be useful for the outer query to know
3415  * that this one is parallel-safe.)
3416  */
3417  if (pathnode->path.parallel_safe)
3418  pathnode->path.parallel_safe =
3419  is_parallel_safe(root, (Node *) target->exprs) &&
3420  is_parallel_safe(root, (Node *) quals);
3421 
3422  return pathnode;
3423 }
List * quals
Definition: pathnodes.h:2278
List * mmaggregates
Definition: pathnodes.h:2277

References PathTarget::cost, cost_qual_eval(), cpu_tuple_cost, PathTarget::exprs, is_parallel_safe(), lfirst, makeNode, MinMaxAggPath::mmaggregates, NIL, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, MinMaxAggPath::path, MinMaxAggInfo::path, MinMaxAggInfo::pathcost, Path::pathkeys, Path::pathtype, QualCost::per_tuple, MinMaxAggPath::quals, Path::rows, QualCost::startup, Path::startup_cost, and Path::total_cost.

Referenced by preprocess_minmax_aggregates().

◆ create_modifytable_path()

ModifyTablePath* create_modifytable_path ( PlannerInfo root,
RelOptInfo rel,
Path subpath,
CmdType  operation,
bool  canSetTag,
Index  nominalRelation,
Index  rootRelation,
bool  partColsUpdated,
List resultRelations,
List updateColnosLists,
List withCheckOptionLists,
List returningLists,
List rowMarks,
OnConflictExpr onconflict,
List mergeActionLists,
int  epqParam 
)

Definition at line 3680 of file pathnode.c.

3690 {
3692 
3693  Assert(operation == CMD_MERGE ||
3694  (operation == CMD_UPDATE ?
3695  list_length(resultRelations) == list_length(updateColnosLists) :
3696  updateColnosLists == NIL));
3697  Assert(withCheckOptionLists == NIL ||
3698  list_length(resultRelations) == list_length(withCheckOptionLists));
3699  Assert(returningLists == NIL ||
3700  list_length(resultRelations) == list_length(returningLists));
3701 
3702  pathnode->path.pathtype = T_ModifyTable;
3703  pathnode->path.parent = rel;
3704  /* pathtarget is not interesting, just make it minimally valid */
3705  pathnode->path.pathtarget = rel->reltarget;
3706  /* For now, assume we are above any joins, so no parameterization */
3707  pathnode->path.param_info = NULL;
3708  pathnode->path.parallel_aware = false;
3709  pathnode->path.parallel_safe = false;
3710  pathnode->path.parallel_workers = 0;
3711  pathnode->path.pathkeys = NIL;
3712 
3713  /*
3714  * Compute cost & rowcount as subpath cost & rowcount (if RETURNING)
3715  *
3716  * Currently, we don't charge anything extra for the actual table
3717  * modification work, nor for the WITH CHECK OPTIONS or RETURNING
3718  * expressions if any. It would only be window dressing, since
3719  * ModifyTable is always a top-level node and there is no way for the
3720  * costs to change any higher-level planning choices. But we might want
3721  * to make it look better sometime.
3722  */
3723  pathnode->path.startup_cost = subpath->startup_cost;
3724  pathnode->path.total_cost = subpath->total_cost;
3725  if (returningLists != NIL)
3726  {
3727  pathnode->path.rows = subpath->rows;
3728 
3729  /*
3730  * Set width to match the subpath output. XXX this is totally wrong:
3731  * we should return an average of the RETURNING tlist widths. But
3732  * it's what happened historically, and improving it is a task for
3733  * another day. (Again, it's mostly window dressing.)
3734  */
3735  pathnode->path.pathtarget->width = subpath->pathtarget->width;
3736  }
3737  else
3738  {
3739  pathnode->path.rows = 0;
3740  pathnode->path.pathtarget->width = 0;
3741  }
3742 
3743  pathnode->subpath = subpath;
3744  pathnode->operation = operation;
3745  pathnode->canSetTag = canSetTag;
3746  pathnode->nominalRelation = nominalRelation;
3747  pathnode->rootRelation = rootRelation;
3748  pathnode->partColsUpdated = partColsUpdated;
3749  pathnode->resultRelations = resultRelations;
3750  pathnode->updateColnosLists = updateColnosLists;
3751  pathnode->withCheckOptionLists = withCheckOptionLists;
3752  pathnode->returningLists = returningLists;
3753  pathnode->rowMarks = rowMarks;
3754  pathnode->onconflict = onconflict;
3755  pathnode->epqParam = epqParam;
3756  pathnode->mergeActionLists = mergeActionLists;
3757 
3758  return pathnode;
3759 }
@ CMD_MERGE
Definition: nodes.h:280
@ CMD_UPDATE
Definition: nodes.h:277
bool partColsUpdated
Definition: pathnodes.h:2348
List * returningLists
Definition: pathnodes.h:2352
List * resultRelations
Definition: pathnodes.h:2349
List * withCheckOptionLists
Definition: pathnodes.h:2351
List * updateColnosLists
Definition: pathnodes.h:2350
OnConflictExpr * onconflict
Definition: pathnodes.h:2354
CmdType operation
Definition: pathnodes.h:2344
Index rootRelation
Definition: pathnodes.h:2347
Index nominalRelation
Definition: pathnodes.h:2346
List * mergeActionLists
Definition: pathnodes.h:2356

References Assert(), ModifyTablePath::canSetTag, CMD_MERGE, CMD_UPDATE, ModifyTablePath::epqParam, list_length(), makeNode, ModifyTablePath::mergeActionLists, NIL, ModifyTablePath::nominalRelation, ModifyTablePath::onconflict, ModifyTablePath::operation, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, ModifyTablePath::partColsUpdated, ModifyTablePath::path, Path::pathkeys, Path::pathtype, RelOptInfo::reltarget, ModifyTablePath::resultRelations, ModifyTablePath::returningLists, ModifyTablePath::rootRelation, ModifyTablePath::rowMarks, Path::rows, Path::startup_cost, subpath(), ModifyTablePath::subpath, Path::total_cost, ModifyTablePath::updateColnosLists, and ModifyTablePath::withCheckOptionLists.

Referenced by grouping_planner().

◆ create_namedtuplestorescan_path()

Path* create_namedtuplestorescan_path ( PlannerInfo root,
RelOptInfo rel,
Relids  required_outer 
)

Definition at line 2141 of file pathnode.c.

2143 {
2144  Path *pathnode = makeNode(Path);
2145 
2146  pathnode->pathtype = T_NamedTuplestoreScan;
2147  pathnode->parent = rel;
2148  pathnode->pathtarget = rel->reltarget;
2149  pathnode->param_info = get_baserel_parampathinfo(root, rel,
2150  required_outer);
2151  pathnode->parallel_aware = false;
2152  pathnode->parallel_safe = rel->consider_parallel;
2153  pathnode->parallel_workers = 0;
2154  pathnode->pathkeys = NIL; /* result is always unordered */
2155 
2156  cost_namedtuplestorescan(pathnode, root, rel, pathnode->param_info);
2157 
2158  return pathnode;
2159 }
void cost_namedtuplestorescan(Path *path, PlannerInfo *root, RelOptInfo *baserel, ParamPathInfo *param_info)
Definition: costsize.c:1711

References RelOptInfo::consider_parallel, cost_namedtuplestorescan(), get_baserel_parampathinfo(), makeNode, NIL, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, Path::pathkeys, Path::pathtype, and RelOptInfo::reltarget.

Referenced by set_namedtuplestore_pathlist().

◆ create_nestloop_path()

NestPath* create_nestloop_path ( PlannerInfo root,
RelOptInfo joinrel,
JoinType  jointype,
JoinCostWorkspace workspace,
JoinPathExtraData extra,
Path outer_path,
Path inner_path,
List restrict_clauses,
List pathkeys,
Relids  required_outer 
)

Definition at line 2426 of file pathnode.c.

2436 {
2437  NestPath *pathnode = makeNode(NestPath);
2438  Relids inner_req_outer = PATH_REQ_OUTER(inner_path);
2439 
2440  /*
2441  * If the inner path is parameterized by the outer, we must drop any
2442  * restrict_clauses that are due to be moved into the inner path. We have
2443  * to do this now, rather than postpone the work till createplan time,
2444  * because the restrict_clauses list can affect the size and cost
2445  * estimates for this path. We detect such clauses by checking for serial
2446  * number match to clauses already enforced in the inner path.
2447  */
2448  if (bms_overlap(inner_req_outer, outer_path->parent->relids))
2449  {
2450  Bitmapset *enforced_serials = get_param_path_clause_serials(inner_path);
2451  List *jclauses = NIL;
2452  ListCell *lc;
2453 
2454  foreach(lc, restrict_clauses)
2455  {
2456  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
2457 
2458  if (!bms_is_member(rinfo->rinfo_serial, enforced_serials))
2459  jclauses = lappend(jclauses, rinfo);
2460  }
2461  restrict_clauses = jclauses;
2462  }
2463 
2464  pathnode->jpath.path.pathtype = T_NestLoop;
2465  pathnode->jpath.path.parent = joinrel;
2466  pathnode->jpath.path.pathtarget = joinrel->reltarget;
2467  pathnode->jpath.path.param_info =
2469  joinrel,
2470  outer_path,
2471  inner_path,
2472  extra->sjinfo,
2473  required_outer,
2474  &restrict_clauses);
2475  pathnode->jpath.path.parallel_aware = false;
2476  pathnode->jpath.path.parallel_safe = joinrel->consider_parallel &&
2477  outer_path->parallel_safe && inner_path->parallel_safe;
2478  /* This is a foolish way to estimate parallel_workers, but for now... */
2479  pathnode->jpath.path.parallel_workers = outer_path->parallel_workers;
2480  pathnode->jpath.path.pathkeys = pathkeys;
2481  pathnode->jpath.jointype = jointype;
2482  pathnode->jpath.inner_unique = extra->inner_unique;
2483  pathnode->jpath.outerjoinpath = outer_path;
2484  pathnode->jpath.innerjoinpath = inner_path;
2485  pathnode->jpath.joinrestrictinfo = restrict_clauses;
2486 
2487  final_cost_nestloop(root, pathnode, workspace, extra);
2488 
2489  return pathnode;
2490 }
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:460
void final_cost_nestloop(PlannerInfo *root, NestPath *path, JoinCostWorkspace *workspace, JoinPathExtraData *extra)
Definition: costsize.c:3280
Bitmapset * get_param_path_clause_serials(Path *path)
Definition: relnode.c:1883
JoinPath jpath
Definition: pathnodes.h:2060
int rinfo_serial
Definition: pathnodes.h:2598

References bms_is_member(), bms_overlap(), RelOptInfo::consider_parallel, final_cost_nestloop(), get_joinrel_parampathinfo(), get_param_path_clause_serials(), JoinPath::inner_unique, JoinPathExtraData::inner_unique, JoinPath::innerjoinpath, JoinPath::joinrestrictinfo, JoinPath::jointype, NestPath::jpath, lappend(), lfirst, makeNode, NIL, JoinPath::outerjoinpath, Path::parallel_safe, Path::parallel_workers, PATH_REQ_OUTER, RelOptInfo::reltarget, RestrictInfo::rinfo_serial, and JoinPathExtraData::sjinfo.

Referenced by try_nestloop_path(), and try_partial_nestloop_path().

◆ create_projection_path()

ProjectionPath* create_projection_path ( PlannerInfo root,
RelOptInfo rel,
Path subpath,
PathTarget target 
)

Definition at line 2644 of file pathnode.c.

2648 {
2649  ProjectionPath *pathnode = makeNode(ProjectionPath);
2650  PathTarget *oldtarget;
2651 
2652  /*
2653  * We mustn't put a ProjectionPath directly above another; it's useless
2654  * and will confuse create_projection_plan. Rather than making sure all
2655  * callers handle that, let's implement it here, by stripping off any
2656  * ProjectionPath in what we're given. Given this rule, there won't be
2657  * more than one.
2658  */
2659  if (IsA(subpath, ProjectionPath))
2660  {
2661  ProjectionPath *subpp = (ProjectionPath *) subpath;
2662 
2663  Assert(subpp->path.parent == rel);
2664  subpath = subpp->subpath;
2666  }
2667 
2668  pathnode->path.pathtype = T_Result;
2669  pathnode->path.parent = rel;
2670  pathnode->path.pathtarget = target;
2671  /* For now, assume we are above any joins, so no parameterization */
2672  pathnode->path.param_info = NULL;
2673  pathnode->path.parallel_aware = false;
2674  pathnode->path.parallel_safe = rel->consider_parallel &&
2675  subpath->parallel_safe &&
2676  is_parallel_safe(root, (Node *) target->exprs);
2677  pathnode->path.parallel_workers = subpath->parallel_workers;
2678  /* Projection does not change the sort order */
2679  pathnode->path.pathkeys = subpath->pathkeys;
2680 
2681  pathnode->subpath = subpath;
2682 
2683  /*
2684  * We might not need a separate Result node. If the input plan node type
2685  * can project, we can just tell it to project something else. Or, if it
2686  * can't project but the desired target has the same expression list as
2687  * what the input will produce anyway, we can still give it the desired
2688  * tlist (possibly changing its ressortgroupref labels, but nothing else).
2689  * Note: in the latter case, create_projection_plan has to recheck our
2690  * conclusion; see comments therein.
2691  */
2692  oldtarget = subpath->pathtarget;
2694  equal(oldtarget->exprs, target->exprs))
2695  {
2696  /* No separate Result node needed */
2697  pathnode->dummypp = true;
2698 
2699  /*
2700  * Set cost of plan as subpath's cost, adjusted for tlist replacement.
2701  */
2702  pathnode->path.rows = subpath->rows;
2703  pathnode->path.startup_cost = subpath->startup_cost +
2704  (target->cost.startup - oldtarget->cost.startup);
2705  pathnode->path.total_cost = subpath->total_cost +
2706  (target->cost.startup - oldtarget->cost.startup) +
2707  (target->cost.per_tuple - oldtarget->cost.per_tuple) * subpath->rows;
2708  }
2709  else
2710  {
2711  /* We really do need the Result node */
2712  pathnode->dummypp = false;
2713 
2714  /*
2715  * The Result node's cost is cpu_tuple_cost per row, plus the cost of
2716  * evaluating the tlist. There is no qual to worry about.
2717  */
2718  pathnode->path.rows = subpath->rows;
2719  pathnode->path.startup_cost = subpath->startup_cost +
2720  target->cost.startup;
2721  pathnode->path.total_cost = subpath->total_cost +
2722  target->cost.startup +
2723  (cpu_tuple_cost + target->cost.per_tuple) * subpath->rows;
2724  }
2725 
2726  return pathnode;
2727 }
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:223
Path * subpath
Definition: pathnodes.h:2142

References Assert(), RelOptInfo::consider_parallel, PathTarget::cost, cpu_tuple_cost, ProjectionPath::dummypp, equal(), PathTarget::exprs, is_parallel_safe(), is_projection_capable_path(), IsA, makeNode, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, ProjectionPath::path, Path::pathkeys, Path::pathtype, QualCost::per_tuple, Path::rows, QualCost::startup, Path::startup_cost, subpath(), ProjectionPath::subpath, and Path::total_cost.

Referenced by add_paths_with_pathkeys_for_rel(), adjust_paths_for_srfs(), apply_projection_to_path(), apply_scanjoin_target_to_paths(), and recurse_set_operations().

◆ create_recursiveunion_path()

RecursiveUnionPath* create_recursiveunion_path ( PlannerInfo root,
RelOptInfo rel,
Path leftpath,
Path rightpath,
PathTarget target,
List distinctList,
int  wtParam,
double  numGroups 
)

Definition at line 3573 of file pathnode.c.

3581 {
3583 
3584  pathnode->path.pathtype = T_RecursiveUnion;
3585  pathnode->path.parent = rel;
3586  pathnode->path.pathtarget = target;
3587  /* For now, assume we are above any joins, so no parameterization */
3588  pathnode->path.param_info = NULL;
3589  pathnode->path.parallel_aware = false;
3590  pathnode->path.parallel_safe = rel->consider_parallel &&
3591  leftpath->parallel_safe && rightpath->parallel_safe;
3592  /* Foolish, but we'll do it like joins for now: */
3593  pathnode->path.parallel_workers = leftpath->parallel_workers;
3594  /* RecursiveUnion result is always unsorted */
3595  pathnode->path.pathkeys = NIL;
3596 
3597  pathnode->leftpath = leftpath;
3598  pathnode->rightpath = rightpath;
3599  pathnode->distinctList = distinctList;
3600  pathnode->wtParam = wtParam;
3601  pathnode->numGroups = numGroups;
3602 
3603  cost_recursive_union(&pathnode->path, leftpath, rightpath);
3604 
3605  return pathnode;
3606 }
void cost_recursive_union(Path *runion, Path *nrterm, Path *rterm)
Definition: costsize.c:1785
Cardinality numGroups
Definition: pathnodes.h:2319

References RelOptInfo::consider_parallel, cost_recursive_union(), RecursiveUnionPath::distinctList, RecursiveUnionPath::leftpath, makeNode, NIL, RecursiveUnionPath::numGroups, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, RecursiveUnionPath::path, Path::pathkeys, Path::pathtype, RecursiveUnionPath::rightpath, and RecursiveUnionPath::wtParam.

Referenced by generate_recursion_path().

◆ create_resultscan_path()

Path* create_resultscan_path ( PlannerInfo root,
RelOptInfo rel,
Relids  required_outer 
)

Definition at line 2167 of file pathnode.c.

2169 {
2170  Path *pathnode = makeNode(Path);
2171 
2172  pathnode->pathtype = T_Result;
2173  pathnode->parent = rel;
2174  pathnode->pathtarget = rel->reltarget;
2175  pathnode->param_info = get_baserel_parampathinfo(root, rel,
2176  required_outer);
2177  pathnode->parallel_aware = false;
2178  pathnode->parallel_safe = rel->consider_parallel;
2179  pathnode->parallel_workers = 0;
2180  pathnode->pathkeys = NIL; /* result is always unordered */
2181 
2182  cost_resultscan(pathnode, root, rel, pathnode->param_info);
2183 
2184  return pathnode;
2185 }
void cost_resultscan(Path *path, PlannerInfo *root, RelOptInfo *baserel, ParamPathInfo *param_info)
Definition: costsize.c:1748

References RelOptInfo::consider_parallel, cost_resultscan(), get_baserel_parampathinfo(), makeNode, NIL, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, Path::pathkeys, Path::pathtype, and RelOptInfo::reltarget.

Referenced by reparameterize_path(), and set_result_pathlist().

◆ create_samplescan_path()

Path* create_samplescan_path ( PlannerInfo root,
RelOptInfo rel,
Relids  required_outer 
)

Definition at line 954 of file pathnode.c.

955 {
956  Path *pathnode = makeNode(Path);
957 
958  pathnode->pathtype = T_SampleScan;
959  pathnode->parent = rel;
960  pathnode->pathtarget = rel->reltarget;
961  pathnode->param_info = get_baserel_parampathinfo(root, rel,
962  required_outer);
963  pathnode->parallel_aware = false;
964  pathnode->parallel_safe = rel->consider_parallel;
965  pathnode->parallel_workers = 0;
966  pathnode->pathkeys = NIL; /* samplescan has unordered result */
967 
968  cost_samplescan(pathnode, root, rel, pathnode->param_info);
969 
970  return pathnode;
971 }
void cost_samplescan(Path *path, PlannerInfo *root, RelOptInfo *baserel, ParamPathInfo *param_info)
Definition: costsize.c:333

References RelOptInfo::consider_parallel, cost_samplescan(), get_baserel_parampathinfo(), makeNode, NIL, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, Path::pathkeys, Path::pathtype, and RelOptInfo::reltarget.

Referenced by reparameterize_path(), and set_tablesample_rel_pathlist().

◆ create_seqscan_path()

Path* create_seqscan_path ( PlannerInfo root,
RelOptInfo rel,
Relids  required_outer,
int  parallel_workers 
)

Definition at line 929 of file pathnode.c.

931 {
932  Path *pathnode = makeNode(Path);
933 
934  pathnode->pathtype = T_SeqScan;
935  pathnode->parent = rel;
936  pathnode->pathtarget = rel->reltarget;
937  pathnode->param_info = get_baserel_parampathinfo(root, rel,
938  required_outer);
939  pathnode->parallel_aware = (parallel_workers > 0);
940  pathnode->parallel_safe = rel->consider_parallel;
941  pathnode->parallel_workers = parallel_workers;
942  pathnode->pathkeys = NIL; /* seqscan has unordered result */
943 
944  cost_seqscan(pathnode, root, rel, pathnode->param_info);
945 
946  return pathnode;
947 }
void cost_seqscan(Path *path, PlannerInfo *root, RelOptInfo *baserel, ParamPathInfo *param_info)
Definition: costsize.c:256

References RelOptInfo::consider_parallel, cost_seqscan(), get_baserel_parampathinfo(), makeNode, NIL, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, Path::pathkeys, Path::pathtype, and RelOptInfo::reltarget.

Referenced by create_plain_partial_paths(), plan_cluster_use_sort(), reparameterize_path(), and set_plain_rel_pathlist().

◆ create_set_projection_path()

ProjectSetPath* create_set_projection_path ( PlannerInfo root,
RelOptInfo rel,
Path subpath,
PathTarget target 
)

Definition at line 2841 of file pathnode.c.

2845 {
2846  ProjectSetPath *pathnode = makeNode(ProjectSetPath);
2847  double tlist_rows;
2848  ListCell *lc;
2849 
2850  pathnode->path.pathtype = T_ProjectSet;
2851  pathnode->path.parent = rel;
2852  pathnode->path.pathtarget = target;
2853  /* For now, assume we are above any joins, so no parameterization */
2854  pathnode->path.param_info = NULL;
2855  pathnode->path.parallel_aware = false;
2856  pathnode->path.parallel_safe = rel->consider_parallel &&
2857  subpath->parallel_safe &&
2858  is_parallel_safe(root, (Node *) target->exprs);
2859  pathnode->path.parallel_workers = subpath->parallel_workers;
2860  /* Projection does not change the sort order XXX? */
2861  pathnode->path.pathkeys = subpath->pathkeys;
2862 
2863  pathnode->subpath = subpath;
2864 
2865  /*
2866  * Estimate number of rows produced by SRFs for each row of input; if
2867  * there's more than one in this node, use the maximum.
2868  */
2869  tlist_rows = 1;
2870  foreach(lc, target->exprs)
2871  {
2872  Node *node = (Node *) lfirst(lc);
2873  double itemrows;
2874 
2875  itemrows = expression_returns_set_rows(root, node);
2876  if (tlist_rows < itemrows)
2877  tlist_rows = itemrows;
2878  }
2879 
2880  /*
2881  * In addition to the cost of evaluating the tlist, charge cpu_tuple_cost
2882  * per input row, and half of cpu_tuple_cost for each added output row.
2883  * This is slightly bizarre maybe, but it's what 9.6 did; we may revisit
2884  * this estimate later.
2885  */
2886  pathnode->path.rows = subpath->rows * tlist_rows;
2887  pathnode->path.startup_cost = subpath->startup_cost +
2888  target->cost.startup;
2889  pathnode->path.total_cost = subpath->total_cost +
2890  target->cost.startup +
2891  (cpu_tuple_cost + target->cost.per_tuple) * subpath->rows +
2892  (pathnode->path.rows - subpath->rows) * cpu_tuple_cost / 2;
2893 
2894  return pathnode;
2895 }
double expression_returns_set_rows(PlannerInfo *root, Node *clause)
Definition: clauses.c:291
Path * subpath
Definition: pathnodes.h:2154

References RelOptInfo::consider_parallel, PathTarget::cost, cpu_tuple_cost, expression_returns_set_rows(), PathTarget::exprs, is_parallel_safe(), lfirst, makeNode, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, ProjectSetPath::path, Path::pathkeys, Path::pathtype, QualCost::per_tuple, Path::rows, QualCost::startup, Path::startup_cost, subpath(), ProjectSetPath::subpath, and Path::total_cost.

Referenced by adjust_paths_for_srfs().

◆ create_setop_path()

SetOpPath* create_setop_path ( PlannerInfo root,
RelOptInfo rel,
Path subpath,
SetOpCmd  cmd,
SetOpStrategy  strategy,
List distinctList,
AttrNumber  flagColIdx,
int  firstFlag,
double  numGroups,
double  outputRows 
)

Definition at line 3511 of file pathnode.c.

3521 {
3522  SetOpPath *pathnode = makeNode(SetOpPath);
3523 
3524  pathnode->path.pathtype = T_SetOp;
3525  pathnode->path.parent = rel;
3526  /* SetOp doesn't project, so use source path's pathtarget */
3527  pathnode->path.pathtarget = subpath->pathtarget;
3528  /* For now, assume we are above any joins, so no parameterization */
3529  pathnode->path.param_info = NULL;
3530  pathnode->path.parallel_aware = false;
3531  pathnode->path.parallel_safe = rel->consider_parallel &&
3532  subpath->parallel_safe;
3533  pathnode->path.parallel_workers = subpath->parallel_workers;
3534  /* SetOp preserves the input sort order if in sort mode */
3535  pathnode->path.pathkeys =
3536  (strategy == SETOP_SORTED) ? subpath->pathkeys : NIL;
3537 
3538  pathnode->subpath = subpath;
3539  pathnode->cmd = cmd;
3540  pathnode->strategy = strategy;
3541  pathnode->distinctList = distinctList;
3542  pathnode->flagColIdx = flagColIdx;
3543  pathnode->firstFlag = firstFlag;
3544  pathnode->numGroups = numGroups;
3545 
3546  /*
3547  * Charge one cpu_operator_cost per comparison per input tuple. We assume
3548  * all columns get compared at most of the tuples.
3549  */
3550  pathnode->path.startup_cost = subpath->startup_cost;
3551  pathnode->path.total_cost = subpath->total_cost +
3552  cpu_operator_cost * subpath->rows * list_length(distinctList);
3553  pathnode->path.rows = outputRows;
3554 
3555  return pathnode;
3556 }
double cpu_operator_cost
Definition: costsize.c:124
@ SETOP_SORTED
Definition: nodes.h:416
List * distinctList
Definition: pathnodes.h:2303
Cardinality numGroups
Definition: pathnodes.h:2306
int firstFlag
Definition: pathnodes.h:2305
Path * subpath
Definition: pathnodes.h:2300
SetOpCmd cmd
Definition: pathnodes.h:2301
Path path
Definition: pathnodes.h:2299
SetOpStrategy strategy
Definition: pathnodes.h:2302
AttrNumber flagColIdx
Definition: pathnodes.h:2304

References SetOpPath::cmd, RelOptInfo::consider_parallel, cpu_operator_cost, SetOpPath::distinctList, SetOpPath::firstFlag, SetOpPath::flagColIdx, list_length(), makeNode, NIL, SetOpPath::numGroups, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, SetOpPath::path, Path::pathkeys, Path::pathtype, Path::rows, SETOP_SORTED, Path::startup_cost, SetOpPath::strategy, subpath(), SetOpPath::subpath, and Path::total_cost.

Referenced by generate_nonunion_paths().

◆ create_sort_path()

SortPath* create_sort_path ( PlannerInfo root,
RelOptInfo rel,
Path subpath,
List pathkeys,
double  limit_tuples 
)

Definition at line 2959 of file pathnode.c.

2964 {
2965  SortPath *pathnode = makeNode(SortPath);
2966 
2967  pathnode->path.pathtype = T_Sort;
2968  pathnode->path.parent = rel;
2969  /* Sort doesn't project, so use source path's pathtarget */
2970  pathnode->path.pathtarget = subpath->pathtarget;
2971  /* For now, assume we are above any joins, so no parameterization */
2972  pathnode->path.param_info = NULL;
2973  pathnode->path.parallel_aware = false;
2974  pathnode->path.parallel_safe = rel->consider_parallel &&
2975  subpath->parallel_safe;
2976  pathnode->path.parallel_workers = subpath->parallel_workers;
2977  pathnode->path.pathkeys = pathkeys;
2978 
2979  pathnode->subpath = subpath;
2980 
2981  cost_sort(&pathnode->path, root, pathkeys,
2982  subpath->total_cost,
2983  subpath->rows,
2984  subpath->pathtarget->width,
2985  0.0, /* XXX comparison_cost shouldn't be 0? */
2986  work_mem, limit_tuples);
2987 
2988  return pathnode;
2989 }

References RelOptInfo::consider_parallel, cost_sort(), makeNode, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, SortPath::path, Path::pathkeys, Path::pathtype, subpath(), SortPath::subpath, and work_mem.

Referenced by add_paths_to_grouping_rel(), add_paths_with_pathkeys_for_rel(), create_final_distinct_paths(), create_one_window_path(), create_ordered_paths(), create_partial_distinct_paths(), create_partial_grouping_paths(), gather_grouping_paths(), generate_nonunion_paths(), generate_useful_gather_paths(), and make_union_unique().

◆ create_subqueryscan_path()

SubqueryScanPath* create_subqueryscan_path ( PlannerInfo root,
RelOptInfo rel,
Path subpath,
bool  trivial_pathtarget,
List pathkeys,
Relids  required_outer 
)

Definition at line 2008 of file pathnode.c.

2011 {
2013 
2014  pathnode->path.pathtype = T_SubqueryScan;
2015  pathnode->path.parent = rel;
2016  pathnode->path.pathtarget = rel->reltarget;
2017  pathnode->path.param_info = get_baserel_parampathinfo(root, rel,
2018  required_outer);
2019  pathnode->path.parallel_aware = false;
2020  pathnode->path.parallel_safe = rel->consider_parallel &&
2021  subpath->parallel_safe;
2022  pathnode->path.parallel_workers = subpath->parallel_workers;
2023  pathnode->path.pathkeys = pathkeys;
2024  pathnode->subpath = subpath;
2025 
2026  cost_subqueryscan(pathnode, root, rel, pathnode->path.param_info,
2027  trivial_pathtarget);
2028 
2029  return pathnode;
2030 }
void cost_subqueryscan(SubqueryScanPath *path, PlannerInfo *root, RelOptInfo *baserel, ParamPathInfo *param_info, bool trivial_pathtarget)
Definition: costsize.c:1423

References RelOptInfo::consider_parallel, cost_subqueryscan(), get_baserel_parampathinfo(), makeNode, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, SubqueryScanPath::path, Path::pathkeys, Path::pathtype, RelOptInfo::reltarget, subpath(), and SubqueryScanPath::subpath.

Referenced by recurse_set_operations(), reparameterize_path(), and set_subquery_pathlist().

◆ create_tablefuncscan_path()

Path* create_tablefuncscan_path ( PlannerInfo root,
RelOptInfo rel,
Relids  required_outer 
)

Definition at line 2064 of file pathnode.c.

2066 {
2067  Path *pathnode = makeNode(Path);
2068 
2069  pathnode->pathtype = T_TableFuncScan;
2070  pathnode->parent = rel;
2071  pathnode->pathtarget = rel->reltarget;
2072  pathnode->param_info = get_baserel_parampathinfo(root, rel,
2073  required_outer);
2074  pathnode->parallel_aware = false;
2075  pathnode->parallel_safe = rel->consider_parallel;
2076  pathnode->parallel_workers = 0;
2077  pathnode->pathkeys = NIL; /* result is always unordered */
2078 
2079  cost_tablefuncscan(pathnode, root, rel, pathnode->param_info);
2080 
2081  return pathnode;
2082 }
void cost_tablefuncscan(Path *path, PlannerInfo *root, RelOptInfo *baserel, ParamPathInfo *param_info)
Definition: costsize.c:1564

References RelOptInfo::consider_parallel, cost_tablefuncscan(), get_baserel_parampathinfo(), makeNode, NIL, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, Path::pathkeys, Path::pathtype, and RelOptInfo::reltarget.

Referenced by set_tablefunc_pathlist().

◆ create_tidrangescan_path()

TidRangePath* create_tidrangescan_path ( PlannerInfo root,
RelOptInfo rel,
List tidrangequals,
Relids  required_outer 
)

Definition at line 1210 of file pathnode.c.

1212 {
1213  TidRangePath *pathnode = makeNode(TidRangePath);
1214 
1215  pathnode->path.pathtype = T_TidRangeScan;
1216  pathnode->path.parent = rel;
1217  pathnode->path.pathtarget = rel->reltarget;
1218  pathnode->path.param_info = get_baserel_parampathinfo(root, rel,
1219  required_outer);
1220  pathnode->path.parallel_aware = false;
1221  pathnode->path.parallel_safe = rel->consider_parallel;
1222  pathnode->path.parallel_workers = 0;
1223  pathnode->path.pathkeys = NIL; /* always unordered */
1224 
1225  pathnode->tidrangequals = tidrangequals;
1226 
1227  cost_tidrangescan(&pathnode->path, root, rel, tidrangequals,
1228  pathnode->path.param_info);
1229 
1230  return pathnode;
1231 }
void cost_tidrangescan(Path *path, PlannerInfo *root, RelOptInfo *baserel, List *tidrangequals, ParamPathInfo *param_info)
Definition: costsize.c:1329
List * tidrangequals
Definition: pathnodes.h:1804

References RelOptInfo::consider_parallel, cost_tidrangescan(), get_baserel_parampathinfo(), makeNode, NIL, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, TidRangePath::path, Path::pathkeys, Path::pathtype, RelOptInfo::reltarget, and TidRangePath::tidrangequals.

Referenced by create_tidscan_paths().

◆ create_tidscan_path()

TidPath* create_tidscan_path ( PlannerInfo root,
RelOptInfo rel,
List tidquals,
Relids  required_outer 
)

Definition at line 1181 of file pathnode.c.

1183 {
1184  TidPath *pathnode = makeNode(TidPath);
1185 
1186  pathnode->path.pathtype = T_TidScan;
1187  pathnode->path.parent = rel;
1188  pathnode->path.pathtarget = rel->reltarget;
1189  pathnode->path.param_info = get_baserel_parampathinfo(root, rel,
1190  required_outer);
1191  pathnode->path.parallel_aware = false;
1192  pathnode->path.parallel_safe = rel->consider_parallel;
1193  pathnode->path.parallel_workers = 0;
1194  pathnode->path.pathkeys = NIL; /* always unordered */
1195 
1196  pathnode->tidquals = tidquals;
1197 
1198  cost_tidscan(&pathnode->path, root, rel, tidquals,
1199  pathnode->path.param_info);
1200 
1201  return pathnode;
1202 }
void cost_tidscan(Path *path, PlannerInfo *root, RelOptInfo *baserel, List *tidquals, ParamPathInfo *param_info)
Definition: costsize.c:1221
List * tidquals
Definition: pathnodes.h:1792
Path path
Definition: pathnodes.h:1791

References RelOptInfo::consider_parallel, cost_tidscan(), get_baserel_parampathinfo(), makeNode, NIL, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, TidPath::path, Path::pathkeys, Path::pathtype, RelOptInfo::reltarget, and TidPath::tidquals.

Referenced by BuildParameterizedTidPaths(), and create_tidscan_paths().

◆ create_unique_path()

UniquePath* create_unique_path ( PlannerInfo root,
RelOptInfo rel,
Path subpath,
SpecialJoinInfo sjinfo 
)

Definition at line 1652 of file pathnode.c.

1654 {
1655  UniquePath *pathnode;
1656  Path sort_path; /* dummy for result of cost_sort */
1657  Path agg_path; /* dummy for result of cost_agg */
1658  MemoryContext oldcontext;
1659  int numCols;
1660 
1661  /* Caller made a mistake if subpath isn't cheapest_total ... */
1663  Assert(subpath->parent == rel);
1664  /* ... or if SpecialJoinInfo is the wrong one */
1665  Assert(sjinfo->jointype == JOIN_SEMI);
1666  Assert(bms_equal(rel->relids, sjinfo->syn_righthand));
1667 
1668  /* If result already cached, return it */
1669  if (rel->cheapest_unique_path)
1670  return (UniquePath *) rel->cheapest_unique_path;
1671 
1672  /* If it's not possible to unique-ify, return NULL */
1673  if (!(sjinfo->semi_can_btree || sjinfo->semi_can_hash))
1674  return NULL;
1675 
1676  /*
1677  * When called during GEQO join planning, we are in a short-lived memory
1678  * context. We must make sure that the path and any subsidiary data
1679  * structures created for a baserel survive the GEQO cycle, else the
1680  * baserel is trashed for future GEQO cycles. On the other hand, when we
1681  * are creating those for a joinrel during GEQO, we don't want them to
1682  * clutter the main planning context. Upshot is that the best solution is
1683  * to explicitly allocate memory in the same context the given RelOptInfo
1684  * is in.
1685  */
1686  oldcontext = MemoryContextSwitchTo(GetMemoryChunkContext(rel));
1687 
1688  pathnode = makeNode(UniquePath);
1689 
1690  pathnode->path.pathtype = T_Unique;
1691  pathnode->path.parent = rel;
1692  pathnode->path.pathtarget = rel->reltarget;
1693  pathnode->path.param_info = subpath->param_info;
1694  pathnode->path.parallel_aware = false;
1695  pathnode->path.parallel_safe = rel->consider_parallel &&
1696  subpath->parallel_safe;
1697  pathnode->path.parallel_workers = subpath->parallel_workers;
1698 
1699  /*
1700  * Assume the output is unsorted, since we don't necessarily have pathkeys
1701  * to represent it. (This might get overridden below.)
1702  */
1703  pathnode->path.pathkeys = NIL;
1704 
1705  pathnode->subpath = subpath;
1706  pathnode->in_operators = sjinfo->semi_operators;
1707  pathnode->uniq_exprs = sjinfo->semi_rhs_exprs;
1708 
1709  /*
1710  * If the input is a relation and it has a unique index that proves the
1711  * semi_rhs_exprs are unique, then we don't need to do anything. Note
1712  * that relation_has_unique_index_for automatically considers restriction
1713  * clauses for the rel, as well.
1714  */
1715  if (rel->rtekind == RTE_RELATION && sjinfo->semi_can_btree &&
1717  sjinfo->semi_rhs_exprs,
1718  sjinfo->semi_operators))
1719  {
1720  pathnode->umethod = UNIQUE_PATH_NOOP;
1721  pathnode->path.rows = rel->rows;
1722  pathnode->path.startup_cost = subpath->startup_cost;
1723  pathnode->path.total_cost = subpath->total_cost;
1724  pathnode->path.pathkeys = subpath->pathkeys;
1725 
1726  rel->cheapest_unique_path = (Path *) pathnode;
1727 
1728  MemoryContextSwitchTo(oldcontext);
1729 
1730  return pathnode;
1731  }
1732 
1733  /*
1734  * If the input is a subquery whose output must be unique already, then we
1735  * don't need to do anything. The test for uniqueness has to consider
1736  * exactly which columns we are extracting; for example "SELECT DISTINCT
1737  * x,y" doesn't guarantee that x alone is distinct. So we cannot check for
1738  * this optimization unless semi_rhs_exprs consists only of simple Vars
1739  * referencing subquery outputs. (Possibly we could do something with
1740  * expressions in the subquery outputs, too, but for now keep it simple.)
1741  */
1742  if (rel->rtekind == RTE_SUBQUERY)
1743  {
1744  RangeTblEntry *rte = planner_rt_fetch(rel->relid, root);
1745 
1747  {
1748  List *sub_tlist_colnos;
1749 
1750  sub_tlist_colnos = translate_sub_tlist(sjinfo->semi_rhs_exprs,
1751  rel->relid);
1752 
1753  if (sub_tlist_colnos &&
1755  sub_tlist_colnos,
1756  sjinfo->semi_operators))
1757  {
1758  pathnode->umethod = UNIQUE_PATH_NOOP;
1759  pathnode->path.rows = rel->rows;
1760  pathnode->path.startup_cost = subpath->startup_cost;
1761  pathnode->path.total_cost = subpath->total_cost;
1762  pathnode->path.pathkeys = subpath->pathkeys;
1763 
1764  rel->cheapest_unique_path = (Path *) pathnode;
1765 
1766  MemoryContextSwitchTo(oldcontext);
1767 
1768  return pathnode;
1769  }
1770  }
1771  }
1772 
1773  /* Estimate number of output rows */
1774  pathnode->path.rows = estimate_num_groups(root,
1775  sjinfo->semi_rhs_exprs,
1776  rel->rows,
1777  NULL,
1778  NULL);
1779  numCols = list_length(sjinfo->semi_rhs_exprs);
1780 
1781  if (sjinfo->semi_can_btree)
1782  {
1783  /*
1784  * Estimate cost for sort+unique implementation
1785  */
1786  cost_sort(&sort_path, root, NIL,
1787  subpath->total_cost,
1788  rel->rows,
1789  subpath->pathtarget->width,
1790  0.0,
1791  work_mem,
1792  -1.0);
1793 
1794  /*
1795  * Charge one cpu_operator_cost per comparison per input tuple. We
1796  * assume all columns get compared at most of the tuples. (XXX
1797  * probably this is an overestimate.) This should agree with
1798  * create_upper_unique_path.
1799  */
1800  sort_path.total_cost += cpu_operator_cost * rel->rows * numCols;
1801  }
1802 
1803  if (sjinfo->semi_can_hash)
1804  {
1805  /*
1806  * Estimate the overhead per hashtable entry at 64 bytes (same as in
1807  * planner.c).
1808  */
1809  int hashentrysize = subpath->pathtarget->width + 64;
1810 
1811  if (hashentrysize * pathnode->path.rows > get_hash_memory_limit())
1812  {
1813  /*
1814  * We should not try to hash. Hack the SpecialJoinInfo to
1815  * remember this, in case we come through here again.
1816  */
1817  sjinfo->semi_can_hash = false;
1818  }
1819  else
1820  cost_agg(&agg_path, root,
1821  AGG_HASHED, NULL,
1822  numCols, pathnode->path.rows,
1823  NIL,
1824  subpath->startup_cost,
1825  subpath->total_cost,
1826  rel->rows,
1827  subpath->pathtarget->width);
1828  }
1829 
1830  if (sjinfo->semi_can_btree && sjinfo->semi_can_hash)
1831  {
1832  if (agg_path.total_cost < sort_path.total_cost)
1833  pathnode->umethod = UNIQUE_PATH_HASH;
1834  else
1835  pathnode->umethod = UNIQUE_PATH_SORT;
1836  }
1837  else if (sjinfo->semi_can_btree)
1838  pathnode->umethod = UNIQUE_PATH_SORT;
1839  else if (sjinfo->semi_can_hash)
1840  pathnode->umethod = UNIQUE_PATH_HASH;
1841  else
1842  {
1843  /* we can get here only if we abandoned hashing above */
1844  MemoryContextSwitchTo(oldcontext);
1845  return NULL;
1846  }
1847 
1848  if (pathnode->umethod == UNIQUE_PATH_HASH)
1849  {
1850  pathnode->path.startup_cost = agg_path.startup_cost;
1851  pathnode->path.total_cost = agg_path.total_cost;
1852  }
1853  else
1854  {
1855  pathnode->path.startup_cost = sort_path.startup_cost;
1856  pathnode->path.total_cost = sort_path.total_cost;
1857  }
1858 
1859  rel->cheapest_unique_path = (Path *) pathnode;
1860 
1861  MemoryContextSwitchTo(oldcontext);
1862 
1863  return pathnode;
1864 }
bool query_is_distinct_for(Query *query, List *colnos, List *opids)
bool query_supports_distinctness(Query *query)
bool relation_has_unique_index_for(PlannerInfo *root, RelOptInfo *rel, List *restrictlist, List *exprlist, List *oprlist)
Definition: indxpath.c:3494
MemoryContext GetMemoryChunkContext(void *pointer)
Definition: mcxt.c:616
size_t get_hash_memory_limit(void)
Definition: nodeHash.c:3587
@ JOIN_SEMI
Definition: nodes.h:318
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:138
static List * translate_sub_tlist(List *tlist, int relid)
Definition: pathnode.c:1938
@ UNIQUE_PATH_SORT
Definition: pathnodes.h:1990
@ UNIQUE_PATH_NOOP
Definition: pathnodes.h:1988
@ UNIQUE_PATH_HASH
Definition: pathnodes.h:1989
#define planner_rt_fetch(rti, root)
Definition: pathnodes.h:555
double estimate_num_groups(PlannerInfo *root, List *groupExprs, double input_rows, List **pgset, EstimationInfo *estinfo)
Definition: selfuncs.c:3386
Query * subquery
Definition: parsenodes.h:1073
List * semi_rhs_exprs
Definition: pathnodes.h:2868
Relids syn_righthand
Definition: pathnodes.h:2856
List * semi_operators
Definition: pathnodes.h:2867
Path * subpath
Definition: pathnodes.h:1996
List * uniq_exprs
Definition: pathnodes.h:1999
UniquePathMethod umethod
Definition: pathnodes.h:1997
List * in_operators
Definition: pathnodes.h:1998

References AGG_HASHED, Assert(), bms_equal(), RelOptInfo::cheapest_total_path, RelOptInfo::cheapest_unique_path, RelOptInfo::consider_parallel, cost_agg(), cost_sort(), cpu_operator_cost, estimate_num_groups(), get_hash_memory_limit(), GetMemoryChunkContext(), UniquePath::in_operators, JOIN_SEMI, SpecialJoinInfo::jointype, list_length(), makeNode, MemoryContextSwitchTo(), NIL, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, UniquePath::path, Path::pathkeys, Path::pathtype, planner_rt_fetch, query_is_distinct_for(), query_supports_distinctness(), relation_has_unique_index_for(), RelOptInfo::relid, RelOptInfo::relids, RelOptInfo::reltarget, RelOptInfo::rows, Path::rows, RTE_RELATION, RTE_SUBQUERY, RelOptInfo::rtekind, SpecialJoinInfo::semi_can_btree, SpecialJoinInfo::semi_can_hash, SpecialJoinInfo::semi_operators, SpecialJoinInfo::semi_rhs_exprs, Path::startup_cost, subpath(), UniquePath::subpath, RangeTblEntry::subquery, SpecialJoinInfo::syn_righthand, Path::total_cost, translate_sub_tlist(), UniquePath::umethod, UniquePath::uniq_exprs, UNIQUE_PATH_HASH, UNIQUE_PATH_NOOP, UNIQUE_PATH_SORT, and work_mem.

Referenced by consider_parallel_nestloop(), hash_inner_and_outer(), join_is_legal(), match_unsorted_outer(), populate_joinrel_with_paths(), and sort_inner_and_outer().

◆ create_upper_unique_path()

UpperUniquePath* create_upper_unique_path ( PlannerInfo root,
RelOptInfo rel,
Path subpath,
int  numCols,
double  numGroups 
)

Definition at line 3062 of file pathnode.c.

3067 {
3069 
3070  pathnode->path.pathtype = T_Unique;
3071  pathnode->path.parent = rel;
3072  /* Unique doesn't project, so use source path's pathtarget */
3073  pathnode->path.pathtarget = subpath->pathtarget;
3074  /* For now, assume we are above any joins, so no parameterization */
3075  pathnode->path.param_info = NULL;
3076  pathnode->path.parallel_aware = false;
3077  pathnode->path.parallel_safe = rel->consider_parallel &&
3078  subpath->parallel_safe;
3079  pathnode->path.parallel_workers = subpath->parallel_workers;
3080  /* Unique doesn't change the input ordering */
3081  pathnode->path.pathkeys = subpath->pathkeys;
3082 
3083  pathnode->subpath = subpath;
3084  pathnode->numkeys = numCols;
3085 
3086  /*
3087  * Charge one cpu_operator_cost per comparison per input tuple. We assume
3088  * all columns get compared at most of the tuples. (XXX probably this is
3089  * an overestimate.)
3090  */
3091  pathnode->path.startup_cost = subpath->startup_cost;
3092  pathnode->path.total_cost = subpath->total_cost +
3093  cpu_operator_cost * subpath->rows * numCols;
3094  pathnode->path.rows = numGroups;
3095 
3096  return pathnode;
3097 }

References RelOptInfo::consider_parallel, cpu_operator_cost, makeNode, UpperUniquePath::numkeys, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, UpperUniquePath::path, Path::pathkeys, Path::pathtype, Path::rows, Path::startup_cost, subpath(), UpperUniquePath::subpath, and Path::total_cost.

Referenced by create_final_distinct_paths(), create_partial_distinct_paths(), and make_union_unique().

◆ create_valuesscan_path()

Path* create_valuesscan_path ( PlannerInfo root,
RelOptInfo rel,
Relids  required_outer 
)

Definition at line 2090 of file pathnode.c.

2092 {
2093  Path *pathnode = makeNode(Path);
2094 
2095  pathnode->pathtype = T_ValuesScan;
2096  pathnode->parent = rel;
2097  pathnode->pathtarget = rel->reltarget;
2098  pathnode->param_info = get_baserel_parampathinfo(root, rel,
2099  required_outer);
2100  pathnode->parallel_aware = false;
2101  pathnode->parallel_safe = rel->consider_parallel;
2102  pathnode->parallel_workers = 0;
2103  pathnode->pathkeys = NIL; /* result is always unordered */
2104 
2105  cost_valuesscan(pathnode, root, rel, pathnode->param_info);
2106 
2107  return pathnode;
2108 }
void cost_valuesscan(Path *path, PlannerInfo *root, RelOptInfo *baserel, ParamPathInfo *param_info)
Definition: costsize.c:1620

References RelOptInfo::consider_parallel, cost_valuesscan(), get_baserel_parampathinfo(), makeNode, NIL, Path::parallel_aware, Path::parallel_safe, Path::parallel_workers, Path::pathkeys, Path::pathtype, and RelOptInfo::reltarget.

Referenced by set_values_pathlist().

◆ create_windowagg_path()

WindowAggPath* create_windowagg_path ( PlannerInfo root,
RelOptInfo rel,
Path subpath,
PathTarget target,
List windowFuncs,
WindowClause winclause,
List qual,
bool  topwindow 
)

Definition at line 3443 of file pathnode.c.

3451 {
3452  WindowAggPath *pathnode = makeNode(WindowAggPath);
3453 
3454  /* qual can only be set for the topwindow */
3455  Assert(qual == NIL || topwindow);
3456 
3457  pathnode->path.pathtype = T_WindowAgg;
3458  pathnode->path.parent = rel;
3459  pathnode->path.pathtarget = target;
3460  /* For now, assume we are above any joins, so no parameterization */
3461  pathnode->path.param_info = NULL;
3462  pathnode->path.parallel_aware = false;
3463  pathnode->path.parallel_safe = rel->consider_parallel &&
3464  subpath->parallel_safe;
3465  pathnode->path.parallel_workers = subpath->parallel_workers;
3466  /* WindowAgg preserves the input sort order */
3467  pathnode->path.pathkeys = subpath->pathkeys;
3468 
3469  pathnode->subpath =