PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
planner.c File Reference
#include "postgres.h"
#include <limits.h>
#include <math.h>
#include "access/htup_details.h"
#include "access/parallel.h"
#include "access/sysattr.h"
#include "access/xact.h"
#include "catalog/pg_constraint_fn.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "executor/executor.h"
#include "executor/nodeAgg.h"
#include "foreign/fdwapi.h"
#include "miscadmin.h"
#include "lib/bipartite_match.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/cost.h"
#include "optimizer/pathnode.h"
#include "optimizer/paths.h"
#include "optimizer/plancat.h"
#include "optimizer/planmain.h"
#include "optimizer/planner.h"
#include "optimizer/prep.h"
#include "optimizer/subselect.h"
#include "optimizer/tlist.h"
#include "optimizer/var.h"
#include "parser/analyze.h"
#include "parser/parsetree.h"
#include "parser/parse_agg.h"
#include "rewrite/rewriteManip.h"
#include "storage/dsm_impl.h"
#include "utils/rel.h"
#include "utils/selfuncs.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
Include dependency graph for planner.c:

Go to the source code of this file.

Data Structures

struct  standard_qp_extra
 

Macros

#define EXPRKIND_QUAL   0
 
#define EXPRKIND_TARGET   1
 
#define EXPRKIND_RTFUNC   2
 
#define EXPRKIND_RTFUNC_LATERAL   3
 
#define EXPRKIND_VALUES   4
 
#define EXPRKIND_VALUES_LATERAL   5
 
#define EXPRKIND_LIMIT   6
 
#define EXPRKIND_APPINFO   7
 
#define EXPRKIND_PHV   8
 
#define EXPRKIND_TABLESAMPLE   9
 
#define EXPRKIND_ARBITER_ELEM   10
 

Functions

static Nodepreprocess_expression (PlannerInfo *root, Node *expr, int kind)
 
static void preprocess_qual_conditions (PlannerInfo *root, Node *jtnode)
 
static void inheritance_planner (PlannerInfo *root)
 
static void grouping_planner (PlannerInfo *root, bool inheritance_update, double tuple_fraction)
 
static void preprocess_rowmarks (PlannerInfo *root)
 
static double preprocess_limit (PlannerInfo *root, double tuple_fraction, int64 *offset_est, int64 *count_est)
 
static bool limit_needed (Query *parse)
 
static void remove_useless_groupby_columns (PlannerInfo *root)
 
static Listpreprocess_groupclause (PlannerInfo *root, List *force)
 
static Listextract_rollup_sets (List *groupingSets)
 
static Listreorder_grouping_sets (List *groupingSets, List *sortclause)
 
static void standard_qp_callback (PlannerInfo *root, void *extra)
 
static double get_number_of_groups (PlannerInfo *root, double path_rows, List *rollup_lists, List *rollup_groupclauses)
 
static Size estimate_hashagg_tablesize (Path *path, const AggClauseCosts *agg_costs, double dNumGroups)
 
static RelOptInfocreate_grouping_paths (PlannerInfo *root, RelOptInfo *input_rel, PathTarget *target, const AggClauseCosts *agg_costs, List *rollup_lists, List *rollup_groupclauses)
 
static RelOptInfocreate_window_paths (PlannerInfo *root, RelOptInfo *input_rel, PathTarget *input_target, PathTarget *output_target, List *tlist, WindowFuncLists *wflists, List *activeWindows)
 
static void create_one_window_path (PlannerInfo *root, RelOptInfo *window_rel, Path *path, PathTarget *input_target, PathTarget *output_target, List *tlist, WindowFuncLists *wflists, List *activeWindows)
 
static RelOptInfocreate_distinct_paths (PlannerInfo *root, RelOptInfo *input_rel)
 
static RelOptInfocreate_ordered_paths (PlannerInfo *root, RelOptInfo *input_rel, PathTarget *target, double limit_tuples)
 
static PathTargetmake_group_input_target (PlannerInfo *root, PathTarget *final_target)
 
static PathTargetmake_partial_grouping_target (PlannerInfo *root, PathTarget *grouping_target)
 
static Listpostprocess_setop_tlist (List *new_tlist, List *orig_tlist)
 
static Listselect_active_windows (PlannerInfo *root, WindowFuncLists *wflists)
 
static PathTargetmake_window_input_target (PlannerInfo *root, PathTarget *final_target, List *activeWindows)
 
static Listmake_pathkeys_for_window (PlannerInfo *root, WindowClause *wc, List *tlist)
 
static PathTargetmake_sort_input_target (PlannerInfo *root, PathTarget *final_target, bool *have_postponed_srfs)
 
static void adjust_paths_for_srfs (PlannerInfo *root, RelOptInfo *rel, List *targets, List *targets_contain_srfs)
 
PlannedStmtplanner (Query *parse, int cursorOptions, ParamListInfo boundParams)
 
PlannedStmtstandard_planner (Query *parse, int cursorOptions, ParamListInfo boundParams)
 
PlannerInfosubquery_planner (PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root, bool hasRecursion, double tuple_fraction)
 
Exprpreprocess_phv_expression (PlannerInfo *root, Expr *expr)
 
bool is_dummy_plan (Plan *plan)
 
RowMarkType select_rowmark_type (RangeTblEntry *rte, LockClauseStrength strength)
 
void mark_partial_aggref (Aggref *agg, AggSplit aggsplit)
 
Pathget_cheapest_fractional_path (RelOptInfo *rel, double tuple_fraction)
 
Exprexpression_planner (Expr *expr)
 
bool plan_cluster_use_sort (Oid tableOid, Oid indexOid)
 

Variables

double cursor_tuple_fraction = DEFAULT_CURSOR_TUPLE_FRACTION
 
int force_parallel_mode = FORCE_PARALLEL_OFF
 
planner_hook_type planner_hook = NULL
 
create_upper_paths_hook_type create_upper_paths_hook = NULL
 

Macro Definition Documentation

#define EXPRKIND_APPINFO   7

Definition at line 79 of file planner.c.

Referenced by subquery_planner().

#define EXPRKIND_ARBITER_ELEM   10

Definition at line 82 of file planner.c.

Referenced by subquery_planner().

#define EXPRKIND_LIMIT   6

Definition at line 78 of file planner.c.

Referenced by subquery_planner().

#define EXPRKIND_PHV   8

Definition at line 80 of file planner.c.

Referenced by preprocess_phv_expression().

#define EXPRKIND_QUAL   0

Definition at line 72 of file planner.c.

Referenced by preprocess_expression(), preprocess_qual_conditions(), and subquery_planner().

#define EXPRKIND_RTFUNC   2

Definition at line 74 of file planner.c.

Referenced by preprocess_expression(), and subquery_planner().

#define EXPRKIND_RTFUNC_LATERAL   3

Definition at line 75 of file planner.c.

Referenced by subquery_planner().

#define EXPRKIND_TABLESAMPLE   9

Definition at line 81 of file planner.c.

Referenced by preprocess_expression(), and subquery_planner().

#define EXPRKIND_TARGET   1

Definition at line 73 of file planner.c.

Referenced by subquery_planner().

#define EXPRKIND_VALUES   4

Definition at line 76 of file planner.c.

Referenced by preprocess_expression(), and subquery_planner().

#define EXPRKIND_VALUES_LATERAL   5

Definition at line 77 of file planner.c.

Referenced by subquery_planner().

Function Documentation

static void adjust_paths_for_srfs ( PlannerInfo root,
RelOptInfo rel,
List targets,
List targets_contain_srfs 
)
static

Definition at line 5101 of file planner.c.

References apply_projection_to_path(), Assert, RelOptInfo::cheapest_startup_path, RelOptInfo::cheapest_total_path, create_projection_path(), create_set_projection_path(), forboth, lfirst, lfirst_int, linitial_int, list_length(), NULL, Path::param_info, RelOptInfo::partial_pathlist, RelOptInfo::pathlist, and subpath().

Referenced by grouping_planner().

5103 {
5104  ListCell *lc;
5105 
5106  Assert(list_length(targets) == list_length(targets_contain_srfs));
5107  Assert(!linitial_int(targets_contain_srfs));
5108 
5109  /* If no SRFs appear at this plan level, nothing to do */
5110  if (list_length(targets) == 1)
5111  return;
5112 
5113  /*
5114  * Stack SRF-evaluation nodes atop each path for the rel.
5115  *
5116  * In principle we should re-run set_cheapest() here to identify the
5117  * cheapest path, but it seems unlikely that adding the same tlist eval
5118  * costs to all the paths would change that, so we don't bother. Instead,
5119  * just assume that the cheapest-startup and cheapest-total paths remain
5120  * so. (There should be no parameterized paths anymore, so we needn't
5121  * worry about updating cheapest_parameterized_paths.)
5122  */
5123  foreach(lc, rel->pathlist)
5124  {
5125  Path *subpath = (Path *) lfirst(lc);
5126  Path *newpath = subpath;
5127  ListCell *lc1,
5128  *lc2;
5129 
5130  Assert(subpath->param_info == NULL);
5131  forboth(lc1, targets, lc2, targets_contain_srfs)
5132  {
5133  PathTarget *thistarget = (PathTarget *) lfirst(lc1);
5134  bool contains_srfs = (bool) lfirst_int(lc2);
5135 
5136  /* If this level doesn't contain SRFs, do regular projection */
5137  if (contains_srfs)
5138  newpath = (Path *) create_set_projection_path(root,
5139  rel,
5140  newpath,
5141  thistarget);
5142  else
5143  newpath = (Path *) apply_projection_to_path(root,
5144  rel,
5145  newpath,
5146  thistarget);
5147  }
5148  lfirst(lc) = newpath;
5149  if (subpath == rel->cheapest_startup_path)
5150  rel->cheapest_startup_path = newpath;
5151  if (subpath == rel->cheapest_total_path)
5152  rel->cheapest_total_path = newpath;
5153  }
5154 
5155  /* Likewise for partial paths, if any */
5156  foreach(lc, rel->partial_pathlist)
5157  {
5158  Path *subpath = (Path *) lfirst(lc);
5159  Path *newpath = subpath;
5160  ListCell *lc1,
5161  *lc2;
5162 
5163  Assert(subpath->param_info == NULL);
5164  forboth(lc1, targets, lc2, targets_contain_srfs)
5165  {
5166  PathTarget *thistarget = (PathTarget *) lfirst(lc1);
5167  bool contains_srfs = (bool) lfirst_int(lc2);
5168 
5169  /* If this level doesn't contain SRFs, do regular projection */
5170  if (contains_srfs)
5171  newpath = (Path *) create_set_projection_path(root,
5172  rel,
5173  newpath,
5174  thistarget);
5175  else
5176  {
5177  /* avoid apply_projection_to_path, in case of multiple refs */
5178  newpath = (Path *) create_projection_path(root,
5179  rel,
5180  newpath,
5181  thistarget);
5182  }
5183  }
5184  lfirst(lc) = newpath;
5185  }
5186 }
Path * apply_projection_to_path(PlannerInfo *root, RelOptInfo *rel, Path *path, PathTarget *target)
Definition: pathnode.c:2253
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:174
struct Path * cheapest_startup_path
Definition: relation.h:507
ParamPathInfo * param_info
Definition: relation.h:897
ProjectionPath * create_projection_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target)
Definition: pathnode.c:2162
List * partial_pathlist
Definition: relation.h:506
char bool
Definition: c.h:199
#define linitial_int(l)
Definition: pg_list.h:111
#define lfirst_int(lc)
Definition: pg_list.h:107
struct Path * cheapest_total_path
Definition: relation.h:508
ProjectSetPath * create_set_projection_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target)
Definition: pathnode.c:2329
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
List * pathlist
Definition: relation.h:504
Definition: relation.h:888
Datum subpath(PG_FUNCTION_ARGS)
Definition: ltree_op.c:234
static RelOptInfo * create_distinct_paths ( PlannerInfo root,
RelOptInfo input_rel 
)
static

Definition at line 3999 of file planner.c.

References add_path(), AGG_HASHED, AGGSPLIT_SIMPLE, Assert, RelOptInfo::cheapest_total_path, RelOptInfo::consider_parallel, create_agg_path(), create_sort_path(), create_upper_paths_hook, create_upper_unique_path(), PlannerInfo::distinct_pathkeys, Query::distinctClause, enable_hashagg, ereport, errcode(), errdetail(), errmsg(), ERROR, estimate_num_groups(), RelOptInfo::fdwroutine, fetch_upper_rel(), get_sortgrouplist_exprs(), FdwRoutine::GetForeignUpperPaths, Query::groupClause, grouping_is_hashable(), grouping_is_sortable(), Query::groupingSets, Query::hasAggs, Query::hasDistinctOn, hash_agg_entry_size(), PlannerInfo::hasHavingQual, lfirst, list_length(), MAXALIGN, NIL, NULL, parse(), PlannerInfo::parse, Path::pathkeys, pathkeys_contained_in(), RelOptInfo::pathlist, Path::pathtarget, Path::rows, RelOptInfo::serverid, set_cheapest(), SizeofMinimalTupleHeader, PlannerInfo::sort_pathkeys, Query::targetList, UPPERREL_DISTINCT, RelOptInfo::userid, RelOptInfo::useridiscurrent, PathTarget::width, and work_mem.

Referenced by grouping_planner().

4001 {
4002  Query *parse = root->parse;
4003  Path *cheapest_input_path = input_rel->cheapest_total_path;
4004  RelOptInfo *distinct_rel;
4005  double numDistinctRows;
4006  bool allow_hash;
4007  Path *path;
4008  ListCell *lc;
4009 
4010  /* For now, do all work in the (DISTINCT, NULL) upperrel */
4011  distinct_rel = fetch_upper_rel(root, UPPERREL_DISTINCT, NULL);
4012 
4013  /*
4014  * We don't compute anything at this level, so distinct_rel will be
4015  * parallel-safe if the input rel is parallel-safe. In particular, if
4016  * there is a DISTINCT ON (...) clause, any path for the input_rel will
4017  * output those expressions, and will not be parallel-safe unless those
4018  * expressions are parallel-safe.
4019  */
4020  distinct_rel->consider_parallel = input_rel->consider_parallel;
4021 
4022  /*
4023  * If the input rel belongs to a single FDW, so does the distinct_rel.
4024  */
4025  distinct_rel->serverid = input_rel->serverid;
4026  distinct_rel->userid = input_rel->userid;
4027  distinct_rel->useridiscurrent = input_rel->useridiscurrent;
4028  distinct_rel->fdwroutine = input_rel->fdwroutine;
4029 
4030  /* Estimate number of distinct rows there will be */
4031  if (parse->groupClause || parse->groupingSets || parse->hasAggs ||
4032  root->hasHavingQual)
4033  {
4034  /*
4035  * If there was grouping or aggregation, use the number of input rows
4036  * as the estimated number of DISTINCT rows (ie, assume the input is
4037  * already mostly unique).
4038  */
4039  numDistinctRows = cheapest_input_path->rows;
4040  }
4041  else
4042  {
4043  /*
4044  * Otherwise, the UNIQUE filter has effects comparable to GROUP BY.
4045  */
4046  List *distinctExprs;
4047 
4048  distinctExprs = get_sortgrouplist_exprs(parse->distinctClause,
4049  parse->targetList);
4050  numDistinctRows = estimate_num_groups(root, distinctExprs,
4051  cheapest_input_path->rows,
4052  NULL);
4053  }
4054 
4055  /*
4056  * Consider sort-based implementations of DISTINCT, if possible.
4057  */
4059  {
4060  /*
4061  * First, if we have any adequately-presorted paths, just stick a
4062  * Unique node on those. Then consider doing an explicit sort of the
4063  * cheapest input path and Unique'ing that.
4064  *
4065  * When we have DISTINCT ON, we must sort by the more rigorous of
4066  * DISTINCT and ORDER BY, else it won't have the desired behavior.
4067  * Also, if we do have to do an explicit sort, we might as well use
4068  * the more rigorous ordering to avoid a second sort later. (Note
4069  * that the parser will have ensured that one clause is a prefix of
4070  * the other.)
4071  */
4072  List *needed_pathkeys;
4073 
4074  if (parse->hasDistinctOn &&
4076  list_length(root->sort_pathkeys))
4077  needed_pathkeys = root->sort_pathkeys;
4078  else
4079  needed_pathkeys = root->distinct_pathkeys;
4080 
4081  foreach(lc, input_rel->pathlist)
4082  {
4083  Path *path = (Path *) lfirst(lc);
4084 
4085  if (pathkeys_contained_in(needed_pathkeys, path->pathkeys))
4086  {
4087  add_path(distinct_rel, (Path *)
4088  create_upper_unique_path(root, distinct_rel,
4089  path,
4091  numDistinctRows));
4092  }
4093  }
4094 
4095  /* For explicit-sort case, always use the more rigorous clause */
4096  if (list_length(root->distinct_pathkeys) <
4097  list_length(root->sort_pathkeys))
4098  {
4099  needed_pathkeys = root->sort_pathkeys;
4100  /* Assert checks that parser didn't mess up... */
4102  needed_pathkeys));
4103  }
4104  else
4105  needed_pathkeys = root->distinct_pathkeys;
4106 
4107  path = cheapest_input_path;
4108  if (!pathkeys_contained_in(needed_pathkeys, path->pathkeys))
4109  path = (Path *) create_sort_path(root, distinct_rel,
4110  path,
4111  needed_pathkeys,
4112  -1.0);
4113 
4114  add_path(distinct_rel, (Path *)
4115  create_upper_unique_path(root, distinct_rel,
4116  path,
4118  numDistinctRows));
4119  }
4120 
4121  /*
4122  * Consider hash-based implementations of DISTINCT, if possible.
4123  *
4124  * If we were not able to make any other types of path, we *must* hash or
4125  * die trying. If we do have other choices, there are several things that
4126  * should prevent selection of hashing: if the query uses DISTINCT ON
4127  * (because it won't really have the expected behavior if we hash), or if
4128  * enable_hashagg is off, or if it looks like the hashtable will exceed
4129  * work_mem.
4130  *
4131  * Note: grouping_is_hashable() is much more expensive to check than the
4132  * other gating conditions, so we want to do it last.
4133  */
4134  if (distinct_rel->pathlist == NIL)
4135  allow_hash = true; /* we have no alternatives */
4136  else if (parse->hasDistinctOn || !enable_hashagg)
4137  allow_hash = false; /* policy-based decision not to hash */
4138  else
4139  {
4140  Size hashentrysize;
4141 
4142  /* Estimate per-hash-entry space at tuple width... */
4143  hashentrysize = MAXALIGN(cheapest_input_path->pathtarget->width) +
4145  /* plus the per-hash-entry overhead */
4146  hashentrysize += hash_agg_entry_size(0);
4147 
4148  /* Allow hashing only if hashtable is predicted to fit in work_mem */
4149  allow_hash = (hashentrysize * numDistinctRows <= work_mem * 1024L);
4150  }
4151 
4152  if (allow_hash && grouping_is_hashable(parse->distinctClause))
4153  {
4154  /* Generate hashed aggregate path --- no sort needed */
4155  add_path(distinct_rel, (Path *)
4156  create_agg_path(root,
4157  distinct_rel,
4158  cheapest_input_path,
4159  cheapest_input_path->pathtarget,
4160  AGG_HASHED,
4162  parse->distinctClause,
4163  NIL,
4164  NULL,
4165  numDistinctRows));
4166  }
4167 
4168  /* Give a helpful error if we failed to find any implementation */
4169  if (distinct_rel->pathlist == NIL)
4170  ereport(ERROR,
4171  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4172  errmsg("could not implement DISTINCT"),
4173  errdetail("Some of the datatypes only support hashing, while others only support sorting.")));
4174 
4175  /*
4176  * If there is an FDW that's responsible for all baserels of the query,
4177  * let it consider adding ForeignPaths.
4178  */
4179  if (distinct_rel->fdwroutine &&
4180  distinct_rel->fdwroutine->GetForeignUpperPaths)
4181  distinct_rel->fdwroutine->GetForeignUpperPaths(root, UPPERREL_DISTINCT,
4182  input_rel, distinct_rel);
4183 
4184  /* Let extensions possibly add some more paths */
4186  (*create_upper_paths_hook) (root, UPPERREL_DISTINCT,
4187  input_rel, distinct_rel);
4188 
4189  /* Now choose the best path(s) */
4190  set_cheapest(distinct_rel);
4191 
4192  return distinct_rel;
4193 }
GetForeignUpperPaths_function GetForeignUpperPaths
Definition: fdwapi.h:190
#define NIL
Definition: pg_list.h:69
double estimate_num_groups(PlannerInfo *root, List *groupExprs, double input_rows, List **pgset)
Definition: selfuncs.c:3272
PathTarget * pathtarget
Definition: relation.h:895
Query * parse
Definition: relation.h:152
void add_path(RelOptInfo *parent_rel, Path *new_path)
Definition: pathnode.c:412
UpperUniquePath * create_upper_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, int numCols, double numGroups)
Definition: pathnode.c:2498
Oid userid
Definition: relation.h:537
bool hasAggs
Definition: parsenodes.h:116
List * groupingSets
Definition: parsenodes.h:139
int errcode(int sqlerrcode)
Definition: elog.c:575
bool grouping_is_hashable(List *groupClause)
Definition: tlist.c:538
create_upper_paths_hook_type create_upper_paths_hook
Definition: planner.c:68
bool useridiscurrent
Definition: relation.h:538
bool hasDistinctOn
Definition: parsenodes.h:120
List * targetList
Definition: parsenodes.h:131
List * distinctClause
Definition: parsenodes.h:145
#define ERROR
Definition: elog.h:43
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
Definition: relnode.c:870
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: pathnode.c:2550
struct Path * cheapest_total_path
Definition: relation.h:508
struct FdwRoutine * fdwroutine
Definition: relation.h:540
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ereport(elevel, rest)
Definition: elog.h:122
List * sort_pathkeys
Definition: relation.h:262
void set_cheapest(RelOptInfo *parent_rel)
Definition: pathnode.c:234
Oid serverid
Definition: relation.h:536
#define SizeofMinimalTupleHeader
Definition: htup_details.h:650
bool pathkeys_contained_in(List *keys1, List *keys2)
Definition: pathkeys.c:317
int work_mem
Definition: globals.c:112
List * distinct_pathkeys
Definition: relation.h:261
SortPath * create_sort_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, List *pathkeys, double limit_tuples)
Definition: pathnode.c:2396
List * pathkeys
Definition: relation.h:909
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
double rows
Definition: relation.h:905
size_t Size
Definition: c.h:352
static int list_length(const List *l)
Definition: pg_list.h:89
Size hash_agg_entry_size(int numAggs)
Definition: nodeAgg.c:1830
List * get_sortgrouplist_exprs(List *sgClauses, List *targetList)
Definition: tlist.c:395
#define MAXALIGN(LEN)
Definition: c.h:583
bool consider_parallel
Definition: relation.h:498
bool enable_hashagg
Definition: costsize.c:124
int width
Definition: relation.h:827
List * groupClause
Definition: parsenodes.h:137
int errmsg(const char *fmt,...)
Definition: elog.c:797
bool grouping_is_sortable(List *groupClause)
Definition: tlist.c:518
bool hasHavingQual
Definition: relation.h:297
List * pathlist
Definition: relation.h:504
Definition: pg_list.h:45
Definition: relation.h:888
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:651
static RelOptInfo * create_grouping_paths ( PlannerInfo root,
RelOptInfo input_rel,
PathTarget target,
const AggClauseCosts agg_costs,
List rollup_lists,
List rollup_groupclauses 
)
static

Definition at line 3252 of file planner.c.

References add_partial_path(), add_path(), AGG_HASHED, AGG_PLAIN, AGG_SORTED, AGGSPLIT_FINAL_DESERIAL, AGGSPLIT_INITIAL_SERIAL, AGGSPLIT_SIMPLE, Assert, RelOptInfo::cheapest_total_path, RelOptInfo::consider_parallel, create_agg_path(), create_append_path(), create_gather_path(), create_group_path(), create_groupingsets_path(), create_result_path(), create_sort_path(), create_upper_paths_hook, ereport, errcode(), errdetail(), errmsg(), ERROR, estimate_hashagg_tablesize(), PathTarget::exprs, RelOptInfo::fdwroutine, fetch_upper_rel(), get_agg_clause_costs(), get_number_of_groups(), FdwRoutine::GetForeignUpperPaths, PlannerInfo::group_pathkeys, Query::groupClause, grouping_is_hashable(), grouping_is_sortable(), Query::groupingSets, Query::hasAggs, PlannerInfo::hasHavingQual, AggClauseCosts::hasNonPartial, AggClauseCosts::hasNonSerial, Query::havingQual, is_parallel_safe(), lappend(), lfirst, linitial, list_length(), make_partial_grouping_target(), MemSet, NIL, NULL, AggClauseCosts::numOrderedAggs, Path::parallel_workers, parse(), PlannerInfo::parse, RelOptInfo::partial_pathlist, Path::pathkeys, pathkeys_contained_in(), RelOptInfo::pathlist, Path::pathtarget, Path::rows, RelOptInfo::serverid, set_cheapest(), UPPERREL_GROUP_AGG, RelOptInfo::userid, RelOptInfo::useridiscurrent, and work_mem.

Referenced by grouping_planner().

3258 {
3259  Query *parse = root->parse;
3260  Path *cheapest_path = input_rel->cheapest_total_path;
3261  RelOptInfo *grouped_rel;
3262  PathTarget *partial_grouping_target = NULL;
3263  AggClauseCosts agg_partial_costs; /* parallel only */
3264  AggClauseCosts agg_final_costs; /* parallel only */
3265  Size hashaggtablesize;
3266  double dNumGroups;
3267  double dNumPartialGroups = 0;
3268  bool can_hash;
3269  bool can_sort;
3270  bool try_parallel_aggregation;
3271 
3272  ListCell *lc;
3273 
3274  /* For now, do all work in the (GROUP_AGG, NULL) upperrel */
3275  grouped_rel = fetch_upper_rel(root, UPPERREL_GROUP_AGG, NULL);
3276 
3277  /*
3278  * If the input relation is not parallel-safe, then the grouped relation
3279  * can't be parallel-safe, either. Otherwise, it's parallel-safe if the
3280  * target list and HAVING quals are parallel-safe.
3281  */
3282  if (input_rel->consider_parallel &&
3283  is_parallel_safe(root, (Node *) target->exprs) &&
3284  is_parallel_safe(root, (Node *) parse->havingQual))
3285  grouped_rel->consider_parallel = true;
3286 
3287  /*
3288  * If the input rel belongs to a single FDW, so does the grouped rel.
3289  */
3290  grouped_rel->serverid = input_rel->serverid;
3291  grouped_rel->userid = input_rel->userid;
3292  grouped_rel->useridiscurrent = input_rel->useridiscurrent;
3293  grouped_rel->fdwroutine = input_rel->fdwroutine;
3294 
3295  /*
3296  * Check for degenerate grouping.
3297  */
3298  if ((root->hasHavingQual || parse->groupingSets) &&
3299  !parse->hasAggs && parse->groupClause == NIL)
3300  {
3301  /*
3302  * We have a HAVING qual and/or grouping sets, but no aggregates and
3303  * no GROUP BY (which implies that the grouping sets are all empty).
3304  *
3305  * This is a degenerate case in which we are supposed to emit either
3306  * zero or one row for each grouping set depending on whether HAVING
3307  * succeeds. Furthermore, there cannot be any variables in either
3308  * HAVING or the targetlist, so we actually do not need the FROM table
3309  * at all! We can just throw away the plan-so-far and generate a
3310  * Result node. This is a sufficiently unusual corner case that it's
3311  * not worth contorting the structure of this module to avoid having
3312  * to generate the earlier paths in the first place.
3313  */
3314  int nrows = list_length(parse->groupingSets);
3315  Path *path;
3316 
3317  if (nrows > 1)
3318  {
3319  /*
3320  * Doesn't seem worthwhile writing code to cons up a
3321  * generate_series or a values scan to emit multiple rows. Instead
3322  * just make N clones and append them. (With a volatile HAVING
3323  * clause, this means you might get between 0 and N output rows.
3324  * Offhand I think that's desired.)
3325  */
3326  List *paths = NIL;
3327 
3328  while (--nrows >= 0)
3329  {
3330  path = (Path *)
3331  create_result_path(root, grouped_rel,
3332  target,
3333  (List *) parse->havingQual);
3334  paths = lappend(paths, path);
3335  }
3336  path = (Path *)
3337  create_append_path(grouped_rel,
3338  paths,
3339  NULL,
3340  0);
3341  path->pathtarget = target;
3342  }
3343  else
3344  {
3345  /* No grouping sets, or just one, so one output row */
3346  path = (Path *)
3347  create_result_path(root, grouped_rel,
3348  target,
3349  (List *) parse->havingQual);
3350  }
3351 
3352  add_path(grouped_rel, path);
3353 
3354  /* No need to consider any other alternatives. */
3355  set_cheapest(grouped_rel);
3356 
3357  return grouped_rel;
3358  }
3359 
3360  /*
3361  * Estimate number of groups.
3362  */
3363  dNumGroups = get_number_of_groups(root,
3364  cheapest_path->rows,
3365  rollup_lists,
3366  rollup_groupclauses);
3367 
3368  /*
3369  * Determine whether it's possible to perform sort-based implementations
3370  * of grouping. (Note that if groupClause is empty,
3371  * grouping_is_sortable() is trivially true, and all the
3372  * pathkeys_contained_in() tests will succeed too, so that we'll consider
3373  * every surviving input path.)
3374  */
3375  can_sort = grouping_is_sortable(parse->groupClause);
3376 
3377  /*
3378  * Determine whether we should consider hash-based implementations of
3379  * grouping.
3380  *
3381  * Hashed aggregation only applies if we're grouping. We currently can't
3382  * hash if there are grouping sets, though.
3383  *
3384  * Executor doesn't support hashed aggregation with DISTINCT or ORDER BY
3385  * aggregates. (Doing so would imply storing *all* the input values in
3386  * the hash table, and/or running many sorts in parallel, either of which
3387  * seems like a certain loser.) We similarly don't support ordered-set
3388  * aggregates in hashed aggregation, but that case is also included in the
3389  * numOrderedAggs count.
3390  *
3391  * Note: grouping_is_hashable() is much more expensive to check than the
3392  * other gating conditions, so we want to do it last.
3393  */
3394  can_hash = (parse->groupClause != NIL &&
3395  parse->groupingSets == NIL &&
3396  agg_costs->numOrderedAggs == 0 &&
3398 
3399  /*
3400  * If grouped_rel->consider_parallel is true, then paths that we generate
3401  * for this grouping relation could be run inside of a worker, but that
3402  * doesn't mean we can actually use the PartialAggregate/FinalizeAggregate
3403  * execution strategy. Figure that out.
3404  */
3405  if (!grouped_rel->consider_parallel)
3406  {
3407  /* Not even parallel-safe. */
3408  try_parallel_aggregation = false;
3409  }
3410  else if (input_rel->partial_pathlist == NIL)
3411  {
3412  /* Nothing to use as input for partial aggregate. */
3413  try_parallel_aggregation = false;
3414  }
3415  else if (!parse->hasAggs && parse->groupClause == NIL)
3416  {
3417  /*
3418  * We don't know how to do parallel aggregation unless we have either
3419  * some aggregates or a grouping clause.
3420  */
3421  try_parallel_aggregation = false;
3422  }
3423  else if (parse->groupingSets)
3424  {
3425  /* We don't know how to do grouping sets in parallel. */
3426  try_parallel_aggregation = false;
3427  }
3428  else if (agg_costs->hasNonPartial || agg_costs->hasNonSerial)
3429  {
3430  /* Insufficient support for partial mode. */
3431  try_parallel_aggregation = false;
3432  }
3433  else
3434  {
3435  /* Everything looks good. */
3436  try_parallel_aggregation = true;
3437  }
3438 
3439  /*
3440  * Before generating paths for grouped_rel, we first generate any possible
3441  * partial paths; that way, later code can easily consider both parallel
3442  * and non-parallel approaches to grouping. Note that the partial paths
3443  * we generate here are also partially aggregated, so simply pushing a
3444  * Gather node on top is insufficient to create a final path, as would be
3445  * the case for a scan/join rel.
3446  */
3447  if (try_parallel_aggregation)
3448  {
3449  Path *cheapest_partial_path = linitial(input_rel->partial_pathlist);
3450 
3451  /*
3452  * Build target list for partial aggregate paths. These paths cannot
3453  * just emit the same tlist as regular aggregate paths, because (1) we
3454  * must include Vars and Aggrefs needed in HAVING, which might not
3455  * appear in the result tlist, and (2) the Aggrefs must be set in
3456  * partial mode.
3457  */
3458  partial_grouping_target = make_partial_grouping_target(root, target);
3459 
3460  /* Estimate number of partial groups. */
3461  dNumPartialGroups = get_number_of_groups(root,
3462  cheapest_partial_path->rows,
3463  NIL,
3464  NIL);
3465 
3466  /*
3467  * Collect statistics about aggregates for estimating costs of
3468  * performing aggregation in parallel.
3469  */
3470  MemSet(&agg_partial_costs, 0, sizeof(AggClauseCosts));
3471  MemSet(&agg_final_costs, 0, sizeof(AggClauseCosts));
3472  if (parse->hasAggs)
3473  {
3474  /* partial phase */
3475  get_agg_clause_costs(root, (Node *) partial_grouping_target->exprs,
3477  &agg_partial_costs);
3478 
3479  /* final phase */
3480  get_agg_clause_costs(root, (Node *) target->exprs,
3482  &agg_final_costs);
3483  get_agg_clause_costs(root, parse->havingQual,
3485  &agg_final_costs);
3486  }
3487 
3488  if (can_sort)
3489  {
3490  /* This was checked before setting try_parallel_aggregation */
3491  Assert(parse->hasAggs || parse->groupClause);
3492 
3493  /*
3494  * Use any available suitably-sorted path as input, and also
3495  * consider sorting the cheapest partial path.
3496  */
3497  foreach(lc, input_rel->partial_pathlist)
3498  {
3499  Path *path = (Path *) lfirst(lc);
3500  bool is_sorted;
3501 
3502  is_sorted = pathkeys_contained_in(root->group_pathkeys,
3503  path->pathkeys);
3504  if (path == cheapest_partial_path || is_sorted)
3505  {
3506  /* Sort the cheapest partial path, if it isn't already */
3507  if (!is_sorted)
3508  path = (Path *) create_sort_path(root,
3509  grouped_rel,
3510  path,
3511  root->group_pathkeys,
3512  -1.0);
3513 
3514  if (parse->hasAggs)
3515  add_partial_path(grouped_rel, (Path *)
3516  create_agg_path(root,
3517  grouped_rel,
3518  path,
3519  partial_grouping_target,
3520  parse->groupClause ? AGG_SORTED : AGG_PLAIN,
3522  parse->groupClause,
3523  NIL,
3524  &agg_partial_costs,
3525  dNumPartialGroups));
3526  else
3527  add_partial_path(grouped_rel, (Path *)
3528  create_group_path(root,
3529  grouped_rel,
3530  path,
3531  partial_grouping_target,
3532  parse->groupClause,
3533  NIL,
3534  dNumPartialGroups));
3535  }
3536  }
3537  }
3538 
3539  if (can_hash)
3540  {
3541  /* Checked above */
3542  Assert(parse->hasAggs || parse->groupClause);
3543 
3544  hashaggtablesize =
3545  estimate_hashagg_tablesize(cheapest_partial_path,
3546  &agg_partial_costs,
3547  dNumPartialGroups);
3548 
3549  /*
3550  * Tentatively produce a partial HashAgg Path, depending on if it
3551  * looks as if the hash table will fit in work_mem.
3552  */
3553  if (hashaggtablesize < work_mem * 1024L)
3554  {
3555  add_partial_path(grouped_rel, (Path *)
3556  create_agg_path(root,
3557  grouped_rel,
3558  cheapest_partial_path,
3559  partial_grouping_target,
3560  AGG_HASHED,
3562  parse->groupClause,
3563  NIL,
3564  &agg_partial_costs,
3565  dNumPartialGroups));
3566  }
3567  }
3568  }
3569 
3570  /* Build final grouping paths */
3571  if (can_sort)
3572  {
3573  /*
3574  * Use any available suitably-sorted path as input, and also consider
3575  * sorting the cheapest-total path.
3576  */
3577  foreach(lc, input_rel->pathlist)
3578  {
3579  Path *path = (Path *) lfirst(lc);
3580  bool is_sorted;
3581 
3582  is_sorted = pathkeys_contained_in(root->group_pathkeys,
3583  path->pathkeys);
3584  if (path == cheapest_path || is_sorted)
3585  {
3586  /* Sort the cheapest-total path if it isn't already sorted */
3587  if (!is_sorted)
3588  path = (Path *) create_sort_path(root,
3589  grouped_rel,
3590  path,
3591  root->group_pathkeys,
3592  -1.0);
3593 
3594  /* Now decide what to stick atop it */
3595  if (parse->groupingSets)
3596  {
3597  /*
3598  * We have grouping sets, possibly with aggregation. Make
3599  * a GroupingSetsPath.
3600  */
3601  add_path(grouped_rel, (Path *)
3603  grouped_rel,
3604  path,
3605  target,
3606  (List *) parse->havingQual,
3607  rollup_lists,
3608  rollup_groupclauses,
3609  agg_costs,
3610  dNumGroups));
3611  }
3612  else if (parse->hasAggs)
3613  {
3614  /*
3615  * We have aggregation, possibly with plain GROUP BY. Make
3616  * an AggPath.
3617  */
3618  add_path(grouped_rel, (Path *)
3619  create_agg_path(root,
3620  grouped_rel,
3621  path,
3622  target,
3623  parse->groupClause ? AGG_SORTED : AGG_PLAIN,
3625  parse->groupClause,
3626  (List *) parse->havingQual,
3627  agg_costs,
3628  dNumGroups));
3629  }
3630  else if (parse->groupClause)
3631  {
3632  /*
3633  * We have GROUP BY without aggregation or grouping sets.
3634  * Make a GroupPath.
3635  */
3636  add_path(grouped_rel, (Path *)
3637  create_group_path(root,
3638  grouped_rel,
3639  path,
3640  target,
3641  parse->groupClause,
3642  (List *) parse->havingQual,
3643  dNumGroups));
3644  }
3645  else
3646  {
3647  /* Other cases should have been handled above */
3648  Assert(false);
3649  }
3650  }
3651  }
3652 
3653  /*
3654  * Now generate a complete GroupAgg Path atop of the cheapest partial
3655  * path. We need only bother with the cheapest path here, as the
3656  * output of Gather is never sorted.
3657  */
3658  if (grouped_rel->partial_pathlist)
3659  {
3660  Path *path = (Path *) linitial(grouped_rel->partial_pathlist);
3661  double total_groups = path->rows * path->parallel_workers;
3662 
3663  path = (Path *) create_gather_path(root,
3664  grouped_rel,
3665  path,
3666  partial_grouping_target,
3667  NULL,
3668  &total_groups);
3669 
3670  /*
3671  * Since Gather's output is always unsorted, we'll need to sort,
3672  * unless there's no GROUP BY clause or a degenerate (constant)
3673  * one, in which case there will only be a single group.
3674  */
3675  if (root->group_pathkeys)
3676  path = (Path *) create_sort_path(root,
3677  grouped_rel,
3678  path,
3679  root->group_pathkeys,
3680  -1.0);
3681 
3682  if (parse->hasAggs)
3683  add_path(grouped_rel, (Path *)
3684  create_agg_path(root,
3685  grouped_rel,
3686  path,
3687  target,
3688  parse->groupClause ? AGG_SORTED : AGG_PLAIN,
3690  parse->groupClause,
3691  (List *) parse->havingQual,
3692  &agg_final_costs,
3693  dNumGroups));
3694  else
3695  add_path(grouped_rel, (Path *)
3696  create_group_path(root,
3697  grouped_rel,
3698  path,
3699  target,
3700  parse->groupClause,
3701  (List *) parse->havingQual,
3702  dNumGroups));
3703  }
3704  }
3705 
3706  if (can_hash)
3707  {
3708  hashaggtablesize = estimate_hashagg_tablesize(cheapest_path,
3709  agg_costs,
3710  dNumGroups);
3711 
3712  /*
3713  * Provided that the estimated size of the hashtable does not exceed
3714  * work_mem, we'll generate a HashAgg Path, although if we were unable
3715  * to sort above, then we'd better generate a Path, so that we at
3716  * least have one.
3717  */
3718  if (hashaggtablesize < work_mem * 1024L ||
3719  grouped_rel->pathlist == NIL)
3720  {
3721  /*
3722  * We just need an Agg over the cheapest-total input path, since
3723  * input order won't matter.
3724  */
3725  add_path(grouped_rel, (Path *)
3726  create_agg_path(root, grouped_rel,
3727  cheapest_path,
3728  target,
3729  AGG_HASHED,
3731  parse->groupClause,
3732  (List *) parse->havingQual,
3733  agg_costs,
3734  dNumGroups));
3735  }
3736 
3737  /*
3738  * Generate a HashAgg Path atop of the cheapest partial path. Once
3739  * again, we'll only do this if it looks as though the hash table
3740  * won't exceed work_mem.
3741  */
3742  if (grouped_rel->partial_pathlist)
3743  {
3744  Path *path = (Path *) linitial(grouped_rel->partial_pathlist);
3745 
3746  hashaggtablesize = estimate_hashagg_tablesize(path,
3747  &agg_final_costs,
3748  dNumGroups);
3749 
3750  if (hashaggtablesize < work_mem * 1024L)
3751  {
3752  double total_groups = path->rows * path->parallel_workers;
3753 
3754  path = (Path *) create_gather_path(root,
3755  grouped_rel,
3756  path,
3757  partial_grouping_target,
3758  NULL,
3759  &total_groups);
3760 
3761  add_path(grouped_rel, (Path *)
3762  create_agg_path(root,
3763  grouped_rel,
3764  path,
3765  target,
3766  AGG_HASHED,
3768  parse->groupClause,
3769  (List *) parse->havingQual,
3770  &agg_final_costs,
3771  dNumGroups));
3772  }
3773  }
3774  }
3775 
3776  /* Give a helpful error if we failed to find any implementation */
3777  if (grouped_rel->pathlist == NIL)
3778  ereport(ERROR,
3779  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3780  errmsg("could not implement GROUP BY"),
3781  errdetail("Some of the datatypes only support hashing, while others only support sorting.")));
3782 
3783  /*
3784  * If there is an FDW that's responsible for all baserels of the query,
3785  * let it consider adding ForeignPaths.
3786  */
3787  if (grouped_rel->fdwroutine &&
3788  grouped_rel->fdwroutine->GetForeignUpperPaths)
3790  input_rel, grouped_rel);
3791 
3792  /* Let extensions possibly add some more paths */
3794  (*create_upper_paths_hook) (root, UPPERREL_GROUP_AGG,
3795  input_rel, grouped_rel);
3796 
3797  /* Now choose the best path(s) */
3798  set_cheapest(grouped_rel);
3799 
3800  return grouped_rel;
3801 }
GetForeignUpperPaths_function GetForeignUpperPaths
Definition: fdwapi.h:190
List * group_pathkeys
Definition: relation.h:259
#define NIL
Definition: pg_list.h:69
GatherPath * create_gather_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target, Relids required_outer, double *rows)
Definition: pathnode.c:1667
PathTarget * pathtarget
Definition: relation.h:895
Query * parse
Definition: relation.h:152
void add_path(RelOptInfo *parent_rel, Path *new_path)
Definition: pathnode.c:412
AppendPath * create_append_path(RelOptInfo *rel, List *subpaths, Relids required_outer, int parallel_workers)
Definition: pathnode.c:1202
Oid userid
Definition: relation.h:537
void get_agg_clause_costs(PlannerInfo *root, Node *clause, AggSplit aggsplit, AggClauseCosts *costs)
Definition: clauses.c:466
bool hasAggs
Definition: parsenodes.h:116
int parallel_workers
Definition: relation.h:901
List * groupingSets
Definition: parsenodes.h:139
Definition: nodes.h:508
int errcode(int sqlerrcode)
Definition: elog.c:575
List * partial_pathlist
Definition: relation.h:506
#define MemSet(start, val, len)
Definition: c.h:852
bool hasNonSerial
Definition: relation.h:61
bool grouping_is_hashable(List *groupClause)
Definition: tlist.c:538
create_upper_paths_hook_type create_upper_paths_hook
Definition: planner.c:68
bool hasNonPartial
Definition: relation.h:60
bool useridiscurrent
Definition: relation.h:538
static PathTarget * make_partial_grouping_target(PlannerInfo *root, PathTarget *grouping_target)
Definition: planner.c:4406
bool is_parallel_safe(PlannerInfo *root, Node *node)
Definition: clauses.c:1071
#define linitial(l)
Definition: pg_list.h:110
#define ERROR
Definition: elog.h:43
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
Definition: relnode.c:870
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: pathnode.c:2550
struct Path * cheapest_total_path
Definition: relation.h:508
static double get_number_of_groups(PlannerInfo *root, double path_rows, List *rollup_lists, List *rollup_groupclauses)
Definition: planner.c:3134
struct FdwRoutine * fdwroutine
Definition: relation.h:540
int errdetail(const char *fmt,...)
Definition: elog.c:873
GroupPath * create_group_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target, List *groupClause, List *qual, double numGroups)
Definition: pathnode.c:2440
static Size estimate_hashagg_tablesize(Path *path, const AggClauseCosts *agg_costs, double dNumGroups)
Definition: planner.c:3208
#define ereport(elevel, rest)
Definition: elog.h:122
List * lappend(List *list, void *datum)
Definition: list.c:128
int numOrderedAggs
Definition: relation.h:59
void set_cheapest(RelOptInfo *parent_rel)
Definition: pathnode.c:234
Oid serverid
Definition: relation.h:536
List * exprs
Definition: relation.h:824
bool pathkeys_contained_in(List *keys1, List *keys2)
Definition: pathkeys.c:317
GroupingSetsPath * create_groupingsets_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target, List *having_qual, List *rollup_lists, List *rollup_groupclauses, const AggClauseCosts *agg_costs, double numGroups)
Definition: pathnode.c:2616
int work_mem
Definition: globals.c:112
SortPath * create_sort_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, List *pathkeys, double limit_tuples)
Definition: pathnode.c:2396
List * pathkeys
Definition: relation.h:909
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
double rows
Definition: relation.h:905
size_t Size
Definition: c.h:352
static int list_length(const List *l)
Definition: pg_list.h:89
bool consider_parallel
Definition: relation.h:498
List * groupClause
Definition: parsenodes.h:137
int errmsg(const char *fmt,...)
Definition: elog.c:797
void add_partial_path(RelOptInfo *parent_rel, Path *new_path)
Definition: pathnode.c:752
bool grouping_is_sortable(List *groupClause)
Definition: tlist.c:518
bool hasHavingQual
Definition: relation.h:297
ResultPath * create_result_path(PlannerInfo *root, RelOptInfo *rel, PathTarget *target, List *resconstantqual)
Definition: pathnode.c:1346
List * pathlist
Definition: relation.h:504
Node * havingQual
Definition: parsenodes.h:141
Definition: pg_list.h:45
Definition: relation.h:888
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:651
static void create_one_window_path ( PlannerInfo root,
RelOptInfo window_rel,
Path path,
PathTarget input_target,
PathTarget output_target,
List tlist,
WindowFuncLists wflists,
List activeWindows 
)
static

Definition at line 3904 of file planner.c.

References add_column_to_pathtarget(), add_path(), castNode, copy_pathtarget(), create_sort_path(), create_windowagg_path(), get_typavgwidth(), lfirst, lnext, make_pathkeys_for_window(), Path::pathkeys, pathkeys_contained_in(), PathTarget::width, WindowFuncLists::windowFuncs, WindowClause::winref, and WindowFunc::wintype.

Referenced by create_window_paths().

3912 {
3913  PathTarget *window_target;
3914  ListCell *l;
3915 
3916  /*
3917  * Since each window clause could require a different sort order, we stack
3918  * up a WindowAgg node for each clause, with sort steps between them as
3919  * needed. (We assume that select_active_windows chose a good order for
3920  * executing the clauses in.)
3921  *
3922  * input_target should contain all Vars and Aggs needed for the result.
3923  * (In some cases we wouldn't need to propagate all of these all the way
3924  * to the top, since they might only be needed as inputs to WindowFuncs.
3925  * It's probably not worth trying to optimize that though.) It must also
3926  * contain all window partitioning and sorting expressions, to ensure
3927  * they're computed only once at the bottom of the stack (that's critical
3928  * for volatile functions). As we climb up the stack, we'll add outputs
3929  * for the WindowFuncs computed at each level.
3930  */
3931  window_target = input_target;
3932 
3933  foreach(l, activeWindows)
3934  {
3935  WindowClause *wc = (WindowClause *) lfirst(l);
3936  List *window_pathkeys;
3937 
3938  window_pathkeys = make_pathkeys_for_window(root,
3939  wc,
3940  tlist);
3941 
3942  /* Sort if necessary */
3943  if (!pathkeys_contained_in(window_pathkeys, path->pathkeys))
3944  {
3945  path = (Path *) create_sort_path(root, window_rel,
3946  path,
3947  window_pathkeys,
3948  -1.0);
3949  }
3950 
3951  if (lnext(l))
3952  {
3953  /*
3954  * Add the current WindowFuncs to the output target for this
3955  * intermediate WindowAggPath. We must copy window_target to
3956  * avoid changing the previous path's target.
3957  *
3958  * Note: a WindowFunc adds nothing to the target's eval costs; but
3959  * we do need to account for the increase in tlist width.
3960  */
3961  ListCell *lc2;
3962 
3963  window_target = copy_pathtarget(window_target);
3964  foreach(lc2, wflists->windowFuncs[wc->winref])
3965  {
3966  WindowFunc *wfunc = castNode(WindowFunc, lfirst(lc2));
3967 
3968  add_column_to_pathtarget(window_target, (Expr *) wfunc, 0);
3969  window_target->width += get_typavgwidth(wfunc->wintype, -1);
3970  }
3971  }
3972  else
3973  {
3974  /* Install the goal target in the topmost WindowAgg */
3975  window_target = output_target;
3976  }
3977 
3978  path = (Path *)
3979  create_windowagg_path(root, window_rel, path, window_target,
3980  wflists->windowFuncs[wc->winref],
3981  wc,
3982  window_pathkeys);
3983  }
3984 
3985  add_path(window_rel, path);
3986 }
PathTarget * copy_pathtarget(PathTarget *src)
Definition: tlist.c:629
void add_path(RelOptInfo *parent_rel, Path *new_path)
Definition: pathnode.c:412
#define castNode(_type_, nodeptr)
Definition: nodes.h:577
void add_column_to_pathtarget(PathTarget *target, Expr *expr, Index sortgroupref)
Definition: tlist.c:667
static List * make_pathkeys_for_window(PlannerInfo *root, WindowClause *wc, List *tlist)
Definition: planner.c:4792
#define lnext(lc)
Definition: pg_list.h:105
bool pathkeys_contained_in(List *keys1, List *keys2)
Definition: pathkeys.c:317
WindowAggPath * create_windowagg_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target, List *windowFuncs, WindowClause *winclause, List *winpathkeys)
Definition: pathnode.c:2792
int32 get_typavgwidth(Oid typid, int32 typmod)
Definition: lsyscache.c:2296
SortPath * create_sort_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, List *pathkeys, double limit_tuples)
Definition: pathnode.c:2396
List * pathkeys
Definition: relation.h:909
#define lfirst(lc)
Definition: pg_list.h:106
Oid wintype
Definition: primnodes.h:334
int width
Definition: relation.h:827
Definition: pg_list.h:45
List ** windowFuncs
Definition: clauses.h:27
Definition: relation.h:888
static RelOptInfo * create_ordered_paths ( PlannerInfo root,
RelOptInfo input_rel,
PathTarget target,
double  limit_tuples 
)
static

Definition at line 4210 of file planner.c.

References add_path(), apply_projection_to_path(), Assert, RelOptInfo::cheapest_total_path, RelOptInfo::consider_parallel, create_sort_path(), create_upper_paths_hook, PathTarget::exprs, RelOptInfo::fdwroutine, fetch_upper_rel(), FdwRoutine::GetForeignUpperPaths, is_parallel_safe(), lfirst, NIL, NULL, Path::pathkeys, pathkeys_contained_in(), RelOptInfo::pathlist, Path::pathtarget, RelOptInfo::serverid, PlannerInfo::sort_pathkeys, UPPERREL_ORDERED, RelOptInfo::userid, and RelOptInfo::useridiscurrent.

Referenced by grouping_planner().

4214 {
4215  Path *cheapest_input_path = input_rel->cheapest_total_path;
4216  RelOptInfo *ordered_rel;
4217  ListCell *lc;
4218 
4219  /* For now, do all work in the (ORDERED, NULL) upperrel */
4220  ordered_rel = fetch_upper_rel(root, UPPERREL_ORDERED, NULL);
4221 
4222  /*
4223  * If the input relation is not parallel-safe, then the ordered relation
4224  * can't be parallel-safe, either. Otherwise, it's parallel-safe if the
4225  * target list is parallel-safe.
4226  */
4227  if (input_rel->consider_parallel &&
4228  is_parallel_safe(root, (Node *) target->exprs))
4229  ordered_rel->consider_parallel = true;
4230 
4231  /*
4232  * If the input rel belongs to a single FDW, so does the ordered_rel.
4233  */
4234  ordered_rel->serverid = input_rel->serverid;
4235  ordered_rel->userid = input_rel->userid;
4236  ordered_rel->useridiscurrent = input_rel->useridiscurrent;
4237  ordered_rel->fdwroutine = input_rel->fdwroutine;
4238 
4239  foreach(lc, input_rel->pathlist)
4240  {
4241  Path *path = (Path *) lfirst(lc);
4242  bool is_sorted;
4243 
4244  is_sorted = pathkeys_contained_in(root->sort_pathkeys,
4245  path->pathkeys);
4246  if (path == cheapest_input_path || is_sorted)
4247  {
4248  if (!is_sorted)
4249  {
4250  /* An explicit sort here can take advantage of LIMIT */
4251  path = (Path *) create_sort_path(root,
4252  ordered_rel,
4253  path,
4254  root->sort_pathkeys,
4255  limit_tuples);
4256  }
4257 
4258  /* Add projection step if needed */
4259  if (path->pathtarget != target)
4260  path = apply_projection_to_path(root, ordered_rel,
4261  path, target);
4262 
4263  add_path(ordered_rel, path);
4264  }
4265  }
4266 
4267  /*
4268  * If there is an FDW that's responsible for all baserels of the query,
4269  * let it consider adding ForeignPaths.
4270  */
4271  if (ordered_rel->fdwroutine &&
4272  ordered_rel->fdwroutine->GetForeignUpperPaths)
4273  ordered_rel->fdwroutine->GetForeignUpperPaths(root, UPPERREL_ORDERED,
4274  input_rel, ordered_rel);
4275 
4276  /* Let extensions possibly add some more paths */
4278  (*create_upper_paths_hook) (root, UPPERREL_ORDERED,
4279  input_rel, ordered_rel);
4280 
4281  /*
4282  * No need to bother with set_cheapest here; grouping_planner does not
4283  * need us to do it.
4284  */
4285  Assert(ordered_rel->pathlist != NIL);
4286 
4287  return ordered_rel;
4288 }
Path * apply_projection_to_path(PlannerInfo *root, RelOptInfo *rel, Path *path, PathTarget *target)
Definition: pathnode.c:2253
GetForeignUpperPaths_function GetForeignUpperPaths
Definition: fdwapi.h:190
#define NIL
Definition: pg_list.h:69
PathTarget * pathtarget
Definition: relation.h:895
void add_path(RelOptInfo *parent_rel, Path *new_path)
Definition: pathnode.c:412
Oid userid
Definition: relation.h:537
Definition: nodes.h:508
create_upper_paths_hook_type create_upper_paths_hook
Definition: planner.c:68
bool useridiscurrent
Definition: relation.h:538
bool is_parallel_safe(PlannerInfo *root, Node *node)
Definition: clauses.c:1071
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
Definition: relnode.c:870
struct Path * cheapest_total_path
Definition: relation.h:508
struct FdwRoutine * fdwroutine
Definition: relation.h:540
List * sort_pathkeys
Definition: relation.h:262
Oid serverid
Definition: relation.h:536
List * exprs
Definition: relation.h:824
bool pathkeys_contained_in(List *keys1, List *keys2)
Definition: pathkeys.c:317
SortPath * create_sort_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, List *pathkeys, double limit_tuples)
Definition: pathnode.c:2396
List * pathkeys
Definition: relation.h:909
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
bool consider_parallel
Definition: relation.h:498
List * pathlist
Definition: relation.h:504
Definition: relation.h:888
static RelOptInfo * create_window_paths ( PlannerInfo root,
RelOptInfo input_rel,
PathTarget input_target,
PathTarget output_target,
List tlist,
WindowFuncLists wflists,
List activeWindows 
)
static

Definition at line 3818 of file planner.c.

References RelOptInfo::cheapest_total_path, RelOptInfo::consider_parallel, create_one_window_path(), create_upper_paths_hook, PathTarget::exprs, RelOptInfo::fdwroutine, fetch_upper_rel(), FdwRoutine::GetForeignUpperPaths, is_parallel_safe(), lfirst, NULL, Path::pathkeys, pathkeys_contained_in(), RelOptInfo::pathlist, RelOptInfo::serverid, set_cheapest(), UPPERREL_WINDOW, RelOptInfo::userid, RelOptInfo::useridiscurrent, and PlannerInfo::window_pathkeys.

Referenced by grouping_planner().

3825 {
3826  RelOptInfo *window_rel;
3827  ListCell *lc;
3828 
3829  /* For now, do all work in the (WINDOW, NULL) upperrel */
3830  window_rel = fetch_upper_rel(root, UPPERREL_WINDOW, NULL);
3831 
3832  /*
3833  * If the input relation is not parallel-safe, then the window relation
3834  * can't be parallel-safe, either. Otherwise, we need to examine the
3835  * target list and active windows for non-parallel-safe constructs.
3836  */
3837  if (input_rel->consider_parallel &&
3838  is_parallel_safe(root, (Node *) output_target->exprs) &&
3839  is_parallel_safe(root, (Node *) activeWindows))
3840  window_rel->consider_parallel = true;
3841 
3842  /*
3843  * If the input rel belongs to a single FDW, so does the window rel.
3844  */
3845  window_rel->serverid = input_rel->serverid;
3846  window_rel->userid = input_rel->userid;
3847  window_rel->useridiscurrent = input_rel->useridiscurrent;
3848  window_rel->fdwroutine = input_rel->fdwroutine;
3849 
3850  /*
3851  * Consider computing window functions starting from the existing
3852  * cheapest-total path (which will likely require a sort) as well as any
3853  * existing paths that satisfy root->window_pathkeys (which won't).
3854  */
3855  foreach(lc, input_rel->pathlist)
3856  {
3857  Path *path = (Path *) lfirst(lc);
3858 
3859  if (path == input_rel->cheapest_total_path ||
3862  window_rel,
3863  path,
3864  input_target,
3865  output_target,
3866  tlist,
3867  wflists,
3868  activeWindows);
3869  }
3870 
3871  /*
3872  * If there is an FDW that's responsible for all baserels of the query,
3873  * let it consider adding ForeignPaths.
3874  */
3875  if (window_rel->fdwroutine &&
3876  window_rel->fdwroutine->GetForeignUpperPaths)
3877  window_rel->fdwroutine->GetForeignUpperPaths(root, UPPERREL_WINDOW,
3878  input_rel, window_rel);
3879 
3880  /* Let extensions possibly add some more paths */
3882  (*create_upper_paths_hook) (root, UPPERREL_WINDOW,
3883  input_rel, window_rel);
3884 
3885  /* Now choose the best path(s) */
3886  set_cheapest(window_rel);
3887 
3888  return window_rel;
3889 }
GetForeignUpperPaths_function GetForeignUpperPaths
Definition: fdwapi.h:190
Oid userid
Definition: relation.h:537
Definition: nodes.h:508
create_upper_paths_hook_type create_upper_paths_hook
Definition: planner.c:68
bool useridiscurrent
Definition: relation.h:538
bool is_parallel_safe(PlannerInfo *root, Node *node)
Definition: clauses.c:1071
static void create_one_window_path(PlannerInfo *root, RelOptInfo *window_rel, Path *path, PathTarget *input_target, PathTarget *output_target, List *tlist, WindowFuncLists *wflists, List *activeWindows)
Definition: planner.c:3904
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
Definition: relnode.c:870
struct Path * cheapest_total_path
Definition: relation.h:508
struct FdwRoutine * fdwroutine
Definition: relation.h:540
void set_cheapest(RelOptInfo *parent_rel)
Definition: pathnode.c:234
Oid serverid
Definition: relation.h:536
List * exprs
Definition: relation.h:824
List * window_pathkeys
Definition: relation.h:260
bool pathkeys_contained_in(List *keys1, List *keys2)
Definition: pathkeys.c:317
List * pathkeys
Definition: relation.h:909
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
bool consider_parallel
Definition: relation.h:498
List * pathlist
Definition: relation.h:504
Definition: relation.h:888
static Size estimate_hashagg_tablesize ( Path path,
const AggClauseCosts agg_costs,
double  dNumGroups 
)
static

Definition at line 3208 of file planner.c.

References hash_agg_entry_size(), MAXALIGN, AggClauseCosts::numAggs, Path::pathtarget, SizeofMinimalTupleHeader, AggClauseCosts::transitionSpace, and PathTarget::width.

Referenced by create_grouping_paths().

3210 {
3211  Size hashentrysize;
3212 
3213  /* Estimate per-hash-entry space at tuple width... */
3214  hashentrysize = MAXALIGN(path->pathtarget->width) +
3216 
3217  /* plus space for pass-by-ref transition values... */
3218  hashentrysize += agg_costs->transitionSpace;
3219  /* plus the per-hash-entry overhead */
3220  hashentrysize += hash_agg_entry_size(agg_costs->numAggs);
3221 
3222  /*
3223  * Note that this disregards the effect of fill-factor and growth policy
3224  * of the hash-table. That's probably ok, given default the default
3225  * fill-factor is relatively high. It'd be hard to meaningfully factor in
3226  * "double-in-size" growth policies here.
3227  */
3228  return hashentrysize * dNumGroups;
3229 }
PathTarget * pathtarget
Definition: relation.h:895
#define SizeofMinimalTupleHeader
Definition: htup_details.h:650
size_t Size
Definition: c.h:352
Size hash_agg_entry_size(int numAggs)
Definition: nodeAgg.c:1830
#define MAXALIGN(LEN)
Definition: c.h:583
int width
Definition: relation.h:827
Size transitionSpace
Definition: relation.h:64
Expr* expression_planner ( Expr expr)

Definition at line 5211 of file planner.c.

References eval_const_expressions(), fix_opfuncids(), and NULL.

Referenced by ATExecAddColumn(), ATPrepAlterColumnType(), BeginCopyFrom(), CheckMutability(), ComputePartitionAttrs(), ExecPrepareExpr(), get_cast_hashentry(), load_domaintype_info(), slot_fill_defaults(), and transformPartitionBound().

5212 {
5213  Node *result;
5214 
5215  /*
5216  * Convert named-argument function calls, insert default arguments and
5217  * simplify constant subexprs
5218  */
5219  result = eval_const_expressions(NULL, (Node *) expr);
5220 
5221  /* Fill in opfuncid values if missing */
5222  fix_opfuncids(result);
5223 
5224  return (Expr *) result;
5225 }
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1591
Definition: nodes.h:508
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2366
#define NULL
Definition: c.h:226
static List * extract_rollup_sets ( List groupingSets)
static

Definition at line 2784 of file planner.c.

References Assert, BipartiteMatch(), BipartiteMatchFree(), bms_add_member(), bms_equal(), bms_free(), bms_is_subset(), for_each_cell, i, lappend(), lcons(), lfirst, lfirst_int, list_concat(), list_head(), list_length(), list_make1, lnext, NIL, NULL, BipartiteMatchState::pair_uv, BipartiteMatchState::pair_vu, palloc(), palloc0(), and pfree().

Referenced by grouping_planner().

2785 {
2786  int num_sets_raw = list_length(groupingSets);
2787  int num_empty = 0;
2788  int num_sets = 0; /* distinct sets */
2789  int num_chains = 0;
2790  List *result = NIL;
2791  List **results;
2792  List **orig_sets;
2793  Bitmapset **set_masks;
2794  int *chains;
2795  short **adjacency;
2796  short *adjacency_buf;
2798  int i;
2799  int j;
2800  int j_size;
2801  ListCell *lc1 = list_head(groupingSets);
2802  ListCell *lc;
2803 
2804  /*
2805  * Start by stripping out empty sets. The algorithm doesn't require this,
2806  * but the planner currently needs all empty sets to be returned in the
2807  * first list, so we strip them here and add them back after.
2808  */
2809  while (lc1 && lfirst(lc1) == NIL)
2810  {
2811  ++num_empty;
2812  lc1 = lnext(lc1);
2813  }
2814 
2815  /* bail out now if it turns out that all we had were empty sets. */
2816  if (!lc1)
2817  return list_make1(groupingSets);
2818 
2819  /*----------
2820  * We don't strictly need to remove duplicate sets here, but if we don't,
2821  * they tend to become scattered through the result, which is a bit
2822  * confusing (and irritating if we ever decide to optimize them out).
2823  * So we remove them here and add them back after.
2824  *
2825  * For each non-duplicate set, we fill in the following:
2826  *
2827  * orig_sets[i] = list of the original set lists
2828  * set_masks[i] = bitmapset for testing inclusion
2829  * adjacency[i] = array [n, v1, v2, ... vn] of adjacency indices
2830  *
2831  * chains[i] will be the result group this set is assigned to.
2832  *
2833  * We index all of these from 1 rather than 0 because it is convenient
2834  * to leave 0 free for the NIL node in the graph algorithm.
2835  *----------
2836  */
2837  orig_sets = palloc0((num_sets_raw + 1) * sizeof(List *));
2838  set_masks = palloc0((num_sets_raw + 1) * sizeof(Bitmapset *));
2839  adjacency = palloc0((num_sets_raw + 1) * sizeof(short *));
2840  adjacency_buf = palloc((num_sets_raw + 1) * sizeof(short));
2841 
2842  j_size = 0;
2843  j = 0;
2844  i = 1;
2845 
2846  for_each_cell(lc, lc1)
2847  {
2848  List *candidate = lfirst(lc);
2849  Bitmapset *candidate_set = NULL;
2850  ListCell *lc2;
2851  int dup_of = 0;
2852 
2853  foreach(lc2, candidate)
2854  {
2855  candidate_set = bms_add_member(candidate_set, lfirst_int(lc2));
2856  }
2857 
2858  /* we can only be a dup if we're the same length as a previous set */
2859  if (j_size == list_length(candidate))
2860  {
2861  int k;
2862 
2863  for (k = j; k < i; ++k)
2864  {
2865  if (bms_equal(set_masks[k], candidate_set))
2866  {
2867  dup_of = k;
2868  break;
2869  }
2870  }
2871  }
2872  else if (j_size < list_length(candidate))
2873  {
2874  j_size = list_length(candidate);
2875  j = i;
2876  }
2877 
2878  if (dup_of > 0)
2879  {
2880  orig_sets[dup_of] = lappend(orig_sets[dup_of], candidate);
2881  bms_free(candidate_set);
2882  }
2883  else
2884  {
2885  int k;
2886  int n_adj = 0;
2887 
2888  orig_sets[i] = list_make1(candidate);
2889  set_masks[i] = candidate_set;
2890 
2891  /* fill in adjacency list; no need to compare equal-size sets */
2892 
2893  for (k = j - 1; k > 0; --k)
2894  {
2895  if (bms_is_subset(set_masks[k], candidate_set))
2896  adjacency_buf[++n_adj] = k;
2897  }
2898 
2899  if (n_adj > 0)
2900  {
2901  adjacency_buf[0] = n_adj;
2902  adjacency[i] = palloc((n_adj + 1) * sizeof(short));
2903  memcpy(adjacency[i], adjacency_buf, (n_adj + 1) * sizeof(short));
2904  }
2905  else
2906  adjacency[i] = NULL;
2907 
2908  ++i;
2909  }
2910  }
2911 
2912  num_sets = i - 1;
2913 
2914  /*
2915  * Apply the graph matching algorithm to do the work.
2916  */
2917  state = BipartiteMatch(num_sets, num_sets, adjacency);
2918 
2919  /*
2920  * Now, the state->pair* fields have the info we need to assign sets to
2921  * chains. Two sets (u,v) belong to the same chain if pair_uv[u] = v or
2922  * pair_vu[v] = u (both will be true, but we check both so that we can do
2923  * it in one pass)
2924  */
2925  chains = palloc0((num_sets + 1) * sizeof(int));
2926 
2927  for (i = 1; i <= num_sets; ++i)
2928  {
2929  int u = state->pair_vu[i];
2930  int v = state->pair_uv[i];
2931 
2932  if (u > 0 && u < i)
2933  chains[i] = chains[u];
2934  else if (v > 0 && v < i)
2935  chains[i] = chains[v];
2936  else
2937  chains[i] = ++num_chains;
2938  }
2939 
2940  /* build result lists. */
2941  results = palloc0((num_chains + 1) * sizeof(List *));
2942 
2943  for (i = 1; i <= num_sets; ++i)
2944  {
2945  int c = chains[i];
2946 
2947  Assert(c > 0);
2948 
2949  results[c] = list_concat(results[c], orig_sets[i]);
2950  }
2951 
2952  /* push any empty sets back on the first list. */
2953  while (num_empty-- > 0)
2954  results[1] = lcons(NIL, results[1]);
2955 
2956  /* make result list */
2957  for (i = 1; i <= num_chains; ++i)
2958  result = lappend(result, results[i]);
2959 
2960  /*
2961  * Free all the things.
2962  *
2963  * (This is over-fussy for small sets but for large sets we could have
2964  * tied up a nontrivial amount of memory.)
2965  */
2966  BipartiteMatchFree(state);
2967  pfree(results);
2968  pfree(chains);
2969  for (i = 1; i <= num_sets; ++i)
2970  if (adjacency[i])
2971  pfree(adjacency[i]);
2972  pfree(adjacency);
2973  pfree(adjacency_buf);
2974  pfree(orig_sets);
2975  for (i = 1; i <= num_sets; ++i)
2976  bms_free(set_masks[i]);
2977  pfree(set_masks);
2978 
2979  return result;
2980 }
#define NIL
Definition: pg_list.h:69
List * list_concat(List *list1, List *list2)
Definition: list.c:321
void BipartiteMatchFree(BipartiteMatchState *state)
#define list_make1(x1)
Definition: pg_list.h:133
void pfree(void *pointer)
Definition: mcxt.c:992
#define lfirst_int(lc)
Definition: pg_list.h:107
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:307
char * c
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define lnext(lc)
Definition: pg_list.h:105
List * lappend(List *list, void *datum)
Definition: list.c:128
void * palloc0(Size size)
Definition: mcxt.c:920
BipartiteMatchState * BipartiteMatch(int u_size, int v_size, short **adjacency)
List * lcons(void *datum, List *list)
Definition: list.c:259
void bms_free(Bitmapset *a)
Definition: bitmapset.c:200
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
Definition: regguts.h:298
static int list_length(const List *l)
Definition: pg_list.h:89
#define for_each_cell(cell, initcell)
Definition: pg_list.h:163
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:668
void * palloc(Size size)
Definition: mcxt.c:891
int i
Definition: pg_list.h:45
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:130
Path* get_cheapest_fractional_path ( RelOptInfo rel,
double  tuple_fraction 
)

Definition at line 5058 of file planner.c.

References RelOptInfo::cheapest_total_path, compare_fractional_path_costs(), lfirst, RelOptInfo::pathlist, and Path::rows.

Referenced by make_subplan(), recurse_set_operations(), and standard_planner().

5059 {
5060  Path *best_path = rel->cheapest_total_path;
5061  ListCell *l;
5062 
5063  /* If all tuples will be retrieved, just return the cheapest-total path */
5064  if (tuple_fraction <= 0.0)
5065  return best_path;
5066 
5067  /* Convert absolute # of tuples to a fraction; no need to clamp to 0..1 */
5068  if (tuple_fraction >= 1.0 && best_path->rows > 0)
5069  tuple_fraction /= best_path->rows;
5070 
5071  foreach(l, rel->pathlist)
5072  {
5073  Path *path = (Path *) lfirst(l);
5074 
5075  if (path == rel->cheapest_total_path ||
5076  compare_fractional_path_costs(best_path, path, tuple_fraction) <= 0)
5077  continue;
5078 
5079  best_path = path;
5080  }
5081 
5082  return best_path;
5083 }
struct Path * cheapest_total_path
Definition: relation.h:508
#define lfirst(lc)
Definition: pg_list.h:106
double rows
Definition: relation.h:905
int compare_fractional_path_costs(Path *path1, Path *path2, double fraction)
Definition: pathnode.c:107
List * pathlist
Definition: relation.h:504
Definition: relation.h:888
static double get_number_of_groups ( PlannerInfo root,
double  path_rows,
List rollup_lists,
List rollup_groupclauses 
)
static

Definition at line 3134 of file planner.c.

References estimate_num_groups(), forboth, get_sortgrouplist_exprs(), Query::groupClause, Query::groupingSets, Query::hasAggs, PlannerInfo::hasHavingQual, lfirst, list_length(), NULL, parse(), PlannerInfo::parse, and Query::targetList.

Referenced by create_grouping_paths().

3138 {
3139  Query *parse = root->parse;
3140  double dNumGroups;
3141 
3142  if (parse->groupClause)
3143  {
3144  List *groupExprs;
3145 
3146  if (parse->groupingSets)
3147  {
3148  /* Add up the estimates for each grouping set */
3149  ListCell *lc,
3150  *lc2;
3151 
3152  dNumGroups = 0;
3153  forboth(lc, rollup_groupclauses, lc2, rollup_lists)
3154  {
3155  List *groupClause = (List *) lfirst(lc);
3156  List *gsets = (List *) lfirst(lc2);
3157  ListCell *lc3;
3158 
3159  groupExprs = get_sortgrouplist_exprs(groupClause,
3160  parse->targetList);
3161 
3162  foreach(lc3, gsets)
3163  {
3164  List *gset = (List *) lfirst(lc3);
3165 
3166  dNumGroups += estimate_num_groups(root,
3167  groupExprs,
3168  path_rows,
3169  &gset);
3170  }
3171  }
3172  }
3173  else
3174  {
3175  /* Plain GROUP BY */
3176  groupExprs = get_sortgrouplist_exprs(parse->groupClause,
3177  parse->targetList);
3178 
3179  dNumGroups = estimate_num_groups(root, groupExprs, path_rows,
3180  NULL);
3181  }
3182  }
3183  else if (parse->groupingSets)
3184  {
3185  /* Empty grouping sets ... one result row for each one */
3186  dNumGroups = list_length(parse->groupingSets);
3187  }
3188  else if (parse->hasAggs || root->hasHavingQual)
3189  {
3190  /* Plain aggregation, one result row */
3191  dNumGroups = 1;
3192  }
3193  else
3194  {
3195  /* Not grouping */
3196  dNumGroups = 1;
3197  }
3198 
3199  return dNumGroups;
3200 }
double estimate_num_groups(PlannerInfo *root, List *groupExprs, double input_rows, List **pgset)
Definition: selfuncs.c:3272
Query * parse
Definition: relation.h:152
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:174
bool hasAggs
Definition: parsenodes.h:116
List * groupingSets
Definition: parsenodes.h:139
List * targetList
Definition: parsenodes.h:131
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
List * get_sortgrouplist_exprs(List *sgClauses, List *targetList)
Definition: tlist.c:395
List * groupClause
Definition: parsenodes.h:137
bool hasHavingQual
Definition: relation.h:297
Definition: pg_list.h:45
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:651
static void grouping_planner ( PlannerInfo root,
bool  inheritance_update,
double  tuple_fraction 
)
static

Definition at line 1382 of file planner.c.

References standard_qp_extra::activeWindows, add_path(), adjust_paths_for_srfs(), AGGSPLIT_SIMPLE, apply_projection_to_path(), Assert, Query::canSetTag, RelOptInfo::cheapest_startup_path, RelOptInfo::cheapest_total_path, CMD_SELECT, Query::commandType, RelOptInfo::consider_parallel, copyObject(), create_distinct_paths(), create_grouping_paths(), create_limit_path(), create_lockrows_path(), create_modifytable_path(), create_ordered_paths(), create_pathtarget, create_projection_path(), create_upper_paths_hook, create_window_paths(), Query::distinctClause, ereport, errcode(), errmsg(), ERROR, expand_grouping_sets(), PathTarget::exprs, extract_rollup_sets(), RelOptInfo::fdwroutine, fetch_upper_rel(), find_window_functions(), get_agg_clause_costs(), FdwRoutine::GetForeignUpperPaths, standard_qp_extra::groupClause, Query::groupClause, Query::groupingSets, Query::hasAggs, PlannerInfo::hasHavingQual, PlannerInfo::hasRecursion, Query::hasTargetSRFs, Query::hasWindowFuncs, Query::havingQual, is_parallel_safe(), lcons(), LCS_asString(), lfirst, lfirst_int, limit_needed(), PlannerInfo::limit_tuples, Query::limitCount, Query::limitOffset, linitial, linitial_int, list_length(), list_make1, list_make1_int, llast, make_group_input_target(), make_pathkeys_for_sortclauses(), make_sort_input_target(), make_window_input_target(), MemSet, NIL, NULL, WindowFuncLists::numWindowFuncs, Query::onConflict, OnConflictExpr::onConflictSet, palloc(), Path::param_info, parse(), PlannerInfo::parse, RelOptInfo::partial_pathlist, RelOptInfo::pathlist, Path::pathtarget, plan_set_operations(), postprocess_setop_tlist(), preprocess_groupclause(), preprocess_limit(), preprocess_minmax_aggregates(), preprocess_onconflict_targetlist(), preprocess_targetlist(), PlannerInfo::processed_tlist, query_planner(), reorder_grouping_sets(), Query::resultRelation, Query::returningList, Query::rowMarks, PlannerInfo::rowMarks, Query::rtable, select_active_windows(), RelOptInfo::serverid, Query::setOperations, PlannerInfo::sort_pathkeys, Query::sortClause, split_pathtarget_at_srfs(), SS_assign_special_param(), standard_qp_callback(), subpath(), Query::targetList, SortGroupClause::tleSortGroupRef, standard_qp_extra::tlist, PlannerInfo::tuple_fraction, PlannerInfo::upper_targets, UPPERREL_FINAL, UPPERREL_GROUP_AGG, UPPERREL_WINDOW, RelOptInfo::userid, RelOptInfo::useridiscurrent, Query::windowClause, and Query::withCheckOptions.

Referenced by inheritance_planner(), and subquery_planner().

1384 {
1385  Query *parse = root->parse;
1386  List *tlist = parse->targetList;
1387  int64 offset_est = 0;
1388  int64 count_est = 0;
1389  double limit_tuples = -1.0;
1390  bool have_postponed_srfs = false;
1391  PathTarget *final_target;
1392  List *final_targets;
1393  List *final_targets_contain_srfs;
1394  RelOptInfo *current_rel;
1395  RelOptInfo *final_rel;
1396  ListCell *lc;
1397 
1398  /* Tweak caller-supplied tuple_fraction if have LIMIT/OFFSET */
1399  if (parse->limitCount || parse->limitOffset)
1400  {
1401  tuple_fraction = preprocess_limit(root, tuple_fraction,
1402  &offset_est, &count_est);
1403 
1404  /*
1405  * If we have a known LIMIT, and don't have an unknown OFFSET, we can
1406  * estimate the effects of using a bounded sort.
1407  */
1408  if (count_est > 0 && offset_est >= 0)
1409  limit_tuples = (double) count_est + (double) offset_est;
1410  }
1411 
1412  /* Make tuple_fraction accessible to lower-level routines */
1413  root->tuple_fraction = tuple_fraction;
1414 
1415  if (parse->setOperations)
1416  {
1417  /*
1418  * If there's a top-level ORDER BY, assume we have to fetch all the
1419  * tuples. This might be too simplistic given all the hackery below
1420  * to possibly avoid the sort; but the odds of accurate estimates here
1421  * are pretty low anyway. XXX try to get rid of this in favor of
1422  * letting plan_set_operations generate both fast-start and
1423  * cheapest-total paths.
1424  */
1425  if (parse->sortClause)
1426  root->tuple_fraction = 0.0;
1427 
1428  /*
1429  * Construct Paths for set operations. The results will not need any
1430  * work except perhaps a top-level sort and/or LIMIT. Note that any
1431  * special work for recursive unions is the responsibility of
1432  * plan_set_operations.
1433  */
1434  current_rel = plan_set_operations(root);
1435 
1436  /*
1437  * We should not need to call preprocess_targetlist, since we must be
1438  * in a SELECT query node. Instead, use the targetlist returned by
1439  * plan_set_operations (since this tells whether it returned any
1440  * resjunk columns!), and transfer any sort key information from the
1441  * original tlist.
1442  */
1443  Assert(parse->commandType == CMD_SELECT);
1444 
1445  tlist = root->processed_tlist; /* from plan_set_operations */
1446 
1447  /* for safety, copy processed_tlist instead of modifying in-place */
1448  tlist = postprocess_setop_tlist(copyObject(tlist), parse->targetList);
1449 
1450  /* Save aside the final decorated tlist */
1451  root->processed_tlist = tlist;
1452 
1453  /* Also extract the PathTarget form of the setop result tlist */
1454  final_target = current_rel->cheapest_total_path->pathtarget;
1455 
1456  /* The setop result tlist couldn't contain any SRFs */
1457  Assert(!parse->hasTargetSRFs);
1458  final_targets = final_targets_contain_srfs = NIL;
1459 
1460  /*
1461  * Can't handle FOR [KEY] UPDATE/SHARE here (parser should have
1462  * checked already, but let's make sure).
1463  */
1464  if (parse->rowMarks)
1465  ereport(ERROR,
1466  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1467  /*------
1468  translator: %s is a SQL row locking clause such as FOR UPDATE */
1469  errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
1471  linitial(parse->rowMarks))->strength))));
1472 
1473  /*
1474  * Calculate pathkeys that represent result ordering requirements
1475  */
1476  Assert(parse->distinctClause == NIL);
1478  parse->sortClause,
1479  tlist);
1480  }
1481  else
1482  {
1483  /* No set operations, do regular planning */
1484  PathTarget *sort_input_target;
1485  List *sort_input_targets;
1486  List *sort_input_targets_contain_srfs;
1487  PathTarget *grouping_target;
1488  List *grouping_targets;
1489  List *grouping_targets_contain_srfs;
1490  PathTarget *scanjoin_target;
1491  List *scanjoin_targets;
1492  List *scanjoin_targets_contain_srfs;
1493  bool have_grouping;
1494  AggClauseCosts agg_costs;
1495  WindowFuncLists *wflists = NULL;
1496  List *activeWindows = NIL;
1497  List *rollup_lists = NIL;
1498  List *rollup_groupclauses = NIL;
1499  standard_qp_extra qp_extra;
1500 
1501  /* A recursive query should always have setOperations */
1502  Assert(!root->hasRecursion);
1503 
1504  /* Preprocess grouping sets and GROUP BY clause, if any */
1505  if (parse->groupingSets)
1506  {
1507  int *tleref_to_colnum_map;
1508  List *sets;
1509  int maxref;
1510  ListCell *lc;
1511  ListCell *lc2;
1512  ListCell *lc_set;
1513 
1514  parse->groupingSets = expand_grouping_sets(parse->groupingSets, -1);
1515 
1516  /* Identify max SortGroupRef in groupClause, for array sizing */
1517  maxref = 0;
1518  foreach(lc, parse->groupClause)
1519  {
1520  SortGroupClause *gc = lfirst(lc);
1521 
1522  if (gc->tleSortGroupRef > maxref)
1523  maxref = gc->tleSortGroupRef;
1524  }
1525 
1526  /* Allocate workspace array for remapping */
1527  tleref_to_colnum_map = (int *) palloc((maxref + 1) * sizeof(int));
1528 
1529  /* Examine the rollup sets */
1530  sets = extract_rollup_sets(parse->groupingSets);
1531 
1532  foreach(lc_set, sets)
1533  {
1534  List *current_sets = (List *) lfirst(lc_set);
1535  List *groupclause;
1536  int ref;
1537 
1538  /*
1539  * Reorder the current list of grouping sets into correct
1540  * prefix order. If only one aggregation pass is needed, try
1541  * to make the list match the ORDER BY clause; if more than
1542  * one pass is needed, we don't bother with that.
1543  */
1544  current_sets = reorder_grouping_sets(current_sets,
1545  (list_length(sets) == 1
1546  ? parse->sortClause
1547  : NIL));
1548 
1549  /*
1550  * Order the groupClause appropriately. If the first grouping
1551  * set is empty, this can match regular GROUP BY
1552  * preprocessing, otherwise we have to force the groupClause
1553  * to match that grouping set's order.
1554  */
1555  groupclause = preprocess_groupclause(root,
1556  linitial(current_sets));
1557 
1558  /*
1559  * Now that we've pinned down an order for the groupClause for
1560  * this list of grouping sets, we need to remap the entries in
1561  * the grouping sets from sortgrouprefs to plain indices
1562  * (0-based) into the groupClause for this collection of
1563  * grouping sets.
1564  */
1565  ref = 0;
1566  foreach(lc, groupclause)
1567  {
1568  SortGroupClause *gc = lfirst(lc);
1569 
1570  tleref_to_colnum_map[gc->tleSortGroupRef] = ref++;
1571  }
1572 
1573  foreach(lc, current_sets)
1574  {
1575  foreach(lc2, (List *) lfirst(lc))
1576  {
1577  lfirst_int(lc2) = tleref_to_colnum_map[lfirst_int(lc2)];
1578  }
1579  }
1580 
1581  /* Save the reordered sets and corresponding groupclauses */
1582  rollup_lists = lcons(current_sets, rollup_lists);
1583  rollup_groupclauses = lcons(groupclause, rollup_groupclauses);
1584  }
1585  }
1586  else
1587  {
1588  /* Preprocess regular GROUP BY clause, if any */
1589  if (parse->groupClause)
1590  parse->groupClause = preprocess_groupclause(root, NIL);
1591  }
1592 
1593  /* Preprocess targetlist */
1594  tlist = preprocess_targetlist(root, tlist);
1595 
1596  if (parse->onConflict)
1597  parse->onConflict->onConflictSet =
1599  parse->resultRelation,
1600  parse->rtable);
1601 
1602  /*
1603  * We are now done hacking up the query's targetlist. Most of the
1604  * remaining planning work will be done with the PathTarget
1605  * representation of tlists, but save aside the full representation so
1606  * that we can transfer its decoration (resnames etc) to the topmost
1607  * tlist of the finished Plan.
1608  */
1609  root->processed_tlist = tlist;
1610 
1611  /*
1612  * Collect statistics about aggregates for estimating costs, and mark
1613  * all the aggregates with resolved aggtranstypes. We must do this
1614  * before slicing and dicing the tlist into various pathtargets, else
1615  * some copies of the Aggref nodes might escape being marked with the
1616  * correct transtypes.
1617  *
1618  * Note: currently, we do not detect duplicate aggregates here. This
1619  * may result in somewhat-overestimated cost, which is fine for our
1620  * purposes since all Paths will get charged the same. But at some
1621  * point we might wish to do that detection in the planner, rather
1622  * than during executor startup.
1623  */
1624  MemSet(&agg_costs, 0, sizeof(AggClauseCosts));
1625  if (parse->hasAggs)
1626  {
1627  get_agg_clause_costs(root, (Node *) tlist, AGGSPLIT_SIMPLE,
1628  &agg_costs);
1630  &agg_costs);
1631  }
1632 
1633  /*
1634  * Locate any window functions in the tlist. (We don't need to look
1635  * anywhere else, since expressions used in ORDER BY will be in there
1636  * too.) Note that they could all have been eliminated by constant
1637  * folding, in which case we don't need to do any more work.
1638  */
1639  if (parse->hasWindowFuncs)
1640  {
1641  wflists = find_window_functions((Node *) tlist,
1642  list_length(parse->windowClause));
1643  if (wflists->numWindowFuncs > 0)
1644  activeWindows = select_active_windows(root, wflists);
1645  else
1646  parse->hasWindowFuncs = false;
1647  }
1648 
1649  /*
1650  * Preprocess MIN/MAX aggregates, if any. Note: be careful about
1651  * adding logic between here and the query_planner() call. Anything
1652  * that is needed in MIN/MAX-optimizable cases will have to be
1653  * duplicated in planagg.c.
1654  */
1655  if (parse->hasAggs)
1656  preprocess_minmax_aggregates(root, tlist);
1657 
1658  /*
1659  * Figure out whether there's a hard limit on the number of rows that
1660  * query_planner's result subplan needs to return. Even if we know a
1661  * hard limit overall, it doesn't apply if the query has any
1662  * grouping/aggregation operations, or SRFs in the tlist.
1663  */
1664  if (parse->groupClause ||
1665  parse->groupingSets ||
1666  parse->distinctClause ||
1667  parse->hasAggs ||
1668  parse->hasWindowFuncs ||
1669  parse->hasTargetSRFs ||
1670  root->hasHavingQual)
1671  root->limit_tuples = -1.0;
1672  else
1673  root->limit_tuples = limit_tuples;
1674 
1675  /* Set up data needed by standard_qp_callback */
1676  qp_extra.tlist = tlist;
1677  qp_extra.activeWindows = activeWindows;
1678  qp_extra.groupClause =
1679  parse->groupingSets ? llast(rollup_groupclauses) : parse->groupClause;
1680 
1681  /*
1682  * Generate the best unsorted and presorted paths for the scan/join
1683  * portion of this Query, ie the processing represented by the
1684  * FROM/WHERE clauses. (Note there may not be any presorted paths.)
1685  * We also generate (in standard_qp_callback) pathkey representations
1686  * of the query's sort clause, distinct clause, etc.
1687  */
1688  current_rel = query_planner(root, tlist,
1689  standard_qp_callback, &qp_extra);
1690 
1691  /*
1692  * Convert the query's result tlist into PathTarget format.
1693  *
1694  * Note: it's desirable to not do this till after query_planner(),
1695  * because the target width estimates can use per-Var width numbers
1696  * that were obtained within query_planner().
1697  */
1698  final_target = create_pathtarget(root, tlist);
1699 
1700  /*
1701  * If ORDER BY was given, consider whether we should use a post-sort
1702  * projection, and compute the adjusted target for preceding steps if
1703  * so.
1704  */
1705  if (parse->sortClause)
1706  sort_input_target = make_sort_input_target(root,
1707  final_target,
1708  &have_postponed_srfs);
1709  else
1710  sort_input_target = final_target;
1711 
1712  /*
1713  * If we have window functions to deal with, the output from any
1714  * grouping step needs to be what the window functions want;
1715  * otherwise, it should be sort_input_target.
1716  */
1717  if (activeWindows)
1718  grouping_target = make_window_input_target(root,
1719  final_target,
1720  activeWindows);
1721  else
1722  grouping_target = sort_input_target;
1723 
1724  /*
1725  * If we have grouping or aggregation to do, the topmost scan/join
1726  * plan node must emit what the grouping step wants; otherwise, it
1727  * should emit grouping_target.
1728  */
1729  have_grouping = (parse->groupClause || parse->groupingSets ||
1730  parse->hasAggs || root->hasHavingQual);
1731  if (have_grouping)
1732  scanjoin_target = make_group_input_target(root, final_target);
1733  else
1734  scanjoin_target = grouping_target;
1735 
1736  /*
1737  * If there are any SRFs in the targetlist, we must separate each of
1738  * these PathTargets into SRF-computing and SRF-free targets. Replace
1739  * each of the named targets with a SRF-free version, and remember the
1740  * list of additional projection steps we need to add afterwards.
1741  */
1742  if (parse->hasTargetSRFs)
1743  {
1744  /* final_target doesn't recompute any SRFs in sort_input_target */
1745  split_pathtarget_at_srfs(root, final_target, sort_input_target,
1746  &final_targets,
1747  &final_targets_contain_srfs);
1748  final_target = (PathTarget *) linitial(final_targets);
1749  Assert(!linitial_int(final_targets_contain_srfs));
1750  /* likewise for sort_input_target vs. grouping_target */
1751  split_pathtarget_at_srfs(root, sort_input_target, grouping_target,
1752  &sort_input_targets,
1753  &sort_input_targets_contain_srfs);
1754  sort_input_target = (PathTarget *) linitial(sort_input_targets);
1755  Assert(!linitial_int(sort_input_targets_contain_srfs));
1756  /* likewise for grouping_target vs. scanjoin_target */
1757  split_pathtarget_at_srfs(root, grouping_target, scanjoin_target,
1758  &grouping_targets,
1759  &grouping_targets_contain_srfs);
1760  grouping_target = (PathTarget *) linitial(grouping_targets);
1761  Assert(!linitial_int(grouping_targets_contain_srfs));
1762  /* scanjoin_target will not have any SRFs precomputed for it */
1763  split_pathtarget_at_srfs(root, scanjoin_target, NULL,
1764  &scanjoin_targets,
1765  &scanjoin_targets_contain_srfs);
1766  scanjoin_target = (PathTarget *) linitial(scanjoin_targets);
1767  Assert(!linitial_int(scanjoin_targets_contain_srfs));
1768  }
1769  else
1770  {
1771  /* initialize lists, just to keep compiler quiet */
1772  final_targets = final_targets_contain_srfs = NIL;
1773  sort_input_targets = sort_input_targets_contain_srfs = NIL;
1774  grouping_targets = grouping_targets_contain_srfs = NIL;
1775  scanjoin_targets = scanjoin_targets_contain_srfs = NIL;
1776  }
1777 
1778  /*
1779  * Forcibly apply SRF-free scan/join target to all the Paths for the
1780  * scan/join rel.
1781  *
1782  * In principle we should re-run set_cheapest() here to identify the
1783  * cheapest path, but it seems unlikely that adding the same tlist
1784  * eval costs to all the paths would change that, so we don't bother.
1785  * Instead, just assume that the cheapest-startup and cheapest-total
1786  * paths remain so. (There should be no parameterized paths anymore,
1787  * so we needn't worry about updating cheapest_parameterized_paths.)
1788  */
1789  foreach(lc, current_rel->pathlist)
1790  {
1791  Path *subpath = (Path *) lfirst(lc);
1792  Path *path;
1793 
1794  Assert(subpath->param_info == NULL);
1795  path = apply_projection_to_path(root, current_rel,
1796  subpath, scanjoin_target);
1797  /* If we had to add a Result, path is different from subpath */
1798  if (path != subpath)
1799  {
1800  lfirst(lc) = path;
1801  if (subpath == current_rel->cheapest_startup_path)
1802  current_rel->cheapest_startup_path = path;
1803  if (subpath == current_rel->cheapest_total_path)
1804  current_rel->cheapest_total_path = path;
1805  }
1806  }
1807 
1808  /*
1809  * Upper planning steps which make use of the top scan/join rel's
1810  * partial pathlist will expect partial paths for that rel to produce
1811  * the same output as complete paths ... and we just changed the
1812  * output for the complete paths, so we'll need to do the same thing
1813  * for partial paths. But only parallel-safe expressions can be
1814  * computed by partial paths.
1815  */
1816  if (current_rel->partial_pathlist &&
1817  is_parallel_safe(root, (Node *) scanjoin_target->exprs))
1818  {
1819  /* Apply the scan/join target to each partial path */
1820  foreach(lc, current_rel->partial_pathlist)
1821  {
1822  Path *subpath = (Path *) lfirst(lc);
1823  Path *newpath;
1824 
1825  /* Shouldn't have any parameterized paths anymore */
1826  Assert(subpath->param_info == NULL);
1827 
1828  /*
1829  * Don't use apply_projection_to_path() here, because there
1830  * could be other pointers to these paths, and therefore we
1831  * mustn't modify them in place.
1832  */
1833  newpath = (Path *) create_projection_path(root,
1834  current_rel,
1835  subpath,
1836  scanjoin_target);
1837  lfirst(lc) = newpath;
1838  }
1839  }
1840  else
1841  {
1842  /*
1843  * In the unfortunate event that scanjoin_target is not
1844  * parallel-safe, we can't apply it to the partial paths; in that
1845  * case, we'll need to forget about the partial paths, which
1846  * aren't valid input for upper planning steps.
1847  */
1848  current_rel->partial_pathlist = NIL;
1849  }
1850 
1851  /* Now fix things up if scan/join target contains SRFs */
1852  if (parse->hasTargetSRFs)
1853  adjust_paths_for_srfs(root, current_rel,
1854  scanjoin_targets,
1855  scanjoin_targets_contain_srfs);
1856 
1857  /*
1858  * Save the various upper-rel PathTargets we just computed into
1859  * root->upper_targets[]. The core code doesn't use this, but it
1860  * provides a convenient place for extensions to get at the info. For
1861  * consistency, we save all the intermediate targets, even though some
1862  * of the corresponding upperrels might not be needed for this query.
1863  */
1864  root->upper_targets[UPPERREL_FINAL] = final_target;
1865  root->upper_targets[UPPERREL_WINDOW] = sort_input_target;
1866  root->upper_targets[UPPERREL_GROUP_AGG] = grouping_target;
1867 
1868  /*
1869  * If we have grouping and/or aggregation, consider ways to implement
1870  * that. We build a new upperrel representing the output of this
1871  * phase.
1872  */
1873  if (have_grouping)
1874  {
1875  current_rel = create_grouping_paths(root,
1876  current_rel,
1877  grouping_target,
1878  &agg_costs,
1879  rollup_lists,
1880  rollup_groupclauses);
1881  /* Fix things up if grouping_target contains SRFs */
1882  if (parse->hasTargetSRFs)
1883  adjust_paths_for_srfs(root, current_rel,
1884  grouping_targets,
1885  grouping_targets_contain_srfs);
1886  }
1887 
1888  /*
1889  * If we have window functions, consider ways to implement those. We
1890  * build a new upperrel representing the output of this phase.
1891  */
1892  if (activeWindows)
1893  {
1894  current_rel = create_window_paths(root,
1895  current_rel,
1896  grouping_target,
1897  sort_input_target,
1898  tlist,
1899  wflists,
1900  activeWindows);
1901  /* Fix things up if sort_input_target contains SRFs */
1902  if (parse->hasTargetSRFs)
1903  adjust_paths_for_srfs(root, current_rel,
1904  sort_input_targets,
1905  sort_input_targets_contain_srfs);
1906  }
1907 
1908  /*
1909  * If there is a DISTINCT clause, consider ways to implement that. We
1910  * build a new upperrel representing the output of this phase.
1911  */
1912  if (parse->distinctClause)
1913  {
1914  current_rel = create_distinct_paths(root,
1915  current_rel);
1916  }
1917 
1918  } /* end of if (setOperations) */
1919 
1920  /*
1921  * If ORDER BY was given, consider ways to implement that, and generate a
1922  * new upperrel containing only paths that emit the correct ordering and
1923  * project the correct final_target. We can apply the original
1924  * limit_tuples limit in sort costing here, but only if there are no
1925  * postponed SRFs.
1926  */
1927  if (parse->sortClause)
1928  {
1929  current_rel = create_ordered_paths(root,
1930  current_rel,
1931  final_target,
1932  have_postponed_srfs ? -1.0 :
1933  limit_tuples);
1934  /* Fix things up if final_target contains SRFs */
1935  if (parse->hasTargetSRFs)
1936  adjust_paths_for_srfs(root, current_rel,
1937  final_targets,
1938  final_targets_contain_srfs);
1939  }
1940 
1941  /*
1942  * Now we are prepared to build the final-output upperrel.
1943  */
1944  final_rel = fetch_upper_rel(root, UPPERREL_FINAL, NULL);
1945 
1946  /*
1947  * If the input rel is marked consider_parallel and there's nothing that's
1948  * not parallel-safe in the LIMIT clause, then the final_rel can be marked
1949  * consider_parallel as well. Note that if the query has rowMarks or is
1950  * not a SELECT, consider_parallel will be false for every relation in the
1951  * query.
1952  */
1953  if (current_rel->consider_parallel &&
1954  is_parallel_safe(root, parse->limitOffset) &&
1955  is_parallel_safe(root, parse->limitCount))
1956  final_rel->consider_parallel = true;
1957 
1958  /*
1959  * If the current_rel belongs to a single FDW, so does the final_rel.
1960  */
1961  final_rel->serverid = current_rel->serverid;
1962  final_rel->userid = current_rel->userid;
1963  final_rel->useridiscurrent = current_rel->useridiscurrent;
1964  final_rel->fdwroutine = current_rel->fdwroutine;
1965 
1966  /*
1967  * Generate paths for the final_rel. Insert all surviving paths, with
1968  * LockRows, Limit, and/or ModifyTable steps added if needed.
1969  */
1970  foreach(lc, current_rel->pathlist)
1971  {
1972  Path *path = (Path *) lfirst(lc);
1973 
1974  /*
1975  * If there is a FOR [KEY] UPDATE/SHARE clause, add the LockRows node.
1976  * (Note: we intentionally test parse->rowMarks not root->rowMarks
1977  * here. If there are only non-locking rowmarks, they should be
1978  * handled by the ModifyTable node instead. However, root->rowMarks
1979  * is what goes into the LockRows node.)
1980  */
1981  if (parse->rowMarks)
1982  {
1983  path = (Path *) create_lockrows_path(root, final_rel, path,
1984  root->rowMarks,
1985  SS_assign_special_param(root));
1986  }
1987 
1988  /*
1989  * If there is a LIMIT/OFFSET clause, add the LIMIT node.
1990  */
1991  if (limit_needed(parse))
1992  {
1993  path = (Path *) create_limit_path(root, final_rel, path,
1994  parse->limitOffset,
1995  parse->limitCount,
1996  offset_est, count_est);
1997  }
1998 
1999  /*
2000  * If this is an INSERT/UPDATE/DELETE, and we're not being called from
2001  * inheritance_planner, add the ModifyTable node.
2002  */
2003  if (parse->commandType != CMD_SELECT && !inheritance_update)
2004  {
2005  List *withCheckOptionLists;
2006  List *returningLists;
2007  List *rowMarks;
2008 
2009  /*
2010  * Set up the WITH CHECK OPTION and RETURNING lists-of-lists, if
2011  * needed.
2012  */
2013  if (parse->withCheckOptions)
2014  withCheckOptionLists = list_make1(parse->withCheckOptions);
2015  else
2016  withCheckOptionLists = NIL;
2017 
2018  if (parse->returningList)
2019  returningLists = list_make1(parse->returningList);
2020  else
2021  returningLists = NIL;
2022 
2023  /*
2024  * If there was a FOR [KEY] UPDATE/SHARE clause, the LockRows node
2025  * will have dealt with fetching non-locked marked rows, else we
2026  * need to have ModifyTable do that.
2027  */
2028  if (parse->rowMarks)
2029  rowMarks = NIL;
2030  else
2031  rowMarks = root->rowMarks;
2032 
2033  path = (Path *)
2034  create_modifytable_path(root, final_rel,
2035  parse->commandType,
2036  parse->canSetTag,
2037  parse->resultRelation,
2039  list_make1(path),
2040  list_make1(root),
2041  withCheckOptionLists,
2042  returningLists,
2043  rowMarks,
2044  parse->onConflict,
2045  SS_assign_special_param(root));
2046  }
2047 
2048  /* And shove it into final_rel */
2049  add_path(final_rel, path);
2050  }
2051 
2052  /*
2053  * If there is an FDW that's responsible for all baserels of the query,
2054  * let it consider adding ForeignPaths.
2055  */
2056  if (final_rel->fdwroutine &&
2057  final_rel->fdwroutine->GetForeignUpperPaths)
2059  current_rel, final_rel);
2060 
2061  /* Let extensions possibly add some more paths */
2063  (*create_upper_paths_hook) (root, UPPERREL_FINAL,
2064  current_rel, final_rel);
2065 
2066  /* Note: currently, we leave it to callers to do set_cheapest() */
2067 }
Path * apply_projection_to_path(PlannerInfo *root, RelOptInfo *rel, Path *path, PathTarget *target)
Definition: pathnode.c:2253
RelOptInfo * plan_set_operations(PlannerInfo *root)
Definition: prepunion.c:129
GetForeignUpperPaths_function GetForeignUpperPaths
Definition: fdwapi.h:190
Node * limitOffset
Definition: parsenodes.h:149
#define NIL
Definition: pg_list.h:69
List * rowMarks
Definition: relation.h:251
static double preprocess_limit(PlannerInfo *root, double tuple_fraction, int64 *offset_est, int64 *count_est)
Definition: planner.c:2282
ModifyTablePath * create_modifytable_path(PlannerInfo *root, RelOptInfo *rel, CmdType operation, bool canSetTag, Index nominalRelation, List *resultRelations, List *subpaths, List *subroots, List *withCheckOptionLists, List *returningLists, List *rowMarks, OnConflictExpr *onconflict, int epqParam)
Definition: pathnode.c:3019
PathTarget * pathtarget
Definition: relation.h:895
Query * parse
Definition: relation.h:152
const char * LCS_asString(LockClauseStrength strength)
Definition: analyze.c:2576
void add_path(RelOptInfo *parent_rel, Path *new_path)
Definition: pathnode.c:412
List * sortClause
Definition: parsenodes.h:147
static List * extract_rollup_sets(List *groupingSets)
Definition: planner.c:2784
LockRowsPath * create_lockrows_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, List *rowMarks, int epqParam)
Definition: pathnode.c:2963
int SS_assign_special_param(PlannerInfo *root)
Definition: subselect.c:415
OnConflictExpr * onConflict
Definition: parsenodes.h:133
List * make_pathkeys_for_sortclauses(PlannerInfo *root, List *sortclauses, List *tlist)
Definition: pathkeys.c:838
List * preprocess_onconflict_targetlist(List *tlist, int result_relation, List *range_table)
Definition: preptlist.c:206
static List * preprocess_groupclause(PlannerInfo *root, List *force)
Definition: planner.c:2681
RelOptInfo * query_planner(PlannerInfo *root, List *tlist, query_pathkeys_callback qp_callback, void *qp_extra)
Definition: planmain.c:54
struct Path * cheapest_startup_path
Definition: relation.h:507
Oid userid
Definition: relation.h:537
List * withCheckOptions
Definition: parsenodes.h:160
void split_pathtarget_at_srfs(PlannerInfo *root, PathTarget *target, PathTarget *input_target, List **targets, List **targets_contain_srfs)
Definition: tlist.c:840
void get_agg_clause_costs(PlannerInfo *root, Node *clause, AggSplit aggsplit, AggClauseCosts *costs)
Definition: clauses.c:466
bool hasAggs
Definition: parsenodes.h:116
int resultRelation
Definition: parsenodes.h:113
int numWindowFuncs
Definition: clauses.h:25
WindowFuncLists * find_window_functions(Node *clause, Index maxWinRef)
Definition: clauses.c:739
#define llast(l)
Definition: pg_list.h:126
Index tleSortGroupRef
Definition: parsenodes.h:1102
List * preprocess_targetlist(PlannerInfo *root, List *tlist)
Definition: preptlist.c:64
ParamPathInfo * param_info
Definition: relation.h:897
List * groupingSets
Definition: parsenodes.h:139
Definition: nodes.h:508
ProjectionPath * create_projection_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target)
Definition: pathnode.c:2162
int errcode(int sqlerrcode)
Definition: elog.c:575
List * partial_pathlist
Definition: relation.h:506
static RelOptInfo * create_distinct_paths(PlannerInfo *root, RelOptInfo *input_rel)
Definition: planner.c:3999
#define MemSet(start, val, len)
Definition: c.h:852
List * tlist
Definition: planner.c:87
static PathTarget * make_group_input_target(PlannerInfo *root, PathTarget *final_target)
Definition: planner.c:4319
create_upper_paths_hook_type create_upper_paths_hook
Definition: planner.c:68
bool useridiscurrent
Definition: relation.h:538
void preprocess_minmax_aggregates(PlannerInfo *root, List *tlist)
Definition: planagg.c:75
List * rowMarks
Definition: parsenodes.h:152
LimitPath * create_limit_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, Node *limitOffset, Node *limitCount, int64 offset_est, int64 count_est)
Definition: pathnode.c:3118
bool hasRecursion
Definition: relation.h:300
static RelOptInfo * create_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, PathTarget *target, const AggClauseCosts *agg_costs, List *rollup_lists, List *rollup_groupclauses)
Definition: planner.c:3252
List * windowClause
Definition: parsenodes.h:143
List * targetList
Definition: parsenodes.h:131
static List * postprocess_setop_tlist(List *new_tlist, List *orig_tlist)
Definition: planner.c:4542
void * copyObject(const void *from)
Definition: copyfuncs.c:4475
static void adjust_paths_for_srfs(PlannerInfo *root, RelOptInfo *rel, List *targets, List *targets_contain_srfs)
Definition: planner.c:5101
#define list_make1(x1)
Definition: pg_list.h:133
#define linitial_int(l)
Definition: pg_list.h:111
bool is_parallel_safe(PlannerInfo *root, Node *node)
Definition: clauses.c:1071
double tuple_fraction
Definition: relation.h:286
#define linitial(l)
Definition: pg_list.h:110
List * rtable
Definition: parsenodes.h:128
List * distinctClause
Definition: parsenodes.h:145
#define ERROR
Definition: elog.h:43
static bool limit_needed(Query *parse)
Definition: planner.c:2467
double limit_tuples
Definition: relation.h:287
#define lfirst_int(lc)
Definition: pg_list.h:107
static List * reorder_grouping_sets(List *groupingSets, List *sortclause)
Definition: planner.c:2996
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
Definition: relnode.c:870
struct Path * cheapest_total_path
Definition: relation.h:508
Node * limitCount
Definition: parsenodes.h:150
static PathTarget * make_window_input_target(PlannerInfo *root, PathTarget *final_target, List *activeWindows)
Definition: planner.c:4672
struct FdwRoutine * fdwroutine
Definition: relation.h:540
static void standard_qp_callback(PlannerInfo *root, void *extra)
Definition: planner.c:3047
#define create_pathtarget(root, tlist)
Definition: tlist.h:69
List * returningList
Definition: parsenodes.h:135
#define list_make1_int(x1)
Definition: pg_list.h:139
#define ereport(elevel, rest)
Definition: elog.h:122
List * sort_pathkeys
Definition: relation.h:262
static RelOptInfo * create_ordered_paths(PlannerInfo *root, RelOptInfo *input_rel, PathTarget *target, double limit_tuples)
Definition: planner.c:4210
Oid serverid
Definition: relation.h:536
List * exprs
Definition: relation.h:824
CmdType commandType
Definition: parsenodes.h:103
bool hasTargetSRFs
Definition: parsenodes.h:118
List * lcons(void *datum, List *list)
Definition: list.c:259
List * groupClause
Definition: planner.c:89
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
bool hasWindowFuncs
Definition: parsenodes.h:117
bool canSetTag
Definition: parsenodes.h:109
static int list_length(const List *l)
Definition: pg_list.h:89
static RelOptInfo * create_window_paths(PlannerInfo *root, RelOptInfo *input_rel, PathTarget *input_target, PathTarget *output_target, List *tlist, WindowFuncLists *wflists, List *activeWindows)
Definition: planner.c:3818
bool consider_parallel
Definition: relation.h:498
List * activeWindows
Definition: planner.c:88
List * expand_grouping_sets(List *groupingSets, int limit)
Definition: parse_agg.c:1687
Node * setOperations
Definition: parsenodes.h:154
List * groupClause
Definition: parsenodes.h:137
void * palloc(Size size)
Definition: mcxt.c:891
int errmsg(const char *fmt,...)
Definition: elog.c:797
List * onConflictSet
Definition: primnodes.h:1458
static List * select_active_windows(PlannerInfo *root, WindowFuncLists *wflists)
Definition: planner.c:4575
bool hasHavingQual
Definition: relation.h:297
List * pathlist
Definition: relation.h:504
Node * havingQual
Definition: parsenodes.h:141
List * processed_tlist
Definition: relation.h:276
Definition: pg_list.h:45
Definition: relation.h:888
Datum subpath(PG_FUNCTION_ARGS)
Definition: ltree_op.c:234
static PathTarget * make_sort_input_target(PlannerInfo *root, PathTarget *final_target, bool *have_postponed_srfs)
Definition: planner.c:4887
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:651
struct PathTarget * upper_targets[UPPERREL_FINAL+1]
Definition: relation.h:270
static void inheritance_planner ( PlannerInfo root)
static

Definition at line 980 of file planner.c.

References add_path(), adjust_appendrel_attrs(), PlannerInfo::append_rel_list, Assert, bms_add_member(), bms_is_member(), bms_overlap(), Query::canSetTag, ChangeVarNodes(), RelOptInfo::cheapest_total_path, AppendRelInfo::child_relid, CMD_INSERT, Query::commandType, copyObject(), create_modifytable_path(), fetch_upper_rel(), grouping_planner(), PlannerInfo::hasInheritedTarget, PlannerInfo::init_plans, IS_DUMMY_PATH, PlannerInfo::join_info_list, lappend(), lappend_int(), lfirst, list_concat(), list_copy_tail(), list_length(), makeNode, NIL, NULL, Query::onConflict, palloc0(), AppendRelInfo::parent_relid, parse(), PlannerInfo::parse, PlannerInfo::placeholder_list, pull_varnos(), Query::resultRelation, Query::returningList, Query::rowMarks, PlannerInfo::rowMarks, rt_fetch, Query::rtable, RTE_SUBQUERY, RangeTblEntry::rtekind, RangeTblEntry::securityQuals, set_cheapest(), set_dummy_rel_pathlist(), PlannerInfo::simple_rel_array, PlannerInfo::simple_rel_array_size, PlannerInfo::simple_rte_array, SS_assign_special_param(), subpath(), AppendRelInfo::translated_vars, UPPERREL_FINAL, and Query::withCheckOptions.

Referenced by subquery_planner().

981 {
982  Query *parse = root->parse;
983  int parentRTindex = parse->resultRelation;
984  Bitmapset *subqueryRTindexes;
985  Bitmapset *modifiableARIindexes;
986  int nominalRelation = -1;
987  List *final_rtable = NIL;
988  int save_rel_array_size = 0;
989  RelOptInfo **save_rel_array = NULL;
990  List *subpaths = NIL;
991  List *subroots = NIL;
992  List *resultRelations = NIL;
993  List *withCheckOptionLists = NIL;
994  List *returningLists = NIL;
995  List *rowMarks;
996  RelOptInfo *final_rel;
997  ListCell *lc;
998  Index rti;
999 
1000  Assert(parse->commandType != CMD_INSERT);
1001 
1002  /*
1003  * We generate a modified instance of the original Query for each target
1004  * relation, plan that, and put all the plans into a list that will be
1005  * controlled by a single ModifyTable node. All the instances share the
1006  * same rangetable, but each instance must have its own set of subquery
1007  * RTEs within the finished rangetable because (1) they are likely to get
1008  * scribbled on during planning, and (2) it's not inconceivable that
1009  * subqueries could get planned differently in different cases. We need
1010  * not create duplicate copies of other RTE kinds, in particular not the
1011  * target relations, because they don't have either of those issues. Not
1012  * having to duplicate the target relations is important because doing so
1013  * (1) would result in a rangetable of length O(N^2) for N targets, with
1014  * at least O(N^3) work expended here; and (2) would greatly complicate
1015  * management of the rowMarks list.
1016  *
1017  * To begin with, generate a bitmapset of the relids of the subquery RTEs.
1018  */
1019  subqueryRTindexes = NULL;
1020  rti = 1;
1021  foreach(lc, parse->rtable)
1022  {
1023  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
1024 
1025  if (rte->rtekind == RTE_SUBQUERY)
1026  subqueryRTindexes = bms_add_member(subqueryRTindexes, rti);
1027  rti++;
1028  }
1029 
1030  /*
1031  * Next, we want to identify which AppendRelInfo items contain references
1032  * to any of the aforesaid subquery RTEs. These items will need to be
1033  * copied and modified to adjust their subquery references; whereas the
1034  * other ones need not be touched. It's worth being tense over this
1035  * because we can usually avoid processing most of the AppendRelInfo
1036  * items, thereby saving O(N^2) space and time when the target is a large
1037  * inheritance tree. We can identify AppendRelInfo items by their
1038  * child_relid, since that should be unique within the list.
1039  */
1040  modifiableARIindexes = NULL;
1041  if (subqueryRTindexes != NULL)
1042  {
1043  foreach(lc, root->append_rel_list)
1044  {
1045  AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(lc);
1046 
1047  if (bms_is_member(appinfo->parent_relid, subqueryRTindexes) ||
1048  bms_is_member(appinfo->child_relid, subqueryRTindexes) ||
1050  subqueryRTindexes))
1051  modifiableARIindexes = bms_add_member(modifiableARIindexes,
1052  appinfo->child_relid);
1053  }
1054  }
1055 
1056  /*
1057  * And now we can get on with generating a plan for each child table.
1058  */
1059  foreach(lc, root->append_rel_list)
1060  {
1061  AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(lc);
1062  PlannerInfo *subroot;
1063  RangeTblEntry *parent_rte;
1064  RangeTblEntry *child_rte;
1065  RelOptInfo *sub_final_rel;
1066  Path *subpath;
1067 
1068  /* append_rel_list contains all append rels; ignore others */
1069  if (appinfo->parent_relid != parentRTindex)
1070  continue;
1071 
1072  /*
1073  * We need a working copy of the PlannerInfo so that we can control
1074  * propagation of information back to the main copy.
1075  */
1076  subroot = makeNode(PlannerInfo);
1077  memcpy(subroot, root, sizeof(PlannerInfo));
1078 
1079  /*
1080  * Generate modified query with this rel as target. We first apply
1081  * adjust_appendrel_attrs, which copies the Query and changes
1082  * references to the parent RTE to refer to the current child RTE,
1083  * then fool around with subquery RTEs.
1084  */
1085  subroot->parse = (Query *)
1087  (Node *) parse,
1088  appinfo);
1089 
1090  /*
1091  * If there are securityQuals attached to the parent, move them to the
1092  * child rel (they've already been transformed properly for that).
1093  */
1094  parent_rte = rt_fetch(parentRTindex, subroot->parse->rtable);
1095  child_rte = rt_fetch(appinfo->child_relid, subroot->parse->rtable);
1096  child_rte->securityQuals = parent_rte->securityQuals;
1097  parent_rte->securityQuals = NIL;
1098 
1099  /*
1100  * The rowMarks list might contain references to subquery RTEs, so
1101  * make a copy that we can apply ChangeVarNodes to. (Fortunately, the
1102  * executor doesn't need to see the modified copies --- we can just
1103  * pass it the original rowMarks list.)
1104  */
1105  subroot->rowMarks = (List *) copyObject(root->rowMarks);
1106 
1107  /*
1108  * The append_rel_list likewise might contain references to subquery
1109  * RTEs (if any subqueries were flattenable UNION ALLs). So prepare
1110  * to apply ChangeVarNodes to that, too. As explained above, we only
1111  * want to copy items that actually contain such references; the rest
1112  * can just get linked into the subroot's append_rel_list.
1113  *
1114  * If we know there are no such references, we can just use the outer
1115  * append_rel_list unmodified.
1116  */
1117  if (modifiableARIindexes != NULL)
1118  {
1119  ListCell *lc2;
1120 
1121  subroot->append_rel_list = NIL;
1122  foreach(lc2, root->append_rel_list)
1123  {
1124  AppendRelInfo *appinfo2 = (AppendRelInfo *) lfirst(lc2);
1125 
1126  if (bms_is_member(appinfo2->child_relid, modifiableARIindexes))
1127  appinfo2 = (AppendRelInfo *) copyObject(appinfo2);
1128 
1129  subroot->append_rel_list = lappend(subroot->append_rel_list,
1130  appinfo2);
1131  }
1132  }
1133 
1134  /*
1135  * Add placeholders to the child Query's rangetable list to fill the
1136  * RT indexes already reserved for subqueries in previous children.
1137  * These won't be referenced, so there's no need to make them very
1138  * valid-looking.
1139  */
1140  while (list_length(subroot->parse->rtable) < list_length(final_rtable))
1141  subroot->parse->rtable = lappend(subroot->parse->rtable,
1143 
1144  /*
1145  * If this isn't the first child Query, generate duplicates of all
1146  * subquery RTEs, and adjust Var numbering to reference the
1147  * duplicates. To simplify the loop logic, we scan the original rtable
1148  * not the copy just made by adjust_appendrel_attrs; that should be OK
1149  * since subquery RTEs couldn't contain any references to the target
1150  * rel.
1151  */
1152  if (final_rtable != NIL && subqueryRTindexes != NULL)
1153  {
1154  ListCell *lr;
1155 
1156  rti = 1;
1157  foreach(lr, parse->rtable)
1158  {
1159  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lr);
1160 
1161  if (bms_is_member(rti, subqueryRTindexes))
1162  {
1163  Index newrti;
1164 
1165  /*
1166  * The RTE can't contain any references to its own RT
1167  * index, except in its securityQuals, so we can save a
1168  * few cycles by applying ChangeVarNodes to the rest of
1169  * the rangetable before we append the RTE to it.
1170  */
1171  newrti = list_length(subroot->parse->rtable) + 1;
1172  ChangeVarNodes((Node *) subroot->parse, rti, newrti, 0);
1173  ChangeVarNodes((Node *) subroot->rowMarks, rti, newrti, 0);
1174  /* Skip processing unchanging parts of append_rel_list */
1175  if (modifiableARIindexes != NULL)
1176  {
1177  ListCell *lc2;
1178 
1179  foreach(lc2, subroot->append_rel_list)
1180  {
1181  AppendRelInfo *appinfo2 = (AppendRelInfo *) lfirst(lc2);
1182 
1183  if (bms_is_member(appinfo2->child_relid,
1184  modifiableARIindexes))
1185  ChangeVarNodes((Node *) appinfo2, rti, newrti, 0);
1186  }
1187  }
1188  rte = copyObject(rte);
1189  ChangeVarNodes((Node *) rte->securityQuals, rti, newrti, 0);
1190  subroot->parse->rtable = lappend(subroot->parse->rtable,
1191  rte);
1192  }
1193  rti++;
1194  }
1195  }
1196 
1197  /* There shouldn't be any OJ info to translate, as yet */
1198  Assert(subroot->join_info_list == NIL);
1199  /* and we haven't created PlaceHolderInfos, either */
1200  Assert(subroot->placeholder_list == NIL);
1201  /* hack to mark target relation as an inheritance partition */
1202  subroot->hasInheritedTarget = true;
1203 
1204  /* Generate Path(s) for accessing this result relation */
1205  grouping_planner(subroot, true, 0.0 /* retrieve all tuples */ );
1206 
1207  /*
1208  * We'll use the first child relation (even if it's excluded) as the
1209  * nominal target relation of the ModifyTable node. Because of the
1210  * way expand_inherited_rtentry works, this should always be the RTE
1211  * representing the parent table in its role as a simple member of the
1212  * inheritance set. (It would be logically cleaner to use the
1213  * inheritance parent RTE as the nominal target; but since that RTE
1214  * will not be otherwise referenced in the plan, doing so would give
1215  * rise to confusing use of multiple aliases in EXPLAIN output for
1216  * what the user will think is the "same" table.)
1217  */
1218  if (nominalRelation < 0)
1219  nominalRelation = appinfo->child_relid;
1220 
1221  /*
1222  * Select cheapest path in case there's more than one. We always run
1223  * modification queries to conclusion, so we care only for the
1224  * cheapest-total path.
1225  */
1226  sub_final_rel = fetch_upper_rel(subroot, UPPERREL_FINAL, NULL);
1227  set_cheapest(sub_final_rel);
1228  subpath = sub_final_rel->cheapest_total_path;
1229 
1230  /*
1231  * If this child rel was excluded by constraint exclusion, exclude it
1232  * from the result plan.
1233  */
1234  if (IS_DUMMY_PATH(subpath))
1235  continue;
1236 
1237  /*
1238  * If this is the first non-excluded child, its post-planning rtable
1239  * becomes the initial contents of final_rtable; otherwise, append
1240  * just its modified subquery RTEs to final_rtable.
1241  */
1242  if (final_rtable == NIL)
1243  final_rtable = subroot->parse->rtable;
1244  else
1245  final_rtable = list_concat(final_rtable,
1246  list_copy_tail(subroot->parse->rtable,
1247  list_length(final_rtable)));
1248 
1249  /*
1250  * We need to collect all the RelOptInfos from all child plans into
1251  * the main PlannerInfo, since setrefs.c will need them. We use the
1252  * last child's simple_rel_array (previous ones are too short), so we
1253  * have to propagate forward the RelOptInfos that were already built
1254  * in previous children.
1255  */
1256  Assert(subroot->simple_rel_array_size >= save_rel_array_size);
1257  for (rti = 1; rti < save_rel_array_size; rti++)
1258  {
1259  RelOptInfo *brel = save_rel_array[rti];
1260 
1261  if (brel)
1262  subroot->simple_rel_array[rti] = brel;
1263  }
1264  save_rel_array_size = subroot->simple_rel_array_size;
1265  save_rel_array = subroot->simple_rel_array;
1266 
1267  /* Make sure any initplans from this rel get into the outer list */
1268  root->init_plans = subroot->init_plans;
1269 
1270  /* Build list of sub-paths */
1271  subpaths = lappend(subpaths, subpath);
1272 
1273  /* Build list of modified subroots, too */
1274  subroots = lappend(subroots, subroot);
1275 
1276  /* Build list of target-relation RT indexes */
1277  resultRelations = lappend_int(resultRelations, appinfo->child_relid);
1278 
1279  /* Build lists of per-relation WCO and RETURNING targetlists */
1280  if (parse->withCheckOptions)
1281  withCheckOptionLists = lappend(withCheckOptionLists,
1282  subroot->parse->withCheckOptions);
1283  if (parse->returningList)
1284  returningLists = lappend(returningLists,
1285  subroot->parse->returningList);
1286 
1287  Assert(!parse->onConflict);
1288  }
1289 
1290  /* Result path must go into outer query's FINAL upperrel */
1291  final_rel = fetch_upper_rel(root, UPPERREL_FINAL, NULL);
1292 
1293  /*
1294  * We don't currently worry about setting final_rel's consider_parallel
1295  * flag in this case, nor about allowing FDWs or create_upper_paths_hook
1296  * to get control here.
1297  */
1298 
1299  /*
1300  * If we managed to exclude every child rel, return a dummy plan; it
1301  * doesn't even need a ModifyTable node.
1302  */
1303  if (subpaths == NIL)
1304  {
1305  set_dummy_rel_pathlist(final_rel);
1306  return;
1307  }
1308 
1309  /*
1310  * Put back the final adjusted rtable into the master copy of the Query.
1311  * (We mustn't do this if we found no non-excluded children.)
1312  */
1313  parse->rtable = final_rtable;
1314  root->simple_rel_array_size = save_rel_array_size;
1315  root->simple_rel_array = save_rel_array;
1316  /* Must reconstruct master's simple_rte_array, too */
1317  root->simple_rte_array = (RangeTblEntry **)
1318  palloc0((list_length(final_rtable) + 1) * sizeof(RangeTblEntry *));
1319  rti = 1;
1320  foreach(lc, final_rtable)
1321  {
1322  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
1323 
1324  root->simple_rte_array[rti++] = rte;
1325  }
1326 
1327  /*
1328  * If there was a FOR [KEY] UPDATE/SHARE clause, the LockRows node will
1329  * have dealt with fetching non-locked marked rows, else we need to have
1330  * ModifyTable do that.
1331  */
1332  if (parse->rowMarks)
1333  rowMarks = NIL;
1334  else
1335  rowMarks = root->rowMarks;
1336 
1337  /* Create Path representing a ModifyTable to do the UPDATE/DELETE work */
1338  add_path(final_rel, (Path *)
1339  create_modifytable_path(root, final_rel,
1340  parse->commandType,
1341  parse->canSetTag,
1342  nominalRelation,
1343  resultRelations,
1344  subpaths,
1345  subroots,
1346  withCheckOptionLists,
1347  returningLists,
1348  rowMarks,
1349  NULL,
1350  SS_assign_special_param(root)));
1351 }
#define NIL
Definition: pg_list.h:69
List * rowMarks
Definition: relation.h:251
ModifyTablePath * create_modifytable_path(PlannerInfo *root, RelOptInfo *rel, CmdType operation, bool canSetTag, Index nominalRelation, List *resultRelations, List *subpaths, List *subroots, List *withCheckOptionLists, List *returningLists, List *rowMarks, OnConflictExpr *onconflict, int epqParam)
Definition: pathnode.c:3019
Query * parse
Definition: relation.h:152
void add_path(RelOptInfo *parent_rel, Path *new_path)
Definition: pathnode.c:412
List * join_info_list
Definition: relation.h:247
int SS_assign_special_param(PlannerInfo *root)
Definition: subselect.c:415
OnConflictExpr * onConflict
Definition: parsenodes.h:133
List * withCheckOptions
Definition: parsenodes.h:160
List * securityQuals
Definition: parsenodes.h:970
int resultRelation
Definition: parsenodes.h:113
Definition: nodes.h:508
List * list_concat(List *list1, List *list2)
Definition: list.c:321
List * list_copy_tail(const List *oldlist, int nskip)
Definition: list.c:1203
List * rowMarks
Definition: parsenodes.h:152
List * translated_vars
Definition: relation.h:1893
struct RelOptInfo ** simple_rel_array
Definition: relation.h:176
void * copyObject(const void *from)
Definition: copyfuncs.c:4475
#define IS_DUMMY_PATH(p)
Definition: relation.h:1122
void set_dummy_rel_pathlist(RelOptInfo *rel)
Definition: allpaths.c:1616
List * rtable
Definition: parsenodes.h:128
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
Definition: relnode.c:870
Node * adjust_appendrel_attrs(PlannerInfo *root, Node *node, AppendRelInfo *appinfo)
Definition: prepunion.c:1733
struct Path * cheapest_total_path
Definition: relation.h:508
List * returningList
Definition: parsenodes.h:135
int simple_rel_array_size
Definition: relation.h:177
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
Relids pull_varnos(Node *node)
Definition: var.c:95
List * lappend_int(List *list, int datum)
Definition: list.c:146
List * lappend(List *list, void *datum)
Definition: list.c:128
RangeTblEntry ** simple_rte_array
Definition: relation.h:185
void set_cheapest(RelOptInfo *parent_rel)
Definition: pathnode.c:234
void * palloc0(Size size)
Definition: mcxt.c:920
List * append_rel_list
Definition: relation.h:249
unsigned int Index
Definition: c.h:361
List * init_plans
Definition: relation.h:225
CmdType commandType
Definition: parsenodes.h:103
#define makeNode(_type_)
Definition: nodes.h:556
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
bool hasInheritedTarget
Definition: relation.h:292
bool canSetTag
Definition: parsenodes.h:109
static int list_length(const List *l)
Definition: pg_list.h:89
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:668
RTEKind rtekind
Definition: parsenodes.h:882
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:442
static void grouping_planner(PlannerInfo *root, bool inheritance_update, double tuple_fraction)
Definition: planner.c:1382
List * placeholder_list
Definition: relation.h:253
void ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up)
Definition: rewriteManip.c:607
Index child_relid
Definition: relation.h:1866
Index parent_relid
Definition: relation.h:1865
Definition: pg_list.h:45
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:419
Definition: relation.h:888
Datum subpath(PG_FUNCTION_ARGS)
Definition: ltree_op.c:234
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:651
bool is_dummy_plan ( Plan plan)

Definition at line 2080 of file planner.c.

References Const::constisnull, Const::constvalue, DatumGetBool, IsA, linitial, and list_length().

2081 {
2082  if (IsA(plan, Result))
2083  {
2084  List *rcqual = (List *) ((Result *) plan)->resconstantqual;
2085 
2086  if (list_length(rcqual) == 1)
2087  {
2088  Const *constqual = (Const *) linitial(rcqual);
2089 
2090  if (constqual && IsA(constqual, Const))
2091  {
2092  if (!constqual->constisnull &&
2093  !DatumGetBool(constqual->constvalue))
2094  return true;
2095  }
2096  }
2097  }
2098  return false;
2099 }
Datum constvalue
Definition: primnodes.h:174
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
#define linitial(l)
Definition: pg_list.h:110
#define DatumGetBool(X)
Definition: postgres.h:401
static int list_length(const List *l)
Definition: pg_list.h:89
Definition: pg_list.h:45
bool constisnull
Definition: primnodes.h:175
static bool limit_needed ( Query parse)
static

Definition at line 2467 of file planner.c.

References DatumGetInt64, IsA, Query::limitCount, and Query::limitOffset.

Referenced by grouping_planner().

2468 {
2469  Node *node;
2470 
2471  node = parse->limitCount;
2472  if (node)
2473  {
2474  if (IsA(node, Const))
2475  {
2476  /* NULL indicates LIMIT ALL, ie, no limit */
2477  if (!((Const *) node)->constisnull)
2478  return true; /* LIMIT with a constant value */
2479  }
2480  else
2481  return true; /* non-constant LIMIT */
2482  }
2483 
2484  node = parse->limitOffset;
2485  if (node)
2486  {
2487  if (IsA(node, Const))
2488  {
2489  /* Treat NULL as no offset; the executor would too */
2490  if (!((Const *) node)->constisnull)
2491  {
2492  int64 offset = DatumGetInt64(((Const *) node)->constvalue);
2493 
2494  if (offset != 0)
2495  return true; /* OFFSET with a nonzero value */
2496  }
2497  }
2498  else
2499  return true; /* non-constant OFFSET */
2500  }
2501 
2502  return false; /* don't need a Limit plan node */
2503 }
Node * limitOffset
Definition: parsenodes.h:149
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
Definition: nodes.h:508
#define DatumGetInt64(X)
Definition: postgres.h:615
Node * limitCount
Definition: parsenodes.h:150
static PathTarget * make_group_input_target ( PlannerInfo root,
PathTarget final_target 
)
static

Definition at line 4319 of file planner.c.

References add_column_to_pathtarget(), add_new_columns_to_pathtarget(), create_empty_pathtarget(), PathTarget::exprs, get_pathtarget_sortgroupref, get_sortgroupref_clause_noerr(), Query::groupClause, Query::havingQual, i, lappend(), lfirst, list_free(), NIL, NULL, parse(), PlannerInfo::parse, pull_var_clause(), PVC_INCLUDE_PLACEHOLDERS, PVC_RECURSE_AGGREGATES, PVC_RECURSE_WINDOWFUNCS, and set_pathtarget_cost_width().

Referenced by grouping_planner().

4320 {
4321  Query *parse = root->parse;
4322  PathTarget *input_target;
4323  List *non_group_cols;
4324  List *non_group_vars;
4325  int i;
4326  ListCell *lc;
4327 
4328  /*
4329  * We must build a target containing all grouping columns, plus any other
4330  * Vars mentioned in the query's targetlist and HAVING qual.
4331  */
4332  input_target = create_empty_pathtarget();
4333  non_group_cols = NIL;
4334 
4335  i = 0;
4336  foreach(lc, final_target->exprs)
4337  {
4338  Expr *expr = (Expr *) lfirst(lc);
4339  Index sgref = get_pathtarget_sortgroupref(final_target, i);
4340 
4341  if (sgref && parse->groupClause &&
4343  {
4344  /*
4345  * It's a grouping column, so add it to the input target as-is.
4346  */
4347  add_column_to_pathtarget(input_target, expr, sgref);
4348  }
4349  else
4350  {
4351  /*
4352  * Non-grouping column, so just remember the expression for later
4353  * call to pull_var_clause.
4354  */
4355  non_group_cols = lappend(non_group_cols, expr);
4356  }
4357 
4358  i++;
4359  }
4360 
4361  /*
4362  * If there's a HAVING clause, we'll need the Vars it uses, too.
4363  */
4364  if (parse->havingQual)
4365  non_group_cols = lappend(non_group_cols, parse->havingQual);
4366 
4367  /*
4368  * Pull out all the Vars mentioned in non-group cols (plus HAVING), and
4369  * add them to the input target if not already present. (A Var used
4370  * directly as a GROUP BY item will be present already.) Note this
4371  * includes Vars used in resjunk items, so we are covering the needs of
4372  * ORDER BY and window specifications. Vars used within Aggrefs and
4373  * WindowFuncs will be pulled out here, too.
4374  */
4375  non_group_vars = pull_var_clause((Node *) non_group_cols,
4379  add_new_columns_to_pathtarget(input_target, non_group_vars);
4380 
4381  /* clean up cruft */
4382  list_free(non_group_vars);
4383  list_free(non_group_cols);
4384 
4385  /* XXX this causes some redundant cost calculation ... */
4386  return set_pathtarget_cost_width(root, input_target);
4387 }
PathTarget * create_empty_pathtarget(void)
Definition: tlist.c:653
#define NIL
Definition: pg_list.h:69
Query * parse
Definition: relation.h:152
#define PVC_RECURSE_AGGREGATES
Definition: var.h:21
PathTarget * set_pathtarget_cost_width(PlannerInfo *root, PathTarget *target)
Definition: costsize.c:4702
void add_column_to_pathtarget(PathTarget *target, Expr *expr, Index sortgroupref)
Definition: tlist.c:667
Definition: nodes.h:508
List * pull_var_clause(Node *node, int flags)
Definition: var.c:535
#define PVC_INCLUDE_PLACEHOLDERS
Definition: var.h:24
#define PVC_RECURSE_WINDOWFUNCS
Definition: var.h:23
#define get_pathtarget_sortgroupref(target, colno)
Definition: relation.h:831
List * lappend(List *list, void *datum)
Definition: list.c:128
List * exprs
Definition: relation.h:824
SortGroupClause * get_sortgroupref_clause_noerr(Index sortref, List *clauses)
Definition: tlist.c:446
unsigned int Index
Definition: c.h:361
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
List * groupClause
Definition: parsenodes.h:137
void list_free(List *list)
Definition: list.c:1133
int i
Node * havingQual
Definition: parsenodes.h:141
Definition: pg_list.h:45
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:651
void add_new_columns_to_pathtarget(PathTarget *target, List *exprs)
Definition: tlist.c:714
static PathTarget * make_partial_grouping_target ( PlannerInfo root,
PathTarget grouping_target 
)
static

Definition at line 4406 of file planner.c.

References add_column_to_pathtarget(), add_new_columns_to_pathtarget(), AGGSPLIT_INITIAL_SERIAL, create_empty_pathtarget(), PathTarget::exprs, get_pathtarget_sortgroupref, get_sortgroupref_clause_noerr(), Query::groupClause, Query::havingQual, i, IsA, lappend(), lfirst, list_free(), makeNode, mark_partial_aggref(), NIL, NULL, parse(), PlannerInfo::parse, pull_var_clause(), PVC_INCLUDE_AGGREGATES, PVC_INCLUDE_PLACEHOLDERS, PVC_RECURSE_WINDOWFUNCS, and set_pathtarget_cost_width().

Referenced by create_grouping_paths().

4407 {
4408  Query *parse = root->parse;
4409  PathTarget *partial_target;
4410  List *non_group_cols;
4411  List *non_group_exprs;
4412  int i;
4413  ListCell *lc;
4414 
4415  partial_target = create_empty_pathtarget();
4416  non_group_cols = NIL;
4417 
4418  i = 0;
4419  foreach(lc, grouping_target->exprs)
4420  {
4421  Expr *expr = (Expr *) lfirst(lc);
4422  Index sgref = get_pathtarget_sortgroupref(grouping_target, i);
4423 
4424  if (sgref && parse->groupClause &&
4426  {
4427  /*
4428  * It's a grouping column, so add it to the partial_target as-is.
4429  * (This allows the upper agg step to repeat the grouping calcs.)
4430  */
4431  add_column_to_pathtarget(partial_target, expr, sgref);
4432  }
4433  else
4434  {
4435  /*
4436  * Non-grouping column, so just remember the expression for later
4437  * call to pull_var_clause.
4438  */
4439  non_group_cols = lappend(non_group_cols, expr);
4440  }
4441 
4442  i++;
4443  }
4444 
4445  /*
4446  * If there's a HAVING clause, we'll need the Vars/Aggrefs it uses, too.
4447  */
4448  if (parse->havingQual)
4449  non_group_cols = lappend(non_group_cols, parse->havingQual);
4450 
4451  /*
4452  * Pull out all the Vars, PlaceHolderVars, and Aggrefs mentioned in
4453  * non-group cols (plus HAVING), and add them to the partial_target if not
4454  * already present. (An expression used directly as a GROUP BY item will
4455  * be present already.) Note this includes Vars used in resjunk items, so
4456  * we are covering the needs of ORDER BY and window specifications.
4457  */
4458  non_group_exprs = pull_var_clause((Node *) non_group_cols,
4462 
4463  add_new_columns_to_pathtarget(partial_target, non_group_exprs);
4464 
4465  /*
4466  * Adjust Aggrefs to put them in partial mode. At this point all Aggrefs
4467  * are at the top level of the target list, so we can just scan the list
4468  * rather than recursing through the expression trees.
4469  */
4470  foreach(lc, partial_target->exprs)
4471  {
4472  Aggref *aggref = (Aggref *) lfirst(lc);
4473 
4474  if (IsA(aggref, Aggref))
4475  {
4476  Aggref *newaggref;
4477 
4478  /*
4479  * We shouldn't need to copy the substructure of the Aggref node,
4480  * but flat-copy the node itself to avoid damaging other trees.
4481  */
4482  newaggref = makeNode(Aggref);
4483  memcpy(newaggref, aggref, sizeof(Aggref));
4484 
4485  /* For now, assume serialization is required */
4487 
4488  lfirst(lc) = newaggref;
4489  }
4490  }
4491 
4492  /* clean up cruft */
4493  list_free(non_group_exprs);
4494  list_free(non_group_cols);
4495 
4496  /* XXX this causes some redundant cost calculation ... */
4497  return set_pathtarget_cost_width(root, partial_target);
4498 }
PathTarget * create_empty_pathtarget(void)
Definition: tlist.c:653
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
Query * parse
Definition: relation.h:152
PathTarget * set_pathtarget_cost_width(PlannerInfo *root, PathTarget *target)
Definition: costsize.c:4702
void add_column_to_pathtarget(PathTarget *target, Expr *expr, Index sortgroupref)
Definition: tlist.c:667
void mark_partial_aggref(Aggref *agg, AggSplit aggsplit)
Definition: planner.c:4507
Definition: nodes.h:508
List * pull_var_clause(Node *node, int flags)
Definition: var.c:535
#define PVC_INCLUDE_AGGREGATES
Definition: var.h:20
#define PVC_INCLUDE_PLACEHOLDERS
Definition: var.h:24
#define PVC_RECURSE_WINDOWFUNCS
Definition: var.h:23
#define get_pathtarget_sortgroupref(target, colno)
Definition: relation.h:831
List * lappend(List *list, void *datum)
Definition: list.c:128
List * exprs
Definition: relation.h:824
SortGroupClause * get_sortgroupref_clause_noerr(Index sortref, List *clauses)
Definition: tlist.c:446
unsigned int Index
Definition: c.h:361
#define makeNode(_type_)
Definition: nodes.h:556
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
List * groupClause
Definition: parsenodes.h:137
void list_free(List *list)
Definition: list.c:1133
int i
Node * havingQual
Definition: parsenodes.h:141
Definition: pg_list.h:45
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:651
void add_new_columns_to_pathtarget(PathTarget *target, List *exprs)
Definition: tlist.c:714
static List * make_pathkeys_for_window ( PlannerInfo root,
WindowClause wc,
List tlist 
)
static

Definition at line 4792 of file planner.c.

References ereport, errcode(), errdetail(), errmsg(), ERROR, grouping_is_sortable(), list_concat(), list_copy(), list_free(), make_pathkeys_for_sortclauses(), WindowClause::orderClause, and WindowClause::partitionClause.

Referenced by create_one_window_path(), and standard_qp_callback().

4794 {
4795  List *window_pathkeys;
4796  List *window_sortclauses;
4797 
4798  /* Throw error if can't sort */
4800  ereport(ERROR,
4801  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4802  errmsg("could not implement window PARTITION BY"),
4803  errdetail("Window partitioning columns must be of sortable datatypes.")));
4805  ereport(ERROR,
4806  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4807  errmsg("could not implement window ORDER BY"),
4808  errdetail("Window ordering columns must be of sortable datatypes.")));
4809 
4810  /* Okay, make the combined pathkeys */
4811  window_sortclauses = list_concat(list_copy(wc->partitionClause),
4812  list_copy(wc->orderClause));
4813  window_pathkeys = make_pathkeys_for_sortclauses(root,
4814  window_sortclauses,
4815  tlist);
4816  list_free(window_sortclauses);
4817  return window_pathkeys;
4818 }
List * make_pathkeys_for_sortclauses(PlannerInfo *root, List *sortclauses, List *tlist)
Definition: pathkeys.c:838
List * list_copy(const List *oldlist)
Definition: list.c:1160
int errcode(int sqlerrcode)
Definition: elog.c:575
List * list_concat(List *list1, List *list2)
Definition: list.c:321
#define ERROR
Definition: elog.h:43
List * partitionClause
Definition: parsenodes.h:1195
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ereport(elevel, rest)
Definition: elog.h:122
List * orderClause
Definition: parsenodes.h:1196
int errmsg(const char *fmt,...)
Definition: elog.c:797
void list_free(List *list)
Definition: list.c:1133
bool grouping_is_sortable(List *groupClause)
Definition: tlist.c:518
Definition: pg_list.h:45
static PathTarget * make_sort_input_target ( PlannerInfo root,
PathTarget final_target,
bool have_postponed_srfs 
)
static

Definition at line 4887 of file planner.c.

References add_column_to_pathtarget(), add_new_columns_to_pathtarget(), Assert, contain_volatile_functions(), cost_qual_eval_node(), cpu_operator_cost, create_empty_pathtarget(), expression_returns_set(), PathTarget::exprs, get_pathtarget_sortgroupref, Query::hasTargetSRFs, i, lappend(), lfirst, Query::limitCount, list_free(), list_length(), NIL, palloc0(), parse(), PlannerInfo::parse, QualCost::per_tuple, pull_var_clause(), PVC_INCLUDE_AGGREGATES, PVC_INCLUDE_PLACEHOLDERS, PVC_INCLUDE_WINDOWFUNCS, set_pathtarget_cost_width(), Query::sortClause, and PlannerInfo::tuple_fraction.

Referenced by grouping_planner().

4890 {
4891  Query *parse = root->parse;
4892  PathTarget *input_target;
4893  int ncols;
4894  bool *col_is_srf;
4895  bool *postpone_col;
4896  bool have_srf;
4897  bool have_volatile;
4898  bool have_expensive;
4899  bool have_srf_sortcols;
4900  bool postpone_srfs;
4901  List *postponable_cols;
4902  List *postponable_vars;
4903  int i;
4904  ListCell *lc;
4905 
4906  /* Shouldn't get here unless query has ORDER BY */
4907  Assert(parse->sortClause);
4908 
4909  *have_postponed_srfs = false; /* default result */
4910 
4911  /* Inspect tlist and collect per-column information */
4912  ncols = list_length(final_target->exprs);
4913  col_is_srf = (bool *) palloc0(ncols * sizeof(bool));
4914  postpone_col = (bool *) palloc0(ncols * sizeof(bool));
4915  have_srf = have_volatile = have_expensive = have_srf_sortcols = false;
4916 
4917  i = 0;
4918  foreach(lc, final_target->exprs)
4919  {
4920  Expr *expr = (Expr *) lfirst(lc);
4921 
4922  /*
4923  * If the column has a sortgroupref, assume it has to be evaluated
4924  * before sorting. Generally such columns would be ORDER BY, GROUP
4925  * BY, etc targets. One exception is columns that were removed from
4926  * GROUP BY by remove_useless_groupby_columns() ... but those would
4927  * only be Vars anyway. There don't seem to be any cases where it
4928  * would be worth the trouble to double-check.
4929  */
4930  if (get_pathtarget_sortgroupref(final_target, i) == 0)
4931  {
4932  /*
4933  * Check for SRF or volatile functions. Check the SRF case first
4934  * because we must know whether we have any postponed SRFs.
4935  */
4936  if (parse->hasTargetSRFs &&
4937  expression_returns_set((Node *) expr))
4938  {
4939  /* We'll decide below whether these are postponable */
4940  col_is_srf[i] = true;
4941  have_srf = true;
4942  }
4943  else if (contain_volatile_functions((Node *) expr))
4944  {
4945  /* Unconditionally postpone */
4946  postpone_col[i] = true;
4947  have_volatile = true;
4948  }
4949  else
4950  {
4951  /*
4952  * Else check the cost. XXX it's annoying to have to do this
4953  * when set_pathtarget_cost_width() just did it. Refactor to
4954  * allow sharing the work?
4955  */
4956  QualCost cost;
4957 
4958  cost_qual_eval_node(&cost, (Node *) expr, root);
4959 
4960  /*
4961  * We arbitrarily define "expensive" as "more than 10X
4962  * cpu_operator_cost". Note this will take in any PL function
4963  * with default cost.
4964  */
4965  if (cost.per_tuple > 10 * cpu_operator_cost)
4966  {
4967  postpone_col[i] = true;
4968  have_expensive = true;
4969  }
4970  }
4971  }
4972  else
4973  {
4974  /* For sortgroupref cols, just check if any contain SRFs */
4975  if (!have_srf_sortcols &&
4976  parse->hasTargetSRFs &&
4977  expression_returns_set((Node *) expr))
4978  have_srf_sortcols = true;
4979  }
4980 
4981  i++;
4982  }
4983 
4984  /*
4985  * We can postpone SRFs if we have some but none are in sortgroupref cols.
4986  */
4987  postpone_srfs = (have_srf && !have_srf_sortcols);
4988 
4989  /*
4990  * If we don't need a post-sort projection, just return final_target.
4991  */
4992  if (!(postpone_srfs || have_volatile ||
4993  (have_expensive &&
4994  (parse->limitCount || root->tuple_fraction > 0))))
4995  return final_target;
4996 
4997  /*
4998  * Report whether the post-sort projection will contain set-returning
4999  * functions. This is important because it affects whether the Sort can
5000  * rely on the query's LIMIT (if any) to bound the number of rows it needs
5001  * to return.
5002  */
5003  *have_postponed_srfs = postpone_srfs;
5004 
5005  /*
5006  * Construct the sort-input target, taking all non-postponable columns and
5007  * then adding Vars, PlaceHolderVars, Aggrefs, and WindowFuncs found in
5008  * the postponable ones.
5009  */
5010  input_target = create_empty_pathtarget();
5011  postponable_cols = NIL;
5012 
5013  i = 0;
5014  foreach(lc, final_target->exprs)
5015  {
5016  Expr *expr = (Expr *) lfirst(lc);
5017 
5018  if (postpone_col[i] || (postpone_srfs && col_is_srf[i]))
5019  postponable_cols = lappend(postponable_cols, expr);
5020  else
5021  add_column_to_pathtarget(input_target, expr,
5022  get_pathtarget_sortgroupref(final_target, i));
5023 
5024  i++;
5025  }
5026 
5027  /*
5028  * Pull out all the Vars, Aggrefs, and WindowFuncs mentioned in
5029  * postponable columns, and add them to the sort-input target if not
5030  * already present. (Some might be there already.) We mustn't
5031  * deconstruct Aggrefs or WindowFuncs here, since the projection node
5032  * would be unable to recompute them.
5033  */
5034  postponable_vars = pull_var_clause((Node *) postponable_cols,
5038  add_new_columns_to_pathtarget(input_target, postponable_vars);
5039 
5040  /* clean up cruft */
5041  list_free(postponable_vars);
5042  list_free(postponable_cols);
5043 
5044  /* XXX this represents even more redundant cost calculation ... */
5045  return set_pathtarget_cost_width(root, input_target);
5046 }
void cost_qual_eval_node(QualCost *cost, Node *qual, PlannerInfo *root)
Definition: costsize.c:3225
PathTarget * create_empty_pathtarget(void)
Definition: tlist.c:653
#define NIL
Definition: pg_list.h:69
Query * parse
Definition: relation.h:152
List * sortClause
Definition: parsenodes.h:147
PathTarget * set_pathtarget_cost_width(PlannerInfo *root, PathTarget *target)
Definition: costsize.c:4702
void add_column_to_pathtarget(PathTarget *target, Expr *expr, Index sortgroupref)
Definition: tlist.c:667
bool expression_returns_set(Node *clause)
Definition: nodeFuncs.c:667
Definition: nodes.h:508
List * pull_var_clause(Node *node, int flags)
Definition: var.c:535
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:950
#define PVC_INCLUDE_AGGREGATES
Definition: var.h:20
#define PVC_INCLUDE_PLACEHOLDERS
Definition: var.h:24
Cost per_tuple
Definition: relation.h:46
double tuple_fraction
Definition: relation.h:286
Node * limitCount
Definition: parsenodes.h:150
double cpu_operator_cost
Definition: costsize.c:108
#define get_pathtarget_sortgroupref(target, colno)
Definition: relation.h:831
List * lappend(List *list, void *datum)
Definition: list.c:128
List * exprs
Definition: relation.h:824
void * palloc0(Size size)
Definition: mcxt.c:920
#define PVC_INCLUDE_WINDOWFUNCS
Definition: var.h:22
bool hasTargetSRFs
Definition: parsenodes.h:118
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
void list_free(List *list)
Definition: list.c:1133
int i
Definition: pg_list.h:45
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:651
void add_new_columns_to_pathtarget(PathTarget *target, List *exprs)
Definition: tlist.c:714
static PathTarget * make_window_input_target ( PlannerInfo root,
PathTarget final_target,
List activeWindows 
)
static

Definition at line 4672 of file planner.c.

References add_column_to_pathtarget(), add_new_columns_to_pathtarget(), Assert, bms_add_member(), bms_is_member(), create_empty_pathtarget(), PathTarget::exprs, get_pathtarget_sortgroupref, Query::groupClause, Query::hasWindowFuncs, i, lappend(), lfirst, list_free(), NIL, NULL, WindowClause::orderClause, parse(), PlannerInfo::parse, WindowClause::partitionClause, pull_var_clause(), PVC_INCLUDE_AGGREGATES, PVC_INCLUDE_PLACEHOLDERS, PVC_RECURSE_WINDOWFUNCS, set_pathtarget_cost_width(), and SortGroupClause::tleSortGroupRef.

Referenced by grouping_planner().

4675 {
4676  Query *parse = root->parse;
4677  PathTarget *input_target;
4678  Bitmapset *sgrefs;
4679  List *flattenable_cols;
4680  List *flattenable_vars;
4681  int i;
4682  ListCell *lc;
4683 
4684  Assert(parse->hasWindowFuncs);
4685 
4686  /*
4687  * Collect the sortgroupref numbers of window PARTITION/ORDER BY clauses
4688  * into a bitmapset for convenient reference below.
4689  */
4690  sgrefs = NULL;
4691  foreach(lc, activeWindows)
4692  {
4693  WindowClause *wc = (WindowClause *) lfirst(lc);
4694  ListCell *lc2;
4695 
4696  foreach(lc2, wc->partitionClause)
4697  {
4698  SortGroupClause *sortcl = (SortGroupClause *) lfirst(lc2);
4699 
4700  sgrefs = bms_add_member(sgrefs, sortcl->tleSortGroupRef);
4701  }
4702  foreach(lc2, wc->orderClause)
4703  {
4704  SortGroupClause *sortcl = (SortGroupClause *) lfirst(lc2);
4705 
4706  sgrefs = bms_add_member(sgrefs, sortcl->tleSortGroupRef);
4707  }
4708  }
4709 
4710  /* Add in sortgroupref numbers of GROUP BY clauses, too */
4711  foreach(lc, parse->groupClause)
4712  {
4713  SortGroupClause *grpcl = (SortGroupClause *) lfirst(lc);
4714 
4715  sgrefs = bms_add_member(sgrefs, grpcl->tleSortGroupRef);
4716  }
4717 
4718  /*
4719  * Construct a target containing all the non-flattenable targetlist items,
4720  * and save aside the others for a moment.
4721  */
4722  input_target = create_empty_pathtarget();
4723  flattenable_cols = NIL;
4724 
4725  i = 0;
4726  foreach(lc, final_target->exprs)
4727  {
4728  Expr *expr = (Expr *) lfirst(lc);
4729  Index sgref = get_pathtarget_sortgroupref(final_target, i);
4730 
4731  /*
4732  * Don't want to deconstruct window clauses or GROUP BY items. (Note
4733  * that such items can't contain window functions, so it's okay to
4734  * compute them below the WindowAgg nodes.)
4735  */
4736  if (sgref != 0 && bms_is_member(sgref, sgrefs))
4737  {
4738  /*
4739  * Don't want to deconstruct this value, so add it to the input
4740  * target as-is.
4741  */
4742  add_column_to_pathtarget(input_target, expr, sgref);
4743  }
4744  else
4745  {
4746  /*
4747  * Column is to be flattened, so just remember the expression for
4748  * later call to pull_var_clause.
4749  */
4750  flattenable_cols = lappend(flattenable_cols, expr);
4751  }
4752 
4753  i++;
4754  }
4755 
4756  /*
4757  * Pull out all the Vars and Aggrefs mentioned in flattenable columns, and
4758  * add them to the input target if not already present. (Some might be
4759  * there already because they're used directly as window/group clauses.)
4760  *
4761  * Note: it's essential to use PVC_INCLUDE_AGGREGATES here, so that any
4762  * Aggrefs are placed in the Agg node's tlist and not left to be computed
4763  * at higher levels. On the other hand, we should recurse into
4764  * WindowFuncs to make sure their input expressions are available.
4765  */
4766  flattenable_vars = pull_var_clause((Node *) flattenable_cols,
4770  add_new_columns_to_pathtarget(input_target, flattenable_vars);
4771 
4772  /* clean up cruft */
4773  list_free(flattenable_vars);
4774  list_free(flattenable_cols);
4775 
4776  /* XXX this causes some redundant cost calculation ... */
4777  return set_pathtarget_cost_width(root, input_target);
4778 }
PathTarget * create_empty_pathtarget(void)
Definition: tlist.c:653
#define NIL
Definition: pg_list.h:69
Query * parse
Definition: relation.h:152
PathTarget * set_pathtarget_cost_width(PlannerInfo *root, PathTarget *target)
Definition: costsize.c:4702
void add_column_to_pathtarget(PathTarget *target, Expr *expr, Index sortgroupref)
Definition: tlist.c:667
Index tleSortGroupRef
Definition: parsenodes.h:1102
Definition: nodes.h:508
List * pull_var_clause(Node *node, int flags)
Definition: var.c:535
#define PVC_INCLUDE_AGGREGATES
Definition: var.h:20
#define PVC_INCLUDE_PLACEHOLDERS
Definition: var.h:24
List * partitionClause
Definition: parsenodes.h:1195
#define PVC_RECURSE_WINDOWFUNCS
Definition: var.h:23
#define get_pathtarget_sortgroupref(target, colno)
Definition: relation.h:831
List * lappend(List *list, void *datum)
Definition: list.c:128
List * exprs
Definition: relation.h:824
unsigned int Index
Definition: c.h:361
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
bool hasWindowFuncs
Definition: parsenodes.h:117
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:668
List * orderClause
Definition: parsenodes.h:1196
List * groupClause
Definition: parsenodes.h:137
void list_free(List *list)
Definition: list.c:1133
int i
Definition: pg_list.h:45
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:419
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:651
void add_new_columns_to_pathtarget(PathTarget *target, List *exprs)
Definition: tlist.c:714
void mark_partial_aggref ( Aggref agg,
AggSplit  aggsplit 
)

Definition at line 4507 of file planner.c.

References Aggref::aggsplit, AGGSPLIT_SIMPLE, Aggref::aggtranstype, Aggref::aggtype, Assert, BYTEAOID, DO_AGGSPLIT_SERIALIZE, DO_AGGSPLIT_SKIPFINAL, INTERNALOID, and OidIsValid.

Referenced by convert_combining_aggrefs(), and make_partial_grouping_target().

4508 {
4509  /* aggtranstype should be computed by this point */
4511  /* ... but aggsplit should still be as the parser left it */
4512  Assert(agg->aggsplit == AGGSPLIT_SIMPLE);
4513 
4514  /* Mark the Aggref with the intended partial-aggregation mode */
4515  agg->aggsplit = aggsplit;
4516 
4517  /*
4518  * Adjust result type if needed. Normally, a partial aggregate returns
4519  * the aggregate's transition type; but if that's INTERNAL and we're
4520  * serializing, it returns BYTEA instead.
4521  */
4522  if (DO_AGGSPLIT_SKIPFINAL(aggsplit))
4523  {
4524  if (agg->aggtranstype == INTERNALOID && DO_AGGSPLIT_SERIALIZE(aggsplit))
4525  agg->aggtype = BYTEAOID;
4526  else
4527  agg->aggtype = agg->aggtranstype;
4528  }
4529 }
#define OidIsValid(objectId)
Definition: c.h:533
#define DO_AGGSPLIT_SERIALIZE(as)
Definition: nodes.h:761
#define INTERNALOID
Definition: pg_type.h:686
#define Assert(condition)
Definition: c.h:670
AggSplit aggsplit
Definition: primnodes.h:288
#define DO_AGGSPLIT_SKIPFINAL(as)
Definition: nodes.h:760
#define BYTEAOID
Definition: pg_type.h:292
Oid aggtranstype
Definition: primnodes.h:276
Oid aggtype
Definition: primnodes.h:273
bool plan_cluster_use_sort ( Oid  tableOid,
Oid  indexOid 
)

Definition at line 5240 of file planner.c.

References build_simple_rel(), CMD_SELECT, Query::commandType, cost_qual_eval(), cost_sort(), create_index_path(), create_seqscan_path(), CurrentMemoryContext, enable_indexscan, ForwardScanDirection, get_relation_data_width(), PlannerInfo::glob, RelOptInfo::indexlist, IndexOptInfo::indexoid, IndexOptInfo::indexprs, RangeTblEntry::inFromCl, RangeTblEntry::inh, RangeTblEntry::lateral, lfirst, list_make1, maintenance_work_mem, makeNode, NIL, NULL, RelOptInfo::pages, PlannerInfo::parse, IndexPath::path, QualCost::per_tuple, PlannerInfo::planner_cxt, PlannerInfo::query_level, RangeTblEntry::relid, RangeTblEntry::relkind, RELKIND_RELATION, RELOPT_BASEREL, RelOptInfo::reltarget, RelOptInfo::rows, Query::rtable, RTE_RELATION, RangeTblEntry::rtekind, setup_simple_rel_arrays(), QualCost::startup, Path::total_cost, PlannerInfo::total_table_pages, RelOptInfo::tuples, PathTarget::width, and PlannerInfo::wt_param_id.

Referenced by copy_heap_data().

5241 {
5242  PlannerInfo *root;
5243  Query *query;
5244  PlannerGlobal *glob;
5245  RangeTblEntry *rte;
5246  RelOptInfo *rel;
5247  IndexOptInfo *indexInfo;
5248  QualCost indexExprCost;
5249  Cost comparisonCost;
5250  Path *seqScanPath;
5251  Path seqScanAndSortPath;
5252  IndexPath *indexScanPath;
5253  ListCell *lc;
5254 
5255  /* We can short-circuit the cost comparison if indexscans are disabled */
5256  if (!enable_indexscan)
5257  return true; /* use sort */
5258 
5259  /* Set up mostly-dummy planner state */
5260  query = makeNode(Query);
5261  query->commandType = CMD_SELECT;
5262 
5263  glob = makeNode(PlannerGlobal);
5264 
5265  root = makeNode(PlannerInfo);
5266  root->parse = query;
5267  root->glob = glob;
5268  root->query_level = 1;
5270  root->wt_param_id = -1;
5271 
5272  /* Build a minimal RTE for the rel */
5273  rte = makeNode(RangeTblEntry);
5274  rte->rtekind = RTE_RELATION;
5275  rte->relid = tableOid;
5276  rte->relkind = RELKIND_RELATION; /* Don't be too picky. */
5277  rte->lateral = false;
5278  rte->inh = false;
5279  rte->inFromCl = true;
5280  query->rtable = list_make1(rte);
5281 
5282  /* Set up RTE/RelOptInfo arrays */
5284 
5285  /* Build RelOptInfo */
5286  rel = build_simple_rel(root, 1, RELOPT_BASEREL);
5287 
5288  /* Locate IndexOptInfo for the target index */
5289  indexInfo = NULL;
5290  foreach(lc, rel->indexlist)
5291  {
5292  indexInfo = (IndexOptInfo *) lfirst(lc);
5293  if (indexInfo->indexoid == indexOid)
5294  break;
5295  }
5296 
5297  /*
5298  * It's possible that get_relation_info did not generate an IndexOptInfo
5299  * for the desired index; this could happen if it's not yet reached its
5300  * indcheckxmin usability horizon, or if it's a system index and we're
5301  * ignoring system indexes. In such cases we should tell CLUSTER to not
5302  * trust the index contents but use seqscan-and-sort.
5303  */
5304  if (lc == NULL) /* not in the list? */
5305  return true; /* use sort */
5306 
5307  /*
5308  * Rather than doing all the pushups that would be needed to use
5309  * set_baserel_size_estimates, just do a quick hack for rows and width.
5310  */
5311  rel->rows = rel->tuples;
5312  rel->reltarget->width = get_relation_data_width(tableOid, NULL);
5313 
5314  root->total_table_pages = rel->pages;
5315 
5316  /*
5317  * Determine eval cost of the index expressions, if any. We need to
5318  * charge twice that amount for each tuple comparison that happens during
5319  * the sort, since tuplesort.c will have to re-evaluate the index
5320  * expressions each time. (XXX that's pretty inefficient...)
5321  */
5322  cost_qual_eval(&indexExprCost, indexInfo->indexprs, root);
5323  comparisonCost = 2.0 * (indexExprCost.startup + indexExprCost.per_tuple);
5324 
5325  /* Estimate the cost of seq scan + sort */
5326  seqScanPath = create_seqscan_path(root, rel, NULL, 0);
5327  cost_sort(&seqScanAndSortPath, root, NIL,
5328  seqScanPath->total_cost, rel->tuples, rel->reltarget->width,
5329  comparisonCost, maintenance_work_mem, -1.0);
5330 
5331  /* Estimate the cost of index scan */
5332  indexScanPath = create_index_path(root, indexInfo,
5333  NIL, NIL, NIL, NIL, NIL,
5334  ForwardScanDirection, false,
5335  NULL, 1.0, false);
5336 
5337  return (seqScanAndSortPath.total_cost < indexScanPath->path.total_cost);
5338 }
#define NIL
Definition: pg_list.h:69
Query * parse
Definition: relation.h:152
Path path
Definition: relation.h:971
double tuples
Definition: relation.h:529
IndexPath * create_index_path(PlannerInfo *root, IndexOptInfo *index, List *indexclauses, List *indexclausecols, List *indexorderbys, List *indexorderbycols, List *pathkeys, ScanDirection indexscandir, bool indexonly, Relids required_outer, double loop_count, bool partial_path)
Definition: pathnode.c:1008
Cost startup
Definition: relation.h:45
#define list_make1(x1)
Definition: pg_list.h:133
Cost per_tuple
Definition: relation.h:46
int wt_param_id
Definition: relation.h:303
List * rtable
Definition: parsenodes.h:128
void cost_qual_eval(QualCost *cost, List *quals, PlannerInfo *root)
Definition: costsize.c:3199
PlannerGlobal * glob
Definition: relation.h:154
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
double total_table_pages
Definition: relation.h:284
int32 get_relation_data_width(Oid relid, int32 *attr_widths)
Definition: plancat.c:1103
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:1462
List * indexlist
Definition: relation.h:527
double rows
Definition: relation.h:493
RelOptInfo * build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind)
Definition: relnode.c:88
int maintenance_work_mem
Definition: globals.c:113
Cost total_cost
Definition: relation.h:907
CmdType commandType
Definition: parsenodes.h:103
#define makeNode(_type_)
Definition: nodes.h:556
BlockNumber pages
Definition: relation.h:528
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
void setup_simple_rel_arrays(PlannerInfo *root)
Definition: relnode.c:59
Index query_level
Definition: relation.h:156
RTEKind rtekind
Definition: parsenodes.h:882
int width
Definition: relation.h:827
MemoryContext planner_cxt
Definition: relation.h:282
Oid indexoid
Definition: relation.h:588
#define RELKIND_RELATION
Definition: pg_class.h:160
struct PathTarget * reltarget
Definition: relation.h:501
bool enable_indexscan
Definition: costsize.c:119
Path * create_seqscan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer, int parallel_workers)
Definition: pathnode.c:938
Definition: relation.h:888
double Cost
Definition: nodes.h:632
List * indexprs
Definition: relation.h:610
PlannedStmt* planner ( Query parse,
int  cursorOptions,
ParamListInfo  boundParams 
)

Definition at line 174 of file planner.c.

References parse(), planner_hook, and standard_planner().

Referenced by pg_plan_query().

175 {
176  PlannedStmt *result;
177 
178  if (planner_hook)
179  result = (*planner_hook) (parse, cursorOptions, boundParams);
180  else
181  result = standard_planner(parse, cursorOptions, boundParams);
182  return result;
183 }
PlannedStmt * standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
Definition: planner.c:186
planner_hook_type planner_hook
Definition: planner.c:65
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:651
static List * postprocess_setop_tlist ( List new_tlist,
List orig_tlist 
)
static

Definition at line 4542 of file planner.c.

References Assert, elog, ERROR, lfirst, list_head(), lnext, NULL, TargetEntry::resjunk, TargetEntry::resno, and TargetEntry::ressortgroupref.

Referenced by grouping_planner().

4543 {
4544  ListCell *l;
4545  ListCell *orig_tlist_item = list_head(orig_tlist);
4546 
4547  foreach(l, new_tlist)
4548  {
4549  TargetEntry *new_tle = (TargetEntry *) lfirst(l);
4550  TargetEntry *orig_tle;
4551 
4552  /* ignore resjunk columns in setop result */
4553  if (new_tle->resjunk)
4554  continue;
4555 
4556  Assert(orig_tlist_item != NULL);
4557  orig_tle = (TargetEntry *) lfirst(orig_tlist_item);
4558  orig_tlist_item = lnext(orig_tlist_item);
4559  if (orig_tle->resjunk) /* should not happen */
4560  elog(ERROR, "resjunk output columns are not implemented");
4561  Assert(new_tle->resno == orig_tle->resno);
4562  new_tle->ressortgroupref = orig_tle->ressortgroupref;
4563  }
4564  if (orig_tlist_item != NULL)
4565  elog(ERROR, "resjunk output columns are not implemented");
4566  return new_tlist;
4567 }
bool resjunk
Definition: primnodes.h:1337
#define ERROR
Definition: elog.h:43
AttrNumber resno
Definition: primnodes.h:1331
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define lnext(lc)
Definition: pg_list.h:105
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
Index ressortgroupref
Definition: primnodes.h:1333
#define elog
Definition: elog.h:219
static Node * preprocess_expression ( PlannerInfo root,
Node expr,
int  kind 
)
static

Definition at line 826 of file planner.c.

References canonicalize_qual(), eval_const_expressions(), EXPRKIND_QUAL, EXPRKIND_RTFUNC, EXPRKIND_TABLESAMPLE, EXPRKIND_VALUES, flatten_join_alias_vars(), PlannerInfo::hasJoinRTEs, Query::hasSubLinks, make_ands_implicit(), NULL, PlannerInfo::parse, pprint(), PlannerInfo::query_level, SS_process_sublinks(), and SS_replace_correlation_vars().

Referenced by preprocess_phv_expression(), preprocess_qual_conditions(), and subquery_planner().

827 {
828  /*
829  * Fall out quickly if expression is empty. This occurs often enough to
830  * be worth checking. Note that null->null is the correct conversion for
831  * implicit-AND result format, too.
832  */
833  if (expr == NULL)
834  return NULL;
835 
836  /*
837  * If the query has any join RTEs, replace join alias variables with
838  * base-relation variables. We must do this before sublink processing,
839  * else sublinks expanded out from join aliases would not get processed.
840  * We can skip it in non-lateral RTE functions, VALUES lists, and
841  * TABLESAMPLE clauses, however, since they can't contain any Vars of the
842  * current query level.
843  */
844  if (root->hasJoinRTEs &&
845  !(kind == EXPRKIND_RTFUNC ||
846  kind == EXPRKIND_VALUES ||
847  kind == EXPRKIND_TABLESAMPLE))
848  expr = flatten_join_alias_vars(root, expr);
849 
850  /*
851  * Simplify constant expressions.
852  *
853  * Note: an essential effect of this is to convert named-argument function
854  * calls to positional notation and insert the current actual values of
855  * any default arguments for functions. To ensure that happens, we *must*
856  * process all expressions here. Previous PG versions sometimes skipped
857  * const-simplification if it didn't seem worth the trouble, but we can't
858  * do that anymore.
859  *
860  * Note: this also flattens nested AND and OR expressions into N-argument
861  * form. All processing of a qual expression after this point must be
862  * careful to maintain AND/OR flatness --- that is, do not generate a tree
863  * with AND directly under AND, nor OR directly under OR.
864  */
865  expr = eval_const_expressions(root, expr);
866 
867  /*
868  * If it's a qual or havingQual, canonicalize it.
869  */
870  if (kind == EXPRKIND_QUAL)
871  {
872  expr = (Node *) canonicalize_qual((Expr *) expr);
873 
874 #ifdef OPTIMIZER_DEBUG
875  printf("After canonicalize_qual()\n");
876  pprint(expr);
877 #endif
878  }
879 
880  /* Expand SubLinks to SubPlans */
881  if (root->parse->hasSubLinks)
882  expr = SS_process_sublinks(root, expr, (kind == EXPRKIND_QUAL));
883 
884  /*
885  * XXX do not insert anything here unless you have grokked the comments in
886  * SS_replace_correlation_vars ...
887  */
888 
889  /* Replace uplevel vars with Param nodes (this IS possible in VALUES) */
890  if (root->query_level > 1)
891  expr = SS_replace_correlation_vars(root, expr);
892 
893  /*
894  * If it's a qual or havingQual, convert it to implicit-AND format. (We
895  * don't want to do this before eval_const_expressions, since the latter
896  * would be unable to simplify a top-level AND correctly. Also,
897  * SS_process_sublinks expects explicit-AND format.)
898  */
899  if (kind == EXPRKIND_QUAL)
900  expr = (Node *) make_ands_implicit((Expr *) expr);
901 
902  return expr;
903 }
Query * parse
Definition: relation.h:152
bool hasJoinRTEs
Definition: relation.h:294
#define EXPRKIND_QUAL
Definition: planner.c:72
#define EXPRKIND_RTFUNC
Definition: planner.c:74
Definition: nodes.h:508
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2366
Node * SS_process_sublinks(PlannerInfo *root, Node *expr, bool isQual)
Definition: subselect.c:1944
List * make_ands_implicit(Expr *clause)
Definition: clauses.c:377
Node * flatten_join_alias_vars(PlannerInfo *root, Node *node)
Definition: var.c:670
void pprint(const void *obj)
Definition: print.c:53
Expr * canonicalize_qual(Expr *qual)
Definition: prepqual.c:286
#define NULL
Definition: c.h:226
Node * SS_replace_correlation_vars(PlannerInfo *root, Node *expr)
Definition: subselect.c:1899
Index query_level
Definition: relation.h:156
bool hasSubLinks
Definition: parsenodes.h:119
#define EXPRKIND_TABLESAMPLE
Definition: planner.c:81
#define EXPRKIND_VALUES
Definition: planner.c:76
static List * preprocess_groupclause ( PlannerInfo root,
List force 
)
static

Definition at line 2681 of file planner.c.

References Assert, equal(), get_sortgroupref_clause(), Query::groupClause, lappend(), lfirst, lfirst_int, list_length(), list_member_ptr(), NIL, NULL, OidIsValid, parse(), PlannerInfo::parse, Query::sortClause, and SortGroupClause::sortop.

Referenced by grouping_planner().

2682 {
2683  Query *parse = root->parse;
2684  List *new_groupclause = NIL;
2685  bool partial_match;
2686  ListCell *sl;
2687  ListCell *gl;
2688 
2689  /* For grouping sets, we need to force the ordering */
2690  if (force)
2691  {
2692  foreach(sl, force)
2693  {
2694  Index ref = lfirst_int(sl);
2696 
2697  new_groupclause = lappend(new_groupclause, cl);
2698  }
2699 
2700  return new_groupclause;
2701  }
2702 
2703  /* If no ORDER BY, nothing useful to do here */
2704  if (parse->sortClause == NIL)
2705  return parse->groupClause;
2706 
2707  /*
2708  * Scan the ORDER BY clause and construct a list of matching GROUP BY
2709  * items, but only as far as we can make a matching prefix.
2710  *
2711  * This code assumes that the sortClause contains no duplicate items.
2712  */
2713  foreach(sl, parse->sortClause)
2714  {
2715  SortGroupClause *sc = (SortGroupClause *) lfirst(sl);
2716 
2717  foreach(gl, parse->groupClause)
2718  {
2719  SortGroupClause *gc = (SortGroupClause *) lfirst(gl);
2720 
2721  if (equal(gc, sc))
2722  {
2723  new_groupclause = lappend(new_groupclause, gc);
2724  break;
2725  }
2726  }
2727  if (gl == NULL)
2728  break; /* no match, so stop scanning */
2729  }
2730 
2731  /* Did we match all of the ORDER BY list, or just some of it? */
2732  partial_match = (sl != NULL);
2733 
2734  /* If no match at all, no point in reordering GROUP BY */
2735  if (new_groupclause == NIL)
2736  return parse->groupClause;
2737 
2738  /*
2739  * Add any remaining GROUP BY items to the new list, but only if we were
2740  * able to make a complete match. In other words, we only rearrange the
2741  * GROUP BY list if the result is that one list is a prefix of the other
2742  * --- otherwise there's no possibility of a common sort. Also, give up
2743  * if there are any non-sortable GROUP BY items, since then there's no
2744  * hope anyway.
2745  */
2746  foreach(gl, parse->groupClause)
2747  {
2748  SortGroupClause *gc = (SortGroupClause *) lfirst(gl);
2749 
2750  if (list_member_ptr(new_groupclause, gc))
2751  continue; /* it matched an ORDER BY item */
2752  if (partial_match)
2753  return parse->groupClause; /* give up, no common sort possible */
2754  if (!OidIsValid(gc->sortop))
2755  return parse->groupClause; /* give up, GROUP BY can't be sorted */
2756  new_groupclause = lappend(new_groupclause, gc);
2757  }
2758 
2759  /* Success --- install the rearranged GROUP BY list */
2760  Assert(list_length(parse->groupClause) == list_length(new_groupclause));
2761  return new_groupclause;
2762 }
#define NIL
Definition: pg_list.h:69
Query * parse
Definition: relation.h:152
List * sortClause
Definition: parsenodes.h:147
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2870
#define OidIsValid(objectId)
Definition: c.h:533
#define lfirst_int(lc)
Definition: pg_list.h:107
List * lappend(List *list, void *datum)
Definition: list.c:128
unsigned int Index
Definition: c.h:361
bool list_member_ptr(const List *list, const void *datum)
Definition: list.c:465
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
SortGroupClause * get_sortgroupref_clause(Index sortref, List *clauses)
Definition: tlist.c:425
List * groupClause
Definition: parsenodes.h:137
Definition: pg_list.h:45
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:651
static double preprocess_limit ( PlannerInfo root,
double  tuple_fraction,
int64 *  offset_est,
int64 *  count_est 
)
static

Definition at line 2282 of file planner.c.

References Assert, DatumGetInt64, estimate_expression_value(), IsA, Query::limitCount, Query::limitOffset, Min, parse(), and PlannerInfo::parse.

Referenced by grouping_planner().

2284 {
2285  Query *parse = root->parse;
2286  Node *est;
2287  double limit_fraction;
2288 
2289  /* Should not be called unless LIMIT or OFFSET */
2290  Assert(parse->limitCount || parse->limitOffset);
2291 
2292  /*
2293  * Try to obtain the clause values. We use estimate_expression_value
2294  * primarily because it can sometimes do something useful with Params.
2295  */
2296  if (parse->limitCount)
2297  {
2298  est = estimate_expression_value(root, parse->limitCount);
2299  if (est && IsA(est, Const))
2300  {
2301  if (((Const *) est)->constisnull)
2302  {
2303  /* NULL indicates LIMIT ALL, ie, no limit */
2304  *count_est = 0; /* treat as not present */
2305  }
2306  else
2307  {
2308  *count_est = DatumGetInt64(((Const *) est)->constvalue);
2309  if (*count_est <= 0)
2310  *count_est = 1; /* force to at least 1 */
2311  }
2312  }
2313  else
2314  *count_est = -1; /* can't estimate */
2315  }
2316  else
2317  *count_est = 0; /* not present */
2318 
2319  if (parse->limitOffset)
2320  {
2321  est = estimate_expression_value(root, parse->limitOffset);
2322  if (est && IsA(est, Const))
2323  {
2324  if (((Const *) est)->constisnull)
2325  {
2326  /* Treat NULL as no offset; the executor will too */
2327  *offset_est = 0; /* treat as not present */
2328  }
2329  else
2330  {
2331  *offset_est = DatumGetInt64(((Const *) est)->constvalue);
2332  if (*offset_est < 0)
2333  *offset_est = 0; /* treat as not present */
2334  }
2335  }
2336  else
2337  *offset_est = -1; /* can't estimate */
2338  }
2339  else
2340  *offset_est = 0; /* not present */
2341 
2342  if (*count_est != 0)
2343  {
2344  /*
2345  * A LIMIT clause limits the absolute number of tuples returned.
2346  * However, if it's not a constant LIMIT then we have to guess; for
2347  * lack of a better idea, assume 10% of the plan's result is wanted.
2348  */
2349  if (*count_est < 0 || *offset_est < 0)
2350  {
2351  /* LIMIT or OFFSET is an expression ... punt ... */
2352  limit_fraction = 0.10;
2353  }
2354  else
2355  {
2356  /* LIMIT (plus OFFSET, if any) is max number of tuples needed */
2357  limit_fraction = (double) *count_est + (double) *offset_est;
2358  }
2359 
2360  /*
2361  * If we have absolute limits from both caller and LIMIT, use the
2362  * smaller value; likewise if they are both fractional. If one is
2363  * fractional and the other absolute, we can't easily determine which
2364  * is smaller, but we use the heuristic that the absolute will usually
2365  * be smaller.
2366  */
2367  if (tuple_fraction >= 1.0)
2368  {
2369  if (limit_fraction >= 1.0)
2370  {
2371  /* both absolute */
2372  tuple_fraction = Min(tuple_fraction, limit_fraction);
2373  }
2374  else
2375  {
2376  /* caller absolute, limit fractional; use caller's value */
2377  }
2378  }
2379  else if (tuple_fraction > 0.0)
2380  {
2381  if (limit_fraction >= 1.0)
2382  {
2383  /* caller fractional, limit absolute; use limit */
2384  tuple_fraction = limit_fraction;
2385  }
2386  else
2387  {
2388  /* both fractional */
2389  tuple_fraction = Min(tuple_fraction, limit_fraction);
2390  }
2391  }
2392  else
2393  {
2394  /* no info from caller, just use limit */
2395  tuple_fraction = limit_fraction;
2396  }
2397  }
2398  else if (*offset_est != 0 && tuple_fraction > 0.0)
2399  {
2400  /*
2401  * We have an OFFSET but no LIMIT. This acts entirely differently
2402  * from the LIMIT case: here, we need to increase rather than decrease
2403  * the caller's tuple_fraction, because the OFFSET acts to cause more
2404  * tuples to be fetched instead of fewer. This only matters if we got
2405  * a tuple_fraction > 0, however.
2406  *
2407  * As above, use 10% if OFFSET is present but unestimatable.
2408  */
2409  if (*offset_est < 0)
2410  limit_fraction = 0.10;
2411  else
2412  limit_fraction = (double) *offset_est;
2413 
2414  /*
2415  * If we have absolute counts from both caller and OFFSET, add them
2416  * together; likewise if they are both fractional. If one is
2417  * fractional and the other absolute, we want to take the larger, and
2418  * we heuristically assume that's the fractional one.
2419  */
2420  if (tuple_fraction >= 1.0)
2421  {
2422  if (limit_fraction >= 1.0)
2423  {
2424  /* both absolute, so add them together */
2425  tuple_fraction += limit_fraction;
2426  }
2427  else
2428  {
2429  /* caller absolute, limit fractional; use limit */
2430  tuple_fraction = limit_fraction;
2431  }
2432  }
2433  else
2434  {
2435  if (limit_fraction >= 1.0)
2436  {
2437  /* caller fractional, limit absolute; use caller's value */
2438  }
2439  else
2440  {
2441  /* both fractional, so add them together */
2442  tuple_fraction += limit_fraction;
2443  if (tuple_fraction >= 1.0)
2444  tuple_fraction = 0.0; /* assume fetch all */
2445  }
2446  }
2447  }
2448 
2449  return tuple_fraction;
2450 }
Node * limitOffset
Definition: parsenodes.h:149
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
Query * parse
Definition: relation.h:152
Node * estimate_expression_value(PlannerInfo *root, Node *node)
Definition: clauses.c:2399
#define Min(x, y)
Definition: c.h:801
Definition: nodes.h:508
#define DatumGetInt64(X)
Definition: postgres.h:615
Node * limitCount
Definition: parsenodes.h:150
#define Assert(condition)
Definition: c.h:670
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:651
Expr* preprocess_phv_expression ( PlannerInfo root,
Expr expr 
)

Definition at line 955 of file planner.c.

References EXPRKIND_PHV, and preprocess_expression().

Referenced by extract_lateral_references().

956 {
957  return (Expr *) preprocess_expression(root, (Node *) expr, EXPRKIND_PHV);
958 }
Definition: nodes.h:508
static Node * preprocess_expression(PlannerInfo *root, Node *expr, int kind)
Definition: planner.c:826
#define EXPRKIND_PHV
Definition: planner.c:80
static void preprocess_qual_conditions ( PlannerInfo root,
Node jtnode 
)
static

Definition at line 911 of file planner.c.

References elog, ERROR, EXPRKIND_QUAL, FromExpr::fromlist, IsA, JoinExpr::larg, lfirst, nodeTag, NULL, preprocess_expression(), JoinExpr::quals, FromExpr::quals, and JoinExpr::rarg.

Referenced by subquery_planner().

912 {
913  if (jtnode == NULL)
914  return;
915  if (IsA(jtnode, RangeTblRef))
916  {
917  /* nothing to do here */
918  }
919  else if (IsA(jtnode, FromExpr))
920  {
921  FromExpr *f = (FromExpr *) jtnode;
922  ListCell *l;
923 
924  foreach(l, f->fromlist)
926 
928  }
929  else if (IsA(jtnode, JoinExpr))
930  {
931  JoinExpr *j = (JoinExpr *) jtnode;
932 
935 
937  }
938  else
939  elog(ERROR, "unrecognized node type: %d",
940  (int) nodeTag(jtnode));
941 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
#define EXPRKIND_QUAL
Definition: planner.c:72
static Node * preprocess_expression(PlannerInfo *root, Node *expr, int kind)
Definition: planner.c:826
List * fromlist
Definition: primnodes.h:1433
Node * quals
Definition: primnodes.h:1434
Node * larg
Definition: primnodes.h:1413
#define ERROR
Definition: elog.h:43
Node * quals
Definition: primnodes.h:1416
Node * rarg
Definition: primnodes.h:1414
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
#define nodeTag(nodeptr)
Definition: nodes.h:513
static void preprocess_qual_conditions(PlannerInfo *root, Node *jtnode)
Definition: planner.c:911
#define elog
Definition: elog.h:219
static void preprocess_rowmarks ( PlannerInfo root)
static

Definition at line 2105 of file planner.c.

References PlanRowMark::allMarkTypes, Assert, bms_del_member(), bms_is_member(), CheckSelectLocking(), CMD_DELETE, CMD_UPDATE, Query::commandType, get_relids_in_jointree(), PlannerInfo::glob, i, PlanRowMark::isParent, Query::jointree, lappend(), PlannerGlobal::lastRowMarkId, LCS_NONE, lfirst, linitial, LockWaitBlock, makeNode, PlanRowMark::markType, NIL, parse(), PlannerInfo::parse, PlanRowMark::prti, Query::resultRelation, PlanRowMark::rowmarkId, Query::rowMarks, PlannerInfo::rowMarks, rt_fetch, Query::rtable, RTE_RELATION, RangeTblEntry::rtekind, PlanRowMark::rti, RowMarkClause::rti, select_rowmark_type(), PlanRowMark::strength, RowMarkClause::strength, PlanRowMark::waitPolicy, and RowMarkClause::waitPolicy.

Referenced by subquery_planner().

2106 {
2107  Query *parse = root->parse;
2108  Bitmapset *rels;
2109  List *prowmarks;
2110  ListCell *l;
2111  int i;
2112 
2113  if (parse->rowMarks)
2114  {
2115  /*
2116  * We've got trouble if FOR [KEY] UPDATE/SHARE appears inside
2117  * grouping, since grouping renders a reference to individual tuple
2118  * CTIDs invalid. This is also checked at parse time, but that's
2119  * insufficient because of rule substitution, query pullup, etc.
2120  */
2121  CheckSelectLocking(parse, ((RowMarkClause *)
2122  linitial(parse->rowMarks))->strength);
2123  }
2124  else
2125  {
2126  /*
2127  * We only need rowmarks for UPDATE, DELETE, or FOR [KEY]
2128  * UPDATE/SHARE.
2129  */
2130  if (parse->commandType != CMD_UPDATE &&
2131  parse->commandType != CMD_DELETE)
2132  return;
2133  }
2134 
2135  /*
2136  * We need to have rowmarks for all base relations except the target. We
2137  * make a bitmapset of all base rels and then remove the items we don't
2138  * need or have FOR [KEY] UPDATE/SHARE marks for.
2139  */
2140  rels = get_relids_in_jointree((Node *) parse->jointree, false);
2141  if (parse->resultRelation)
2142  rels = bms_del_member(rels, parse->resultRelation);
2143 
2144  /*
2145  * Convert RowMarkClauses to PlanRowMark representation.
2146  */
2147  prowmarks = NIL;
2148  foreach(l, parse->rowMarks)
2149  {
2150  RowMarkClause *rc = (RowMarkClause *) lfirst(l);
2151  RangeTblEntry *rte = rt_fetch(rc->rti, parse->rtable);
2152  PlanRowMark *newrc;
2153 
2154  /*
2155  * Currently, it is syntactically impossible to have FOR UPDATE et al
2156  * applied to an update/delete target rel. If that ever becomes
2157  * possible, we should drop the target from the PlanRowMark list.
2158  */
2159  Assert(rc->rti != parse->resultRelation);
2160 
2161  /*
2162  * Ignore RowMarkClauses for subqueries; they aren't real tables and
2163  * can't support true locking. Subqueries that got flattened into the
2164  * main query should be ignored completely. Any that didn't will get
2165  * ROW_MARK_COPY items in the next loop.
2166  */
2167  if (rte->rtekind != RTE_RELATION)
2168  continue;
2169 
2170  rels = bms_del_member(rels, rc->rti);
2171 
2172  newrc = makeNode(PlanRowMark);
2173  newrc->rti = newrc->prti = rc->rti;
2174  newrc->rowmarkId = ++(root->glob->lastRowMarkId);
2175  newrc->markType = select_rowmark_type(rte, rc->strength);
2176  newrc->allMarkTypes = (1 << newrc->markType);
2177  newrc->strength = rc->strength;
2178  newrc->waitPolicy = rc->waitPolicy;
2179  newrc->isParent = false;
2180 
2181  prowmarks = lappend(prowmarks, newrc);
2182  }
2183 
2184  /*
2185  * Now, add rowmarks for any non-target, non-locked base relations.
2186  */
2187  i = 0;
2188  foreach(l, parse->rtable)
2189  {
2190  RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
2191  PlanRowMark *newrc;
2192 
2193  i++;
2194  if (!bms_is_member(i, rels))
2195  continue;
2196 
2197  newrc = makeNode(PlanRowMark);
2198  newrc->rti = newrc->prti = i;
2199  newrc->rowmarkId = ++(root->glob->lastRowMarkId);
2200  newrc->markType = select_rowmark_type(rte, LCS_NONE);
2201  newrc->allMarkTypes = (1 << newrc->markType);
2202  newrc->strength = LCS_NONE;
2203  newrc->waitPolicy = LockWaitBlock; /* doesn't matter */
2204  newrc->isParent = false;
2205 
2206  prowmarks = lappend(prowmarks, newrc);
2207  }
2208 
2209  root->rowMarks = prowmarks;
2210 }
#define NIL
Definition: pg_list.h:69
List * rowMarks
Definition: relation.h:251
Query * parse
Definition: relation.h:152
RowMarkType markType
Definition: plannodes.h:943
FromExpr * jointree
Definition: parsenodes.h:129
RowMarkType select_rowmark_type(RangeTblEntry *rte, LockClauseStrength strength)
Definition: planner.c:2216
int resultRelation
Definition: parsenodes.h:113
Definition: nodes.h:508
Index prti
Definition: plannodes.h:941
List * rowMarks
Definition: parsenodes.h:152
Index rowmarkId
Definition: plannodes.h:942
LockWaitPolicy waitPolicy
Definition: plannodes.h:946
LockClauseStrength strength
Definition: parsenodes.h:1220
void CheckSelectLocking(Query *qry, LockClauseStrength strength)
Definition: analyze.c:2601
#define linitial(l)
Definition: pg_list.h:110
List * rtable
Definition: parsenodes.h:128
Relids get_relids_in_jointree(Node *jtnode, bool include_joins)
PlannerGlobal * glob
Definition: relation.h:154
int allMarkTypes
Definition: plannodes.h:944
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
List * lappend(List *list, void *datum)
Definition: list.c:128
CmdType commandType
Definition: parsenodes.h:103
Index rti
Definition: plannodes.h:940
#define makeNode(_type_)
Definition: nodes.h:556
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
LockClauseStrength strength
Definition: plannodes.h:945
LockWaitPolicy waitPolicy
Definition: parsenodes.h:1221
RTEKind rtekind
Definition: parsenodes.h:882
Index lastRowMarkId
Definition: relation.h:118
int i
bool isParent
Definition: plannodes.h:947
Bitmapset * bms_del_member(Bitmapset *a, int x)
Definition: bitmapset.c:705
Definition: pg_list.h:45
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:419
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:651