LCOV - code coverage report
Current view: top level - src/backend/optimizer/plan - planner.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 96.7 % 2573 2488
Test Date: 2026-08-01 18:15:37 Functions: 100.0 % 66 66
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 85.6 % 2244 1921

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * planner.c
       4                 :             :  *    The query optimizer external interface.
       5                 :             :  *
       6                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       7                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
       8                 :             :  *
       9                 :             :  *
      10                 :             :  * IDENTIFICATION
      11                 :             :  *    src/backend/optimizer/plan/planner.c
      12                 :             :  *
      13                 :             :  *-------------------------------------------------------------------------
      14                 :             :  */
      15                 :             : 
      16                 :             : #include "postgres.h"
      17                 :             : 
      18                 :             : #include <limits.h>
      19                 :             : #include <math.h>
      20                 :             : 
      21                 :             : #include "access/genam.h"
      22                 :             : #include "access/parallel.h"
      23                 :             : #include "access/sysattr.h"
      24                 :             : #include "access/table.h"
      25                 :             : #include "catalog/pg_aggregate.h"
      26                 :             : #include "catalog/pg_inherits.h"
      27                 :             : #include "catalog/pg_proc.h"
      28                 :             : #include "catalog/pg_type.h"
      29                 :             : #include "executor/executor.h"
      30                 :             : #include "foreign/fdwapi.h"
      31                 :             : #include "jit/jit.h"
      32                 :             : #include "lib/bipartite_match.h"
      33                 :             : #include "lib/knapsack.h"
      34                 :             : #include "miscadmin.h"
      35                 :             : #include "nodes/makefuncs.h"
      36                 :             : #include "nodes/nodeFuncs.h"
      37                 :             : #ifdef OPTIMIZER_DEBUG
      38                 :             : #include "nodes/print.h"
      39                 :             : #endif
      40                 :             : #include "nodes/supportnodes.h"
      41                 :             : #include "optimizer/appendinfo.h"
      42                 :             : #include "optimizer/clauses.h"
      43                 :             : #include "optimizer/cost.h"
      44                 :             : #include "optimizer/optimizer.h"
      45                 :             : #include "optimizer/paramassign.h"
      46                 :             : #include "optimizer/pathnode.h"
      47                 :             : #include "optimizer/paths.h"
      48                 :             : #include "optimizer/plancat.h"
      49                 :             : #include "optimizer/planmain.h"
      50                 :             : #include "optimizer/planner.h"
      51                 :             : #include "optimizer/prep.h"
      52                 :             : #include "optimizer/subselect.h"
      53                 :             : #include "optimizer/tlist.h"
      54                 :             : #include "parser/analyze.h"
      55                 :             : #include "parser/parse_agg.h"
      56                 :             : #include "parser/parse_clause.h"
      57                 :             : #include "parser/parse_relation.h"
      58                 :             : #include "parser/parsetree.h"
      59                 :             : #include "partitioning/partdesc.h"
      60                 :             : #include "rewrite/rewriteManip.h"
      61                 :             : #include "utils/acl.h"
      62                 :             : #include "utils/backend_status.h"
      63                 :             : #include "utils/lsyscache.h"
      64                 :             : #include "utils/rel.h"
      65                 :             : #include "utils/selfuncs.h"
      66                 :             : 
      67                 :             : /* GUC parameters */
      68                 :             : double      cursor_tuple_fraction = DEFAULT_CURSOR_TUPLE_FRACTION;
      69                 :             : int         debug_parallel_query = DEBUG_PARALLEL_OFF;
      70                 :             : bool        parallel_leader_participation = true;
      71                 :             : bool        enable_distinct_reordering = true;
      72                 :             : 
      73                 :             : /* Hook for plugins to get control in planner() */
      74                 :             : planner_hook_type planner_hook = NULL;
      75                 :             : 
      76                 :             : /* Hook for plugins to get control after PlannerGlobal is initialized */
      77                 :             : planner_setup_hook_type planner_setup_hook = NULL;
      78                 :             : 
      79                 :             : /* Hook for plugins to get control before PlannerGlobal is discarded */
      80                 :             : planner_shutdown_hook_type planner_shutdown_hook = NULL;
      81                 :             : 
      82                 :             : /* Hook for plugins to get control when grouping_planner() plans upper rels */
      83                 :             : create_upper_paths_hook_type create_upper_paths_hook = NULL;
      84                 :             : 
      85                 :             : 
      86                 :             : /* Expression kind codes for preprocess_expression */
      87                 :             : #define EXPRKIND_QUAL               0
      88                 :             : #define EXPRKIND_TARGET             1
      89                 :             : #define EXPRKIND_RTFUNC             2
      90                 :             : #define EXPRKIND_RTFUNC_LATERAL     3
      91                 :             : #define EXPRKIND_VALUES             4
      92                 :             : #define EXPRKIND_VALUES_LATERAL     5
      93                 :             : #define EXPRKIND_LIMIT              6
      94                 :             : #define EXPRKIND_APPINFO            7
      95                 :             : #define EXPRKIND_PHV                8
      96                 :             : #define EXPRKIND_TABLESAMPLE        9
      97                 :             : #define EXPRKIND_ARBITER_ELEM       10
      98                 :             : #define EXPRKIND_TABLEFUNC          11
      99                 :             : #define EXPRKIND_TABLEFUNC_LATERAL  12
     100                 :             : #define EXPRKIND_GROUPEXPR          13
     101                 :             : 
     102                 :             : /*
     103                 :             :  * Data specific to grouping sets
     104                 :             :  */
     105                 :             : typedef struct
     106                 :             : {
     107                 :             :     List       *rollups;
     108                 :             :     List       *hash_sets_idx;
     109                 :             :     double      dNumHashGroups;
     110                 :             :     bool        any_hashable;
     111                 :             :     Bitmapset  *unsortable_refs;
     112                 :             :     Bitmapset  *unhashable_refs;
     113                 :             :     List       *unsortable_sets;
     114                 :             :     int        *tleref_to_colnum_map;
     115                 :             : } grouping_sets_data;
     116                 :             : 
     117                 :             : /*
     118                 :             :  * Temporary structure for use during WindowClause reordering in order to be
     119                 :             :  * able to sort WindowClauses on partitioning/ordering prefix.
     120                 :             :  */
     121                 :             : typedef struct
     122                 :             : {
     123                 :             :     WindowClause *wc;
     124                 :             :     List       *uniqueOrder;    /* A List of unique ordering/partitioning
     125                 :             :                                  * clauses per Window */
     126                 :             : } WindowClauseSortData;
     127                 :             : 
     128                 :             : /* Passthrough data for standard_qp_callback */
     129                 :             : typedef struct
     130                 :             : {
     131                 :             :     List       *activeWindows;  /* active windows, if any */
     132                 :             :     grouping_sets_data *gset_data;  /* grouping sets data, if any */
     133                 :             :     SetOperationStmt *setop;    /* parent set operation or NULL if not a
     134                 :             :                                  * subquery belonging to a set operation */
     135                 :             : } standard_qp_extra;
     136                 :             : 
     137                 :             : /*
     138                 :             :  * Context for find_having_conflicts.  This is the callback context passed to
     139                 :             :  * expression_has_grouping_conflict in clauses.c.
     140                 :             :  */
     141                 :             : typedef struct
     142                 :             : {
     143                 :             :     Query      *parse;
     144                 :             :     Index       group_rtindex;
     145                 :             : } having_grouping_ctx;
     146                 :             : 
     147                 :             : /* Local functions */
     148                 :             : static Node *preprocess_expression(PlannerInfo *root, Node *expr, int kind);
     149                 :             : static void preprocess_qual_conditions(PlannerInfo *root, Node *jtnode);
     150                 :             : static Bitmapset *find_having_conflicts(Query *parse, Index group_rtindex);
     151                 :             : static Oid  having_var_grouping_eqop(Var *var, void *context);
     152                 :             : static Oid  group_var_eqop(Query *parse, Var *var);
     153                 :             : static void grouping_planner(PlannerInfo *root, double tuple_fraction,
     154                 :             :                              SetOperationStmt *setops);
     155                 :             : static grouping_sets_data *preprocess_grouping_sets(PlannerInfo *root);
     156                 :             : static List *remap_to_groupclause_idx(List *groupClause, List *gsets,
     157                 :             :                                       int *tleref_to_colnum_map);
     158                 :             : static void preprocess_rowmarks(PlannerInfo *root);
     159                 :             : static double preprocess_limit(PlannerInfo *root,
     160                 :             :                                double tuple_fraction,
     161                 :             :                                int64 *offset_est, int64 *count_est);
     162                 :             : static List *preprocess_groupclause(PlannerInfo *root, List *force);
     163                 :             : static List *extract_rollup_sets(List *groupingSets);
     164                 :             : static List *reorder_grouping_sets(List *groupingSets, List *sortclause);
     165                 :             : static void standard_qp_callback(PlannerInfo *root, void *extra);
     166                 :             : static double get_number_of_groups(PlannerInfo *root,
     167                 :             :                                    double path_rows,
     168                 :             :                                    grouping_sets_data *gd,
     169                 :             :                                    List *target_list);
     170                 :             : static RelOptInfo *create_grouping_paths(PlannerInfo *root,
     171                 :             :                                          RelOptInfo *input_rel,
     172                 :             :                                          PathTarget *target,
     173                 :             :                                          bool target_parallel_safe,
     174                 :             :                                          grouping_sets_data *gd);
     175                 :             : static bool is_degenerate_grouping(PlannerInfo *root);
     176                 :             : static void create_degenerate_grouping_paths(PlannerInfo *root,
     177                 :             :                                              RelOptInfo *input_rel,
     178                 :             :                                              RelOptInfo *grouped_rel);
     179                 :             : static RelOptInfo *make_grouping_rel(PlannerInfo *root, RelOptInfo *input_rel,
     180                 :             :                                      PathTarget *target, bool target_parallel_safe,
     181                 :             :                                      Node *havingQual);
     182                 :             : static void create_ordinary_grouping_paths(PlannerInfo *root,
     183                 :             :                                            RelOptInfo *input_rel,
     184                 :             :                                            RelOptInfo *grouped_rel,
     185                 :             :                                            const AggClauseCosts *agg_costs,
     186                 :             :                                            grouping_sets_data *gd,
     187                 :             :                                            GroupPathExtraData *extra,
     188                 :             :                                            RelOptInfo **partially_grouped_rel_p);
     189                 :             : static void consider_groupingsets_paths(PlannerInfo *root,
     190                 :             :                                         RelOptInfo *grouped_rel,
     191                 :             :                                         Path *path,
     192                 :             :                                         bool is_sorted,
     193                 :             :                                         bool can_hash,
     194                 :             :                                         grouping_sets_data *gd,
     195                 :             :                                         const AggClauseCosts *agg_costs,
     196                 :             :                                         double dNumGroups);
     197                 :             : static RelOptInfo *create_window_paths(PlannerInfo *root,
     198                 :             :                                        RelOptInfo *input_rel,
     199                 :             :                                        PathTarget *input_target,
     200                 :             :                                        PathTarget *output_target,
     201                 :             :                                        bool output_target_parallel_safe,
     202                 :             :                                        WindowFuncLists *wflists,
     203                 :             :                                        List *activeWindows);
     204                 :             : static void create_one_window_path(PlannerInfo *root,
     205                 :             :                                    RelOptInfo *window_rel,
     206                 :             :                                    Path *path,
     207                 :             :                                    PathTarget *input_target,
     208                 :             :                                    PathTarget *output_target,
     209                 :             :                                    WindowFuncLists *wflists,
     210                 :             :                                    List *activeWindows);
     211                 :             : static RelOptInfo *create_distinct_paths(PlannerInfo *root,
     212                 :             :                                          RelOptInfo *input_rel,
     213                 :             :                                          PathTarget *target);
     214                 :             : static void create_partial_distinct_paths(PlannerInfo *root,
     215                 :             :                                           RelOptInfo *input_rel,
     216                 :             :                                           RelOptInfo *final_distinct_rel,
     217                 :             :                                           PathTarget *target);
     218                 :             : static RelOptInfo *create_final_distinct_paths(PlannerInfo *root,
     219                 :             :                                                RelOptInfo *input_rel,
     220                 :             :                                                RelOptInfo *distinct_rel);
     221                 :             : static List *get_useful_pathkeys_for_distinct(PlannerInfo *root,
     222                 :             :                                               List *needed_pathkeys,
     223                 :             :                                               List *path_pathkeys);
     224                 :             : static RelOptInfo *create_ordered_paths(PlannerInfo *root,
     225                 :             :                                         RelOptInfo *input_rel,
     226                 :             :                                         PathTarget *target,
     227                 :             :                                         bool target_parallel_safe,
     228                 :             :                                         double limit_tuples);
     229                 :             : static PathTarget *make_group_input_target(PlannerInfo *root,
     230                 :             :                                            PathTarget *final_target);
     231                 :             : static PathTarget *make_partial_grouping_target(PlannerInfo *root,
     232                 :             :                                                 PathTarget *grouping_target,
     233                 :             :                                                 Node *havingQual);
     234                 :             : static List *postprocess_setop_tlist(List *new_tlist, List *orig_tlist);
     235                 :             : static void optimize_window_clauses(PlannerInfo *root,
     236                 :             :                                     WindowFuncLists *wflists);
     237                 :             : static List *select_active_windows(PlannerInfo *root, WindowFuncLists *wflists);
     238                 :             : static void name_active_windows(List *activeWindows);
     239                 :             : static PathTarget *make_window_input_target(PlannerInfo *root,
     240                 :             :                                             PathTarget *final_target,
     241                 :             :                                             List *activeWindows);
     242                 :             : static List *make_pathkeys_for_window(PlannerInfo *root, WindowClause *wc,
     243                 :             :                                       List *tlist);
     244                 :             : static PathTarget *make_sort_input_target(PlannerInfo *root,
     245                 :             :                                           PathTarget *final_target,
     246                 :             :                                           bool *have_postponed_srfs);
     247                 :             : static void adjust_paths_for_srfs(PlannerInfo *root, RelOptInfo *rel,
     248                 :             :                                   List *targets, List *targets_contain_srfs);
     249                 :             : static void add_paths_to_grouping_rel(PlannerInfo *root, RelOptInfo *input_rel,
     250                 :             :                                       RelOptInfo *grouped_rel,
     251                 :             :                                       RelOptInfo *partially_grouped_rel,
     252                 :             :                                       const AggClauseCosts *agg_costs,
     253                 :             :                                       grouping_sets_data *gd,
     254                 :             :                                       GroupPathExtraData *extra);
     255                 :             : static RelOptInfo *create_partial_grouping_paths(PlannerInfo *root,
     256                 :             :                                                  RelOptInfo *grouped_rel,
     257                 :             :                                                  RelOptInfo *input_rel,
     258                 :             :                                                  grouping_sets_data *gd,
     259                 :             :                                                  GroupPathExtraData *extra,
     260                 :             :                                                  bool force_rel_creation);
     261                 :             : static Path *make_ordered_path(PlannerInfo *root,
     262                 :             :                                RelOptInfo *rel,
     263                 :             :                                Path *path,
     264                 :             :                                Path *cheapest_path,
     265                 :             :                                List *pathkeys,
     266                 :             :                                double limit_tuples);
     267                 :             : static void gather_grouping_paths(PlannerInfo *root, RelOptInfo *rel);
     268                 :             : static bool can_partial_agg(PlannerInfo *root);
     269                 :             : static void apply_scanjoin_target_to_paths(PlannerInfo *root,
     270                 :             :                                            RelOptInfo *rel,
     271                 :             :                                            List *scanjoin_targets,
     272                 :             :                                            List *scanjoin_targets_contain_srfs,
     273                 :             :                                            bool scanjoin_target_parallel_safe,
     274                 :             :                                            bool tlist_same_exprs);
     275                 :             : static void create_partitionwise_grouping_paths(PlannerInfo *root,
     276                 :             :                                                 RelOptInfo *input_rel,
     277                 :             :                                                 RelOptInfo *grouped_rel,
     278                 :             :                                                 RelOptInfo *partially_grouped_rel,
     279                 :             :                                                 const AggClauseCosts *agg_costs,
     280                 :             :                                                 grouping_sets_data *gd,
     281                 :             :                                                 PartitionwiseAggregateType patype,
     282                 :             :                                                 GroupPathExtraData *extra);
     283                 :             : static bool group_by_has_partkey(RelOptInfo *input_rel,
     284                 :             :                                  List *targetList,
     285                 :             :                                  List *groupClause);
     286                 :             : static int  common_prefix_cmp(const void *a, const void *b);
     287                 :             : static List *generate_setop_child_grouplist(SetOperationStmt *op,
     288                 :             :                                             List *targetlist);
     289                 :             : static void create_final_unique_paths(PlannerInfo *root, RelOptInfo *input_rel,
     290                 :             :                                       List *sortPathkeys, List *groupClause,
     291                 :             :                                       SpecialJoinInfo *sjinfo, RelOptInfo *unique_rel);
     292                 :             : static void create_partial_unique_paths(PlannerInfo *root, RelOptInfo *input_rel,
     293                 :             :                                         List *sortPathkeys, List *groupClause,
     294                 :             :                                         SpecialJoinInfo *sjinfo, RelOptInfo *unique_rel);
     295                 :             : 
     296                 :             : 
     297                 :             : /*****************************************************************************
     298                 :             :  *
     299                 :             :  *     Query optimizer entry point
     300                 :             :  *
     301                 :             :  * Inputs:
     302                 :             :  *  parse: an analyzed-and-rewritten query tree for an optimizable statement
     303                 :             :  *  query_string: source text for the query tree (used for error reports)
     304                 :             :  *  cursorOptions: bitmask of CURSOR_OPT_XXX flags, see parsenodes.h
     305                 :             :  *  boundParams: passed-in parameter values, or NULL if none
     306                 :             :  *  es: ExplainState if being called from EXPLAIN, else NULL
     307                 :             :  *
     308                 :             :  * The result is a PlannedStmt tree.
     309                 :             :  *
     310                 :             :  * PARAM_EXTERN Param nodes within the parse tree can be replaced by Consts
     311                 :             :  * using values from boundParams, if those values are marked PARAM_FLAG_CONST.
     312                 :             :  * Parameter values not so marked are still relied on for estimation purposes.
     313                 :             :  *
     314                 :             :  * The ExplainState pointer is not currently used by the core planner, but it
     315                 :             :  * is passed through to some planner hooks so that they can report information
     316                 :             :  * back to EXPLAIN extension hooks.
     317                 :             :  *
     318                 :             :  * To support loadable plugins that monitor or modify planner behavior,
     319                 :             :  * we provide a hook variable that lets a plugin get control before and
     320                 :             :  * after the standard planning process.  The plugin would normally call
     321                 :             :  * standard_planner().
     322                 :             :  *
     323                 :             :  * Note to plugin authors: standard_planner() scribbles on its Query input,
     324                 :             :  * so you'd better copy that data structure if you want to plan more than once.
     325                 :             :  *
     326                 :             :  *****************************************************************************/
     327                 :             : PlannedStmt *
     328                 :      336462 : planner(Query *parse, const char *query_string, int cursorOptions,
     329                 :             :         ParamListInfo boundParams, ExplainState *es)
     330                 :             : {
     331                 :             :     PlannedStmt *result;
     332                 :             : 
     333         [ +  + ]:      336462 :     if (planner_hook)
     334                 :       50915 :         result = (*planner_hook) (parse, query_string, cursorOptions,
     335                 :             :                                   boundParams, es);
     336                 :             :     else
     337                 :      285547 :         result = standard_planner(parse, query_string, cursorOptions,
     338                 :             :                                   boundParams, es);
     339                 :             : 
     340                 :      332381 :     pgstat_report_plan_id(result->planId, false);
     341                 :             : 
     342                 :      332381 :     return result;
     343                 :             : }
     344                 :             : 
     345                 :             : PlannedStmt *
     346                 :      336462 : standard_planner(Query *parse, const char *query_string, int cursorOptions,
     347                 :             :                  ParamListInfo boundParams, ExplainState *es)
     348                 :             : {
     349                 :             :     PlannedStmt *result;
     350                 :             :     PlannerGlobal *glob;
     351                 :             :     double      tuple_fraction;
     352                 :             :     PlannerInfo *root;
     353                 :             :     RelOptInfo *final_rel;
     354                 :             :     Path       *best_path;
     355                 :             :     Plan       *top_plan;
     356                 :             :     ListCell   *lp,
     357                 :             :                *lr,
     358                 :             :                *lc;
     359                 :             : 
     360                 :             :     /*
     361                 :             :      * Set up global state for this planner invocation.  This data is needed
     362                 :             :      * across all levels of sub-Query that might exist in the given command,
     363                 :             :      * so we keep it in a separate struct that's linked to by each per-Query
     364                 :             :      * PlannerInfo.
     365                 :             :      */
     366                 :      336462 :     glob = makeNode(PlannerGlobal);
     367                 :             : 
     368                 :      336462 :     glob->boundParams = boundParams;
     369                 :      336462 :     glob->subplans = NIL;
     370                 :      336462 :     glob->subpaths = NIL;
     371                 :      336462 :     glob->subroots = NIL;
     372                 :      336462 :     glob->rewindPlanIDs = NULL;
     373                 :      336462 :     glob->finalrtable = NIL;
     374                 :      336462 :     glob->allRelids = NULL;
     375                 :      336462 :     glob->prunableRelids = NULL;
     376                 :      336462 :     glob->finalrteperminfos = NIL;
     377                 :      336462 :     glob->finalrowmarks = NIL;
     378                 :      336462 :     glob->resultRelations = NIL;
     379                 :      336462 :     glob->appendRelations = NIL;
     380                 :      336462 :     glob->partPruneInfos = NIL;
     381                 :      336462 :     glob->relationOids = NIL;
     382                 :      336462 :     glob->invalItems = NIL;
     383                 :      336462 :     glob->paramExecTypes = NIL;
     384                 :      336462 :     glob->lastPHId = 0;
     385                 :      336462 :     glob->lastRowMarkId = 0;
     386                 :      336462 :     glob->lastPlanNodeId = 0;
     387                 :      336462 :     glob->transientPlan = false;
     388                 :      336462 :     glob->dependsOnRole = false;
     389                 :      336462 :     glob->partition_directory = NULL;
     390                 :      336462 :     glob->rel_notnullatts_hash = NULL;
     391                 :             : 
     392                 :             :     /*
     393                 :             :      * Assess whether it's feasible to use parallel mode for this query. We
     394                 :             :      * can't do this in a standalone backend, or if the command will try to
     395                 :             :      * modify any data, or if this is a cursor operation, or if GUCs are set
     396                 :             :      * to values that don't permit parallelism, or if parallel-unsafe
     397                 :             :      * functions are present in the query tree.
     398                 :             :      *
     399                 :             :      * (Note that we do allow CREATE TABLE AS, SELECT INTO, and CREATE
     400                 :             :      * MATERIALIZED VIEW to use parallel plans, but this is safe only because
     401                 :             :      * the command is writing into a completely new table which workers won't
     402                 :             :      * be able to see.  If the workers could see the table, the fact that
     403                 :             :      * group locking would cause them to ignore the leader's heavyweight GIN
     404                 :             :      * page locks would make this unsafe.  We'll have to fix that somehow if
     405                 :             :      * we want to allow parallel inserts in general; updates and deletes have
     406                 :             :      * additional problems especially around combo CIDs.)
     407                 :             :      *
     408                 :             :      * For now, we don't try to use parallel mode if we're running inside a
     409                 :             :      * parallel worker.  We might eventually be able to relax this
     410                 :             :      * restriction, but for now it seems best not to have parallel workers
     411                 :             :      * trying to create their own parallel workers.
     412                 :             :      */
     413   [ +  +  +  + ]:      336462 :     if ((cursorOptions & CURSOR_OPT_PARALLEL_OK) != 0 &&
     414                 :      318356 :         IsUnderPostmaster &&
     415         [ +  + ]:      318356 :         parse->commandType == CMD_SELECT &&
     416         [ +  + ]:      256318 :         !parse->hasModifyingCTE &&
     417         [ +  + ]:      256194 :         max_parallel_workers_per_gather > 0 &&
     418         [ +  + ]:      255502 :         !IsParallelWorker())
     419                 :             :     {
     420                 :             :         /* all the cheap tests pass, so scan the query tree */
     421                 :      255462 :         glob->maxParallelHazard = max_parallel_hazard(parse);
     422                 :      255462 :         glob->parallelModeOK = (glob->maxParallelHazard != PROPARALLEL_UNSAFE);
     423                 :             :     }
     424                 :             :     else
     425                 :             :     {
     426                 :             :         /* skip the query tree scan, just assume it's unsafe */
     427                 :       81000 :         glob->maxParallelHazard = PROPARALLEL_UNSAFE;
     428                 :       81000 :         glob->parallelModeOK = false;
     429                 :             :     }
     430                 :             : 
     431                 :             :     /*
     432                 :             :      * glob->parallelModeNeeded is normally set to false here and changed to
     433                 :             :      * true during plan creation if a Gather or Gather Merge plan is actually
     434                 :             :      * created (cf. create_gather_plan, create_gather_merge_plan).
     435                 :             :      *
     436                 :             :      * However, if debug_parallel_query = on or debug_parallel_query =
     437                 :             :      * regress, then we impose parallel mode whenever it's safe to do so, even
     438                 :             :      * if the final plan doesn't use parallelism.  It's not safe to do so if
     439                 :             :      * the query contains anything parallel-unsafe; parallelModeOK will be
     440                 :             :      * false in that case.  Note that parallelModeOK can't change after this
     441                 :             :      * point. Otherwise, everything in the query is either parallel-safe or
     442                 :             :      * parallel-restricted, and in either case it should be OK to impose
     443                 :             :      * parallel-mode restrictions.  If that ends up breaking something, then
     444                 :             :      * either some function the user included in the query is incorrectly
     445                 :             :      * labeled as parallel-safe or parallel-restricted when in reality it's
     446                 :             :      * parallel-unsafe, or else the query planner itself has a bug.
     447                 :             :      */
     448         [ +  + ]:      557047 :     glob->parallelModeNeeded = glob->parallelModeOK &&
     449         [ +  + ]:      220585 :         (debug_parallel_query != DEBUG_PARALLEL_OFF);
     450                 :             : 
     451                 :             :     /* Determine what fraction of the plan is likely to be scanned */
     452         [ +  + ]:      336462 :     if (cursorOptions & CURSOR_OPT_FAST_PLAN)
     453                 :             :     {
     454                 :             :         /*
     455                 :             :          * We have no real idea how many tuples the user will ultimately FETCH
     456                 :             :          * from a cursor, but it is often the case that he doesn't want 'em
     457                 :             :          * all, or would prefer a fast-start plan anyway so that he can
     458                 :             :          * process some of the tuples sooner.  Use a GUC parameter to decide
     459                 :             :          * what fraction to optimize for.
     460                 :             :          */
     461                 :        3251 :         tuple_fraction = cursor_tuple_fraction;
     462                 :             : 
     463                 :             :         /*
     464                 :             :          * We document cursor_tuple_fraction as simply being a fraction, which
     465                 :             :          * means the edge cases 0 and 1 have to be treated specially here.  We
     466                 :             :          * convert 1 to 0 ("all the tuples") and 0 to a very small fraction.
     467                 :             :          */
     468         [ -  + ]:        3251 :         if (tuple_fraction >= 1.0)
     469                 :           0 :             tuple_fraction = 0.0;
     470         [ -  + ]:        3251 :         else if (tuple_fraction <= 0.0)
     471                 :           0 :             tuple_fraction = 1e-10;
     472                 :             :     }
     473                 :             :     else
     474                 :             :     {
     475                 :             :         /* Default assumption is we need all the tuples */
     476                 :      333211 :         tuple_fraction = 0.0;
     477                 :             :     }
     478                 :             : 
     479                 :             :     /*
     480                 :             :      * Compute the initial path generation strategy mask.
     481                 :             :      *
     482                 :             :      * Some strategies, such as PGS_FOREIGNJOIN, have no corresponding enable_*
     483                 :             :      * GUC, and so the corresponding bits are always set in the default
     484                 :             :      * strategy mask.
     485                 :             :      *
     486                 :             :      * It may seem surprising that enable_indexscan sets both PGS_INDEXSCAN
     487                 :             :      * and PGS_INDEXONLYSCAN. However, the historical behavior of this GUC
     488                 :             :      * corresponds to this exactly: enable_indexscan=off disables both
     489                 :             :      * index-scan and index-only scan paths, whereas enable_indexonlyscan=off
     490                 :             :      * converts the index-only scan paths that we would have considered into
     491                 :             :      * index scan paths.
     492                 :             :      */
     493                 :      336462 :     glob->default_pgs_mask = PGS_APPEND | PGS_MERGE_APPEND | PGS_FOREIGNJOIN |
     494                 :             :         PGS_GATHER | PGS_CONSIDER_NONPARTIAL;
     495         [ +  - ]:      336462 :     if (enable_tidscan)
     496                 :      336462 :         glob->default_pgs_mask |= PGS_TIDSCAN;
     497         [ +  + ]:      336462 :     if (enable_seqscan)
     498                 :      319213 :         glob->default_pgs_mask |= PGS_SEQSCAN;
     499         [ +  + ]:      336462 :     if (enable_indexscan)
     500                 :      334225 :         glob->default_pgs_mask |= PGS_INDEXSCAN | PGS_INDEXONLYSCAN;
     501         [ +  + ]:      336462 :     if (enable_indexonlyscan)
     502                 :      335072 :         glob->default_pgs_mask |= PGS_CONSIDER_INDEXONLY;
     503         [ +  + ]:      336462 :     if (enable_bitmapscan)
     504                 :      327039 :         glob->default_pgs_mask |= PGS_BITMAPSCAN;
     505         [ +  + ]:      336462 :     if (enable_mergejoin)
     506                 :             :     {
     507                 :      334526 :         glob->default_pgs_mask |= PGS_MERGEJOIN_PLAIN;
     508         [ +  + ]:      334526 :         if (enable_material)
     509                 :      334459 :             glob->default_pgs_mask |= PGS_MERGEJOIN_MATERIALIZE;
     510                 :             :     }
     511         [ +  + ]:      336462 :     if (enable_nestloop)
     512                 :             :     {
     513                 :      336157 :         glob->default_pgs_mask |= PGS_NESTLOOP_PLAIN;
     514         [ +  + ]:      336157 :         if (enable_material)
     515                 :      335837 :             glob->default_pgs_mask |= PGS_NESTLOOP_MATERIALIZE;
     516         [ +  + ]:      336157 :         if (enable_memoize)
     517                 :      336048 :             glob->default_pgs_mask |= PGS_NESTLOOP_MEMOIZE;
     518                 :             :     }
     519         [ +  + ]:      336462 :     if (enable_hashjoin)
     520                 :      334197 :         glob->default_pgs_mask |= PGS_HASHJOIN;
     521         [ +  - ]:      336462 :     if (enable_gathermerge)
     522                 :      336462 :         glob->default_pgs_mask |= PGS_GATHER_MERGE;
     523         [ +  + ]:      336462 :     if (enable_partitionwise_join)
     524                 :        2074 :         glob->default_pgs_mask |= PGS_CONSIDER_PARTITIONWISE;
     525                 :             : 
     526                 :             :     /* Allow plugins to take control after we've initialized "glob" */
     527         [ +  + ]:      336462 :     if (planner_setup_hook)
     528                 :       89714 :         (*planner_setup_hook) (glob, parse, query_string, cursorOptions,
     529                 :             :                                &tuple_fraction, es);
     530                 :             : 
     531                 :             :     /* primary planning entry point (may recurse for subqueries) */
     532                 :      335677 :     root = subquery_planner(glob, parse, NULL, NULL, NULL, false,
     533                 :             :                             tuple_fraction, NULL);
     534                 :             : 
     535                 :             :     /* Select best Path and turn it into a Plan */
     536                 :      332651 :     final_rel = fetch_upper_rel(root, UPPERREL_FINAL, NULL);
     537                 :      332651 :     best_path = get_cheapest_fractional_path(final_rel, tuple_fraction);
     538                 :             : 
     539                 :      332651 :     top_plan = create_plan(root, best_path);
     540                 :             : 
     541                 :             :     /*
     542                 :             :      * If creating a plan for a scrollable cursor, make sure it can run
     543                 :             :      * backwards on demand.  Add a Material node at the top at need.
     544                 :             :      */
     545         [ +  + ]:      332381 :     if (cursorOptions & CURSOR_OPT_SCROLL)
     546                 :             :     {
     547         [ +  + ]:         221 :         if (!ExecSupportsBackwardScan(top_plan))
     548                 :          26 :             top_plan = materialize_finished_plan(top_plan);
     549                 :             :     }
     550                 :             : 
     551                 :             :     /*
     552                 :             :      * Optionally add a Gather node for testing purposes, provided this is
     553                 :             :      * actually a safe thing to do.
     554                 :             :      *
     555                 :             :      * We can add Gather even when top_plan has parallel-safe initPlans, but
     556                 :             :      * then we have to move the initPlans to the Gather node because of
     557                 :             :      * SS_finalize_plan's limitations.  That would cause cosmetic breakage of
     558                 :             :      * regression tests when debug_parallel_query = regress, because initPlans
     559                 :             :      * that would normally appear on the top_plan move to the Gather, causing
     560                 :             :      * them to disappear from EXPLAIN output.  That doesn't seem worth kluging
     561                 :             :      * EXPLAIN to hide, so skip it when debug_parallel_query = regress.
     562                 :             :      */
     563         [ +  + ]:      332381 :     if (debug_parallel_query != DEBUG_PARALLEL_OFF &&
     564         [ +  + ]:         157 :         top_plan->parallel_safe &&
     565         [ -  + ]:         104 :         (top_plan->initPlan == NIL ||
     566         [ #  # ]:           0 :          debug_parallel_query != DEBUG_PARALLEL_REGRESS))
     567                 :             :     {
     568                 :         104 :         Gather     *gather = makeNode(Gather);
     569                 :             :         Cost        initplan_cost;
     570                 :             :         bool        unsafe_initplans;
     571                 :             : 
     572                 :         104 :         gather->plan.targetlist = top_plan->targetlist;
     573                 :         104 :         gather->plan.qual = NIL;
     574                 :         104 :         gather->plan.lefttree = top_plan;
     575                 :         104 :         gather->plan.righttree = NULL;
     576                 :         104 :         gather->num_workers = 1;
     577                 :         104 :         gather->single_copy = true;
     578                 :         104 :         gather->invisible = (debug_parallel_query == DEBUG_PARALLEL_REGRESS);
     579                 :             : 
     580                 :             :         /* Transfer any initPlans to the new top node */
     581                 :         104 :         gather->plan.initPlan = top_plan->initPlan;
     582                 :         104 :         top_plan->initPlan = NIL;
     583                 :             : 
     584                 :             :         /*
     585                 :             :          * Since this Gather has no parallel-aware descendants to signal to,
     586                 :             :          * we don't need a rescan Param.
     587                 :             :          */
     588                 :         104 :         gather->rescan_param = -1;
     589                 :             : 
     590                 :             :         /*
     591                 :             :          * Ideally we'd use cost_gather here, but setting up dummy path data
     592                 :             :          * to satisfy it doesn't seem much cleaner than knowing what it does.
     593                 :             :          */
     594                 :         104 :         gather->plan.startup_cost = top_plan->startup_cost +
     595                 :             :             parallel_setup_cost;
     596                 :         104 :         gather->plan.total_cost = top_plan->total_cost +
     597                 :         104 :             parallel_setup_cost + parallel_tuple_cost * top_plan->plan_rows;
     598                 :         104 :         gather->plan.plan_rows = top_plan->plan_rows;
     599                 :         104 :         gather->plan.plan_width = top_plan->plan_width;
     600                 :         104 :         gather->plan.parallel_aware = false;
     601                 :         104 :         gather->plan.parallel_safe = false;
     602                 :             : 
     603                 :             :         /*
     604                 :             :          * Delete the initplans' cost from top_plan.  We needn't add it to the
     605                 :             :          * Gather node, since the above coding already included it there.
     606                 :             :          */
     607                 :         104 :         SS_compute_initplan_cost(gather->plan.initPlan,
     608                 :             :                                  &initplan_cost, &unsafe_initplans);
     609                 :         104 :         top_plan->startup_cost -= initplan_cost;
     610                 :         104 :         top_plan->total_cost -= initplan_cost;
     611                 :             : 
     612                 :             :         /* use parallel mode for parallel plans. */
     613                 :         104 :         root->glob->parallelModeNeeded = true;
     614                 :             : 
     615                 :         104 :         top_plan = &gather->plan;
     616                 :             :     }
     617                 :             : 
     618                 :             :     /*
     619                 :             :      * If any Params were generated, run through the plan tree and compute
     620                 :             :      * each plan node's extParam/allParam sets.  Ideally we'd merge this into
     621                 :             :      * set_plan_references' tree traversal, but for now it has to be separate
     622                 :             :      * because we need to visit subplans before not after main plan.
     623                 :             :      */
     624         [ +  + ]:      332381 :     if (glob->paramExecTypes != NIL)
     625                 :             :     {
     626                 :             :         Assert(list_length(glob->subplans) == list_length(glob->subroots));
     627   [ +  +  +  +  :      146157 :         forboth(lp, glob->subplans, lr, glob->subroots)
          +  +  +  +  +  
             +  +  -  +  
                      + ]
     628                 :             :         {
     629                 :       32413 :             Plan       *subplan = (Plan *) lfirst(lp);
     630                 :       32413 :             PlannerInfo *subroot = lfirst_node(PlannerInfo, lr);
     631                 :             : 
     632                 :       32413 :             SS_finalize_plan(subroot, subplan);
     633                 :             :         }
     634                 :      113744 :         SS_finalize_plan(root, top_plan);
     635                 :             :     }
     636                 :             : 
     637                 :             :     /* final cleanup of the plan */
     638                 :             :     Assert(glob->finalrtable == NIL);
     639                 :             :     Assert(glob->finalrteperminfos == NIL);
     640                 :             :     Assert(glob->finalrowmarks == NIL);
     641                 :             :     Assert(glob->resultRelations == NIL);
     642                 :             :     Assert(glob->appendRelations == NIL);
     643                 :      332381 :     top_plan = set_plan_references(root, top_plan);
     644                 :             :     /* ... and the subplans (both regular subplans and initplans) */
     645                 :             :     Assert(list_length(glob->subplans) == list_length(glob->subroots));
     646   [ +  +  +  +  :      364794 :     forboth(lp, glob->subplans, lr, glob->subroots)
          +  +  +  +  +  
             +  +  -  +  
                      + ]
     647                 :             :     {
     648                 :       32413 :         Plan       *subplan = (Plan *) lfirst(lp);
     649                 :       32413 :         PlannerInfo *subroot = lfirst_node(PlannerInfo, lr);
     650                 :             : 
     651                 :       32413 :         lfirst(lp) = set_plan_references(subroot, subplan);
     652                 :             :     }
     653                 :             : 
     654                 :             :     /* build the PlannedStmt result */
     655                 :      332381 :     result = makeNode(PlannedStmt);
     656                 :             : 
     657                 :      332381 :     result->commandType = parse->commandType;
     658                 :      332381 :     result->queryId = parse->queryId;
     659                 :      332381 :     result->planOrigin = PLAN_STMT_STANDARD;
     660                 :      332381 :     result->hasReturning = (parse->returningList != NIL);
     661                 :      332381 :     result->hasModifyingCTE = parse->hasModifyingCTE;
     662                 :      332381 :     result->canSetTag = parse->canSetTag;
     663                 :      332381 :     result->transientPlan = glob->transientPlan;
     664                 :      332381 :     result->dependsOnRole = glob->dependsOnRole;
     665                 :      332381 :     result->parallelModeNeeded = glob->parallelModeNeeded;
     666                 :      332381 :     result->planTree = top_plan;
     667                 :      332381 :     result->partPruneInfos = glob->partPruneInfos;
     668                 :      332381 :     result->rtable = glob->finalrtable;
     669                 :      664762 :     result->unprunableRelids = bms_difference(glob->allRelids,
     670                 :      332381 :                                               glob->prunableRelids);
     671                 :      332381 :     result->permInfos = glob->finalrteperminfos;
     672                 :      332381 :     result->subrtinfos = glob->subrtinfos;
     673                 :      332381 :     result->appendRelations = glob->appendRelations;
     674                 :      332381 :     result->subplans = glob->subplans;
     675                 :      332381 :     result->rewindPlanIDs = glob->rewindPlanIDs;
     676                 :      332381 :     result->rowMarks = glob->finalrowmarks;
     677                 :             : 
     678                 :             :     /*
     679                 :             :      * Compute resultRelationRelids and rowMarkRelids from resultRelations and
     680                 :             :      * rowMarks. These can be used for cheap membership checks.
     681                 :             :      */
     682   [ +  +  +  +  :      402157 :     foreach(lc, glob->resultRelations)
                   +  + ]
     683                 :       69776 :         result->resultRelationRelids = bms_add_member(result->resultRelationRelids,
     684                 :             :                                                       lfirst_int(lc));
     685   [ +  +  +  +  :      343192 :     foreach(lc, glob->finalrowmarks)
                   +  + ]
     686                 :       10811 :         result->rowMarkRelids = bms_add_member(result->rowMarkRelids,
     687                 :       10811 :                                                ((PlanRowMark *) lfirst(lc))->rti);
     688                 :             : 
     689                 :      332381 :     result->relationOids = glob->relationOids;
     690                 :      332381 :     result->invalItems = glob->invalItems;
     691                 :      332381 :     result->paramExecTypes = glob->paramExecTypes;
     692                 :             :     /* utilityStmt should be null, but we might as well copy it */
     693                 :      332381 :     result->utilityStmt = parse->utilityStmt;
     694                 :      332381 :     result->elidedNodes = glob->elidedNodes;
     695                 :      332381 :     result->stmt_location = parse->stmt_location;
     696                 :      332381 :     result->stmt_len = parse->stmt_len;
     697                 :             : 
     698                 :      332381 :     result->jitFlags = PGJIT_NONE;
     699   [ -  +  -  - ]:      332381 :     if (jit_enabled && jit_above_cost >= 0 &&
     700         [ #  # ]:           0 :         top_plan->total_cost > jit_above_cost)
     701                 :             :     {
     702                 :           0 :         result->jitFlags |= PGJIT_PERFORM;
     703                 :             : 
     704                 :             :         /*
     705                 :             :          * Decide how much effort should be put into generating better code.
     706                 :             :          */
     707         [ #  # ]:           0 :         if (jit_optimize_above_cost >= 0 &&
     708         [ #  # ]:           0 :             top_plan->total_cost > jit_optimize_above_cost)
     709                 :           0 :             result->jitFlags |= PGJIT_OPT3;
     710         [ #  # ]:           0 :         if (jit_inline_above_cost >= 0 &&
     711         [ #  # ]:           0 :             top_plan->total_cost > jit_inline_above_cost)
     712                 :           0 :             result->jitFlags |= PGJIT_INLINE;
     713                 :             : 
     714                 :             :         /*
     715                 :             :          * Decide which operations should be JITed.
     716                 :             :          */
     717         [ #  # ]:           0 :         if (jit_expressions)
     718                 :           0 :             result->jitFlags |= PGJIT_EXPR;
     719         [ #  # ]:           0 :         if (jit_tuple_deforming)
     720                 :           0 :             result->jitFlags |= PGJIT_DEFORM;
     721                 :             :     }
     722                 :             : 
     723                 :             :     /* Allow plugins to take control before we discard "glob" */
     724         [ +  + ]:      332381 :     if (planner_shutdown_hook)
     725                 :       88141 :         (*planner_shutdown_hook) (glob, parse, query_string, result);
     726                 :             : 
     727         [ +  + ]:      332381 :     if (glob->partition_directory != NULL)
     728                 :        9215 :         DestroyPartitionDirectory(glob->partition_directory);
     729                 :             : 
     730                 :      332381 :     return result;
     731                 :             : }
     732                 :             : 
     733                 :             : 
     734                 :             : /*--------------------
     735                 :             :  * subquery_planner
     736                 :             :  *    Invokes the planner on a subquery.  We recurse to here for each
     737                 :             :  *    sub-SELECT found in the query tree.
     738                 :             :  *
     739                 :             :  * glob is the global state for the current planner run.
     740                 :             :  * parse is the querytree produced by the parser & rewriter.
     741                 :             :  * plan_name is the name to assign to this subplan (NULL at the top level).
     742                 :             :  * parent_root is the immediate parent Query's info (NULL at the top level).
     743                 :             :  * alternative_root is a previously created PlannerInfo for which this query
     744                 :             :  * level is an alternative implementation, or else NULL.
     745                 :             :  * hasRecursion is true if this is a recursive WITH query.
     746                 :             :  * tuple_fraction is the fraction of tuples we expect will be retrieved.
     747                 :             :  * tuple_fraction is interpreted as explained for grouping_planner, below.
     748                 :             :  * setops is used for set operation subqueries to provide the subquery with
     749                 :             :  * the context in which it's being used so that Paths correctly sorted for the
     750                 :             :  * set operation can be generated.  NULL when not planning a set operation
     751                 :             :  * child, or when a child of a set op that isn't interested in sorted input.
     752                 :             :  *
     753                 :             :  * Basically, this routine does the stuff that should only be done once
     754                 :             :  * per Query object.  It then calls grouping_planner.  At one time,
     755                 :             :  * grouping_planner could be invoked recursively on the same Query object;
     756                 :             :  * that's not currently true, but we keep the separation between the two
     757                 :             :  * routines anyway, in case we need it again someday.
     758                 :             :  *
     759                 :             :  * subquery_planner will be called recursively to handle sub-Query nodes
     760                 :             :  * found within the query's expressions and rangetable.
     761                 :             :  *
     762                 :             :  * Returns the PlannerInfo struct ("root") that contains all data generated
     763                 :             :  * while planning the subquery.  In particular, the Path(s) attached to
     764                 :             :  * the (UPPERREL_FINAL, NULL) upperrel represent our conclusions about the
     765                 :             :  * cheapest way(s) to implement the query.  The top level will select the
     766                 :             :  * best Path and pass it through createplan.c to produce a finished Plan.
     767                 :             :  *--------------------
     768                 :             :  */
     769                 :             : PlannerInfo *
     770                 :      397976 : subquery_planner(PlannerGlobal *glob, Query *parse, char *plan_name,
     771                 :             :                  PlannerInfo *parent_root, PlannerInfo *alternative_root,
     772                 :             :                  bool hasRecursion, double tuple_fraction,
     773                 :             :                  SetOperationStmt *setops)
     774                 :             : {
     775                 :             :     PlannerInfo *root;
     776                 :             :     List       *newWithCheckOptions;
     777                 :             :     List       *newHaving;
     778                 :             :     Bitmapset  *havingPushdownConflicts;
     779                 :             :     int         havingIdx;
     780                 :             :     bool        hasOuterJoins;
     781                 :             :     bool        hasResultRTEs;
     782                 :             :     RelOptInfo *final_rel;
     783                 :             :     ListCell   *l;
     784                 :             : 
     785                 :             :     /* Create a PlannerInfo data structure for this subquery */
     786                 :      397976 :     root = makeNode(PlannerInfo);
     787                 :      397976 :     root->parse = parse;
     788                 :      397976 :     root->glob = glob;
     789         [ +  + ]:      397976 :     root->query_level = parent_root ? parent_root->query_level + 1 : 1;
     790                 :      397976 :     root->plan_name = plan_name;
     791         [ +  + ]:      397976 :     if (alternative_root != NULL)
     792                 :        1273 :         root->alternative_plan_name = alternative_root->plan_name;
     793                 :             :     else
     794                 :      396703 :         root->alternative_plan_name = plan_name;
     795                 :      397976 :     root->parent_root = parent_root;
     796                 :      397976 :     root->plan_params = NIL;
     797                 :      397976 :     root->outer_params = NULL;
     798                 :      397976 :     root->planner_cxt = CurrentMemoryContext;
     799                 :      397976 :     root->init_plans = NIL;
     800                 :      397976 :     root->cte_plan_ids = NIL;
     801                 :      397976 :     root->multiexpr_params = NIL;
     802                 :      397976 :     root->join_domains = NIL;
     803                 :      397976 :     root->eq_classes = NIL;
     804                 :      397976 :     root->ec_merging_done = false;
     805                 :      397976 :     root->last_rinfo_serial = 0;
     806                 :      397976 :     root->all_result_relids =
     807         [ +  + ]:      397976 :         parse->resultRelation ? bms_make_singleton(parse->resultRelation) : NULL;
     808                 :      397976 :     root->leaf_result_relids = NULL; /* we'll find out leaf-ness later */
     809                 :      397976 :     root->append_rel_list = NIL;
     810                 :      397976 :     root->row_identity_vars = NIL;
     811                 :      397976 :     root->rowMarks = NIL;
     812                 :      397976 :     memset(root->upper_rels, 0, sizeof(root->upper_rels));
     813                 :      397976 :     memset(root->upper_targets, 0, sizeof(root->upper_targets));
     814                 :      397976 :     root->processed_groupClause = NIL;
     815                 :      397976 :     root->processed_distinctClause = NIL;
     816                 :      397976 :     root->processed_tlist = NIL;
     817                 :      397976 :     root->update_colnos = NIL;
     818                 :      397976 :     root->grouping_map = NULL;
     819                 :      397976 :     root->minmax_aggs = NIL;
     820                 :      397976 :     root->qual_security_level = 0;
     821                 :      397976 :     root->hasPseudoConstantQuals = false;
     822                 :      397976 :     root->hasAlternativeSubPlans = false;
     823                 :      397976 :     root->placeholdersFrozen = false;
     824                 :      397976 :     root->hasRecursion = hasRecursion;
     825                 :      397976 :     root->assumeReplanning = false;
     826         [ +  + ]:      397976 :     if (hasRecursion)
     827                 :         638 :         root->wt_param_id = assign_special_exec_param(root);
     828                 :             :     else
     829                 :      397338 :         root->wt_param_id = -1;
     830                 :      397976 :     root->non_recursive_path = NULL;
     831                 :             : 
     832                 :             :     /*
     833                 :             :      * Create the top-level join domain.  This won't have valid contents until
     834                 :             :      * deconstruct_jointree fills it in, but the node needs to exist before
     835                 :             :      * that so we can build EquivalenceClasses referencing it.
     836                 :             :      */
     837                 :      397976 :     root->join_domains = list_make1(makeNode(JoinDomain));
     838                 :             : 
     839                 :             :     /*
     840                 :             :      * If there is a WITH list, process each WITH query and either convert it
     841                 :             :      * to RTE_SUBQUERY RTE(s) or build an initplan SubPlan structure for it.
     842                 :             :      */
     843         [ +  + ]:      397976 :     if (parse->cteList)
     844                 :        2179 :         SS_process_ctes(root);
     845                 :             : 
     846                 :             :     /*
     847                 :             :      * If it's a MERGE command, transform the joinlist as appropriate.
     848                 :             :      */
     849                 :      397972 :     transform_MERGE_to_join(parse);
     850                 :             : 
     851                 :             :     /*
     852                 :             :      * Reject FOR PORTION OF on a generated column.  We can't write to a
     853                 :             :      * virtual generated column, and a stored generated column should be
     854                 :             :      * written by its own expression.
     855                 :             :      *
     856                 :             :      * We do this in the planner rather than parse analysis so that updatable
     857                 :             :      * views have been rewritten; otherwise they would mask which columns are
     858                 :             :      * generated.  We need to check before preprocess_relation_rtes(), so that
     859                 :             :      * for virtual generated columns we still have the rangeVar.  After that
     860                 :             :      * it is replaced by the column's expression.
     861                 :             :      *
     862                 :             :      * XXX: We plan to implement PERIODs as stored generated columns, so later
     863                 :             :      * we will loosen this restriction if the column belongs to a PERIOD.
     864                 :             :      */
     865         [ +  + ]:      397972 :     if (parse->forPortionOf)
     866                 :             :     {
     867                 :        1111 :         ForPortionOfExpr *forPortionOf = parse->forPortionOf;
     868                 :        1111 :         RangeTblEntry *rte = rt_fetch(parse->resultRelation, parse->rtable);
     869                 :             : 
     870         [ +  + ]:        1111 :         if (get_attgenerated(rte->relid, forPortionOf->rangeVar->varattno))
     871         [ +  - ]:          16 :             ereport(ERROR,
     872                 :             :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     873                 :             :                      errmsg("cannot use generated column \"%s\" in FOR PORTION OF",
     874                 :             :                             get_attname(rte->relid,
     875                 :             :                                         forPortionOf->rangeVar->varattno,
     876                 :             :                                         false))));
     877                 :             :     }
     878                 :             : 
     879                 :             :     /*
     880                 :             :      * Scan the rangetable for relation RTEs and retrieve the necessary
     881                 :             :      * catalog information for each relation.  Using this information, clear
     882                 :             :      * the inh flag for any relation that has no children, collect not-null
     883                 :             :      * attribute numbers for any relation that has column not-null
     884                 :             :      * constraints, and expand virtual generated columns for any relation that
     885                 :             :      * contains them.  Note that this step does not descend into sublinks and
     886                 :             :      * subqueries; if we pull up any sublinks or subqueries below, their
     887                 :             :      * relation RTEs are processed just before pulling them up.
     888                 :             :      */
     889                 :      397956 :     parse = root->parse = preprocess_relation_rtes(root);
     890                 :             : 
     891                 :             :     /*
     892                 :             :      * If the FROM clause is empty, replace it with a dummy RTE_RESULT RTE, so
     893                 :             :      * that we don't need so many special cases to deal with that situation.
     894                 :             :      */
     895                 :      397956 :     replace_empty_jointree(parse);
     896                 :             : 
     897                 :             :     /*
     898                 :             :      * Look for ANY and EXISTS SubLinks in WHERE and JOIN/ON clauses, and try
     899                 :             :      * to transform them into joins.  Note that this step does not descend
     900                 :             :      * into subqueries; if we pull up any subqueries below, their SubLinks are
     901                 :             :      * processed just before pulling them up.
     902                 :             :      */
     903         [ +  + ]:      397956 :     if (parse->hasSubLinks)
     904                 :       30319 :         pull_up_sublinks(root);
     905                 :             : 
     906                 :             :     /*
     907                 :             :      * Scan the rangetable for function RTEs, do const-simplification on them,
     908                 :             :      * and then inline them if possible (producing subqueries that might get
     909                 :             :      * pulled up next).  Recursion issues here are handled in the same way as
     910                 :             :      * for SubLinks.
     911                 :             :      */
     912                 :      397956 :     preprocess_function_rtes(root);
     913                 :             : 
     914                 :             :     /*
     915                 :             :      * Check to see if any subqueries in the jointree can be merged into this
     916                 :             :      * query.
     917                 :             :      */
     918                 :      397952 :     pull_up_subqueries(root);
     919                 :             : 
     920                 :             :     /*
     921                 :             :      * If this is a simple UNION ALL query, flatten it into an appendrel. We
     922                 :             :      * do this now because it requires applying pull_up_subqueries to the leaf
     923                 :             :      * queries of the UNION ALL, which weren't touched above because they
     924                 :             :      * weren't referenced by the jointree (they will be after we do this).
     925                 :             :      */
     926         [ +  + ]:      397952 :     if (parse->setOperations)
     927                 :        5495 :         flatten_simple_union_all(root);
     928                 :             : 
     929                 :             :     /*
     930                 :             :      * Survey the rangetable to see what kinds of entries are present.  We can
     931                 :             :      * skip some later processing if relevant SQL features are not used; for
     932                 :             :      * example if there are no JOIN RTEs we can avoid the expense of doing
     933                 :             :      * flatten_join_alias_vars().  This must be done after we have finished
     934                 :             :      * adding rangetable entries, of course.  (Note: actually, processing of
     935                 :             :      * inherited or partitioned rels can cause RTEs for their child tables to
     936                 :             :      * get added later; but those must all be RTE_RELATION entries, so they
     937                 :             :      * don't invalidate the conclusions drawn here.)
     938                 :             :      */
     939                 :      397952 :     root->hasJoinRTEs = false;
     940                 :      397952 :     root->hasLateralRTEs = false;
     941                 :      397952 :     root->group_rtindex = 0;
     942                 :      397952 :     hasOuterJoins = false;
     943                 :      397952 :     hasResultRTEs = false;
     944   [ +  -  +  +  :     1100112 :     foreach(l, parse->rtable)
                   +  + ]
     945                 :             :     {
     946                 :      702160 :         RangeTblEntry *rte = lfirst_node(RangeTblEntry, l);
     947                 :             : 
     948   [ +  +  +  + ]:      702160 :         switch (rte->rtekind)
     949                 :             :         {
     950                 :       71646 :             case RTE_JOIN:
     951                 :       71646 :                 root->hasJoinRTEs = true;
     952         [ +  + ]:       71646 :                 if (IS_OUTER_JOIN(rte->jointype))
     953                 :       36484 :                     hasOuterJoins = true;
     954                 :       71646 :                 break;
     955                 :      148954 :             case RTE_RESULT:
     956                 :      148954 :                 hasResultRTEs = true;
     957                 :      148954 :                 break;
     958                 :        4371 :             case RTE_GROUP:
     959                 :             :                 Assert(parse->hasGroupRTE);
     960                 :        4371 :                 root->group_rtindex = list_cell_number(parse->rtable, l) + 1;
     961                 :        4371 :                 break;
     962                 :      477189 :             default:
     963                 :             :                 /* No work here for other RTE types */
     964                 :      477189 :                 break;
     965                 :             :         }
     966                 :             : 
     967         [ +  + ]:      702160 :         if (rte->lateral)
     968                 :        8203 :             root->hasLateralRTEs = true;
     969                 :             : 
     970                 :             :         /*
     971                 :             :          * We can also determine the maximum security level required for any
     972                 :             :          * securityQuals now.  Addition of inheritance-child RTEs won't affect
     973                 :             :          * this, because child tables don't have their own securityQuals; see
     974                 :             :          * expand_single_inheritance_child().
     975                 :             :          */
     976         [ +  + ]:      702160 :         if (rte->securityQuals)
     977         [ -  + ]:        2485 :             root->qual_security_level = Max(root->qual_security_level,
     978                 :             :                                             list_length(rte->securityQuals));
     979                 :             :     }
     980                 :             : 
     981                 :             :     /*
     982                 :             :      * If we have now verified that the query target relation is
     983                 :             :      * non-inheriting, mark it as a leaf target.
     984                 :             :      */
     985         [ +  + ]:      397952 :     if (parse->resultRelation)
     986                 :             :     {
     987                 :       66057 :         RangeTblEntry *rte = rt_fetch(parse->resultRelation, parse->rtable);
     988                 :             : 
     989         [ +  + ]:       66057 :         if (!rte->inh)
     990                 :       63702 :             root->leaf_result_relids =
     991                 :       63702 :                 bms_make_singleton(parse->resultRelation);
     992                 :             :     }
     993                 :             : 
     994                 :             :     /*
     995                 :             :      * This would be a convenient time to check access permissions for all
     996                 :             :      * relations mentioned in the query, since it would be better to fail now,
     997                 :             :      * before doing any detailed planning.  However, for historical reasons,
     998                 :             :      * we leave this to be done at executor startup.
     999                 :             :      *
    1000                 :             :      * Note, however, that we do need to check access permissions for any view
    1001                 :             :      * relations mentioned in the query, in order to prevent information being
    1002                 :             :      * leaked by selectivity estimation functions, which only check view owner
    1003                 :             :      * permissions on underlying tables (see all_rows_selectable() and its
    1004                 :             :      * callers).  This is a little ugly, because it means that access
    1005                 :             :      * permissions for views will be checked twice, which is another reason
    1006                 :             :      * why it would be better to do all the ACL checks here.
    1007                 :             :      */
    1008   [ +  -  +  +  :     1099324 :     foreach(l, parse->rtable)
                   +  + ]
    1009                 :             :     {
    1010                 :      701638 :         RangeTblEntry *rte = lfirst_node(RangeTblEntry, l);
    1011                 :             : 
    1012         [ +  + ]:      701638 :         if (rte->perminfoindex != 0 &&
    1013         [ +  + ]:      379323 :             rte->relkind == RELKIND_VIEW)
    1014                 :             :         {
    1015                 :             :             RTEPermissionInfo *perminfo;
    1016                 :             :             bool        result;
    1017                 :             : 
    1018                 :       16422 :             perminfo = getRTEPermissionInfo(parse->rteperminfos, rte);
    1019                 :       16422 :             result = ExecCheckOneRelPerms(perminfo);
    1020         [ +  + ]:       16422 :             if (!result)
    1021                 :         266 :                 aclcheck_error(ACLCHECK_NO_PRIV, OBJECT_VIEW,
    1022                 :         266 :                                get_rel_name(perminfo->relid));
    1023                 :             :         }
    1024                 :             :     }
    1025                 :             : 
    1026                 :             :     /*
    1027                 :             :      * Preprocess RowMark information.  We need to do this after subquery
    1028                 :             :      * pullup, so that all base relations are present.
    1029                 :             :      */
    1030                 :      397686 :     preprocess_rowmarks(root);
    1031                 :             : 
    1032                 :             :     /*
    1033                 :             :      * Set hasHavingQual to remember if HAVING clause is present.  Needed
    1034                 :             :      * because preprocess_expression will reduce a constant-true condition to
    1035                 :             :      * an empty qual list ... but "HAVING TRUE" is not a semantic no-op.
    1036                 :             :      */
    1037                 :      397686 :     root->hasHavingQual = (parse->havingQual != NULL);
    1038                 :             : 
    1039                 :             :     /*
    1040                 :             :      * Do expression preprocessing on targetlist and quals, as well as other
    1041                 :             :      * random expressions in the querytree.  Note that we do not need to
    1042                 :             :      * handle sort/group expressions explicitly, because they are actually
    1043                 :             :      * part of the targetlist.
    1044                 :             :      */
    1045                 :      395013 :     parse->targetList = (List *)
    1046                 :      397686 :         preprocess_expression(root, (Node *) parse->targetList,
    1047                 :             :                               EXPRKIND_TARGET);
    1048                 :             : 
    1049                 :      395013 :     newWithCheckOptions = NIL;
    1050   [ +  +  +  +  :      397641 :     foreach(l, parse->withCheckOptions)
                   +  + ]
    1051                 :             :     {
    1052                 :        2628 :         WithCheckOption *wco = lfirst_node(WithCheckOption, l);
    1053                 :             : 
    1054                 :        2628 :         wco->qual = preprocess_expression(root, wco->qual,
    1055                 :             :                                           EXPRKIND_QUAL);
    1056         [ +  + ]:        2628 :         if (wco->qual != NULL)
    1057                 :        2286 :             newWithCheckOptions = lappend(newWithCheckOptions, wco);
    1058                 :             :     }
    1059                 :      395013 :     parse->withCheckOptions = newWithCheckOptions;
    1060                 :             : 
    1061                 :      395013 :     parse->returningList = (List *)
    1062                 :      395013 :         preprocess_expression(root, (Node *) parse->returningList,
    1063                 :             :                               EXPRKIND_TARGET);
    1064                 :             : 
    1065                 :      395013 :     preprocess_qual_conditions(root, (Node *) parse->jointree);
    1066                 :             : 
    1067                 :      395009 :     parse->havingQual = preprocess_expression(root, parse->havingQual,
    1068                 :             :                                               EXPRKIND_QUAL);
    1069                 :             : 
    1070   [ +  +  +  +  :      397560 :     foreach(l, parse->windowClause)
                   +  + ]
    1071                 :             :     {
    1072                 :        2551 :         WindowClause *wc = lfirst_node(WindowClause, l);
    1073                 :             : 
    1074                 :             :         /* partitionClause/orderClause are sort/group expressions */
    1075                 :        2551 :         wc->startOffset = preprocess_expression(root, wc->startOffset,
    1076                 :             :                                                 EXPRKIND_LIMIT);
    1077                 :        2551 :         wc->endOffset = preprocess_expression(root, wc->endOffset,
    1078                 :             :                                               EXPRKIND_LIMIT);
    1079                 :             :     }
    1080                 :             : 
    1081                 :      395009 :     parse->limitOffset = preprocess_expression(root, parse->limitOffset,
    1082                 :             :                                                EXPRKIND_LIMIT);
    1083                 :      395009 :     parse->limitCount = preprocess_expression(root, parse->limitCount,
    1084                 :             :                                               EXPRKIND_LIMIT);
    1085                 :             : 
    1086         [ +  + ]:      395009 :     if (parse->onConflict)
    1087                 :             :     {
    1088                 :        3580 :         parse->onConflict->arbiterElems = (List *)
    1089                 :        1790 :             preprocess_expression(root,
    1090                 :        1790 :                                   (Node *) parse->onConflict->arbiterElems,
    1091                 :             :                                   EXPRKIND_ARBITER_ELEM);
    1092                 :        3580 :         parse->onConflict->arbiterWhere =
    1093                 :        1790 :             preprocess_expression(root,
    1094                 :        1790 :                                   parse->onConflict->arbiterWhere,
    1095                 :             :                                   EXPRKIND_QUAL);
    1096                 :        3580 :         parse->onConflict->onConflictSet = (List *)
    1097                 :        1790 :             preprocess_expression(root,
    1098                 :        1790 :                                   (Node *) parse->onConflict->onConflictSet,
    1099                 :             :                                   EXPRKIND_TARGET);
    1100                 :        1790 :         parse->onConflict->onConflictWhere =
    1101                 :        1790 :             preprocess_expression(root,
    1102                 :        1790 :                                   parse->onConflict->onConflictWhere,
    1103                 :             :                                   EXPRKIND_QUAL);
    1104                 :             :         /* exclRelTlist contains only Vars, so no preprocessing needed */
    1105                 :             :     }
    1106                 :             : 
    1107         [ +  + ]:      395009 :     if (parse->forPortionOf)
    1108                 :             :     {
    1109                 :        2174 :         parse->forPortionOf->targetRange =
    1110                 :        1087 :             preprocess_expression(root,
    1111                 :        1087 :                                   parse->forPortionOf->targetRange,
    1112                 :             :                                   EXPRKIND_TARGET);
    1113         [ +  + ]:        1087 :         if (contain_volatile_functions(parse->forPortionOf->targetRange))
    1114         [ +  - ]:           8 :             ereport(ERROR,
    1115                 :             :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1116                 :             :                      errmsg("FOR PORTION OF bounds cannot contain volatile functions")));
    1117                 :             :     }
    1118                 :             : 
    1119   [ +  +  +  +  :      397289 :     foreach(l, parse->mergeActionList)
                   +  + ]
    1120                 :             :     {
    1121                 :        2288 :         MergeAction *action = (MergeAction *) lfirst(l);
    1122                 :             : 
    1123                 :        2288 :         action->targetList = (List *)
    1124                 :        2288 :             preprocess_expression(root,
    1125                 :        2288 :                                   (Node *) action->targetList,
    1126                 :             :                                   EXPRKIND_TARGET);
    1127                 :        2288 :         action->qual =
    1128                 :        2288 :             preprocess_expression(root,
    1129                 :             :                                   (Node *) action->qual,
    1130                 :             :                                   EXPRKIND_QUAL);
    1131                 :             :     }
    1132                 :             : 
    1133                 :      395001 :     parse->mergeJoinCondition =
    1134                 :      395001 :         preprocess_expression(root, parse->mergeJoinCondition, EXPRKIND_QUAL);
    1135                 :             : 
    1136                 :      395001 :     root->append_rel_list = (List *)
    1137                 :      395001 :         preprocess_expression(root, (Node *) root->append_rel_list,
    1138                 :             :                               EXPRKIND_APPINFO);
    1139                 :             : 
    1140                 :             :     /* Also need to preprocess expressions within RTEs */
    1141   [ +  -  +  +  :     1093279 :     foreach(l, parse->rtable)
                   +  + ]
    1142                 :             :     {
    1143                 :      698286 :         RangeTblEntry *rte = lfirst_node(RangeTblEntry, l);
    1144                 :             :         int         kind;
    1145                 :             :         ListCell   *lcsq;
    1146                 :             : 
    1147         [ +  + ]:      698286 :         if (rte->rtekind == RTE_RELATION)
    1148                 :             :         {
    1149         [ +  + ]:      365954 :             if (rte->tablesample)
    1150                 :         180 :                 rte->tablesample = (TableSampleClause *)
    1151                 :         180 :                     preprocess_expression(root,
    1152                 :         180 :                                           (Node *) rte->tablesample,
    1153                 :             :                                           EXPRKIND_TABLESAMPLE);
    1154                 :             :         }
    1155         [ +  + ]:      332332 :         else if (rte->rtekind == RTE_SUBQUERY)
    1156                 :             :         {
    1157                 :             :             /*
    1158                 :             :              * We don't want to do all preprocessing yet on the subquery's
    1159                 :             :              * expressions, since that will happen when we plan it.  But if it
    1160                 :             :              * contains any join aliases of our level, those have to get
    1161                 :             :              * expanded now, because planning of the subquery won't do it.
    1162                 :             :              * That's only possible if the subquery is LATERAL.
    1163                 :             :              */
    1164   [ +  +  +  + ]:       63609 :             if (rte->lateral && root->hasJoinRTEs)
    1165                 :        1622 :                 rte->subquery = (Query *)
    1166                 :        1622 :                     flatten_join_alias_vars(root, root->parse,
    1167                 :        1622 :                                             (Node *) rte->subquery);
    1168                 :             :         }
    1169         [ +  + ]:      268723 :         else if (rte->rtekind == RTE_FUNCTION)
    1170                 :             :         {
    1171                 :             :             /* Preprocess the function expression(s) fully */
    1172         [ +  + ]:       35011 :             kind = rte->lateral ? EXPRKIND_RTFUNC_LATERAL : EXPRKIND_RTFUNC;
    1173                 :       35011 :             rte->functions = (List *)
    1174                 :       35011 :                 preprocess_expression(root, (Node *) rte->functions, kind);
    1175                 :             :         }
    1176         [ +  + ]:      233712 :         else if (rte->rtekind == RTE_TABLEFUNC)
    1177                 :             :         {
    1178                 :             :             /* Preprocess the function expression(s) fully */
    1179         [ +  + ]:         612 :             kind = rte->lateral ? EXPRKIND_TABLEFUNC_LATERAL : EXPRKIND_TABLEFUNC;
    1180                 :         604 :             rte->tablefunc = (TableFunc *)
    1181                 :         612 :                 preprocess_expression(root, (Node *) rte->tablefunc, kind);
    1182                 :             :         }
    1183         [ +  + ]:      233100 :         else if (rte->rtekind == RTE_VALUES)
    1184                 :             :         {
    1185                 :             :             /* Preprocess the values lists fully */
    1186         [ +  + ]:        7013 :             kind = rte->lateral ? EXPRKIND_VALUES_LATERAL : EXPRKIND_VALUES;
    1187                 :        7013 :             rte->values_lists = (List *)
    1188                 :        7013 :                 preprocess_expression(root, (Node *) rte->values_lists, kind);
    1189                 :             :         }
    1190         [ +  + ]:      226087 :         else if (rte->rtekind == RTE_GROUP)
    1191                 :             :         {
    1192                 :             :             /* Preprocess the groupexprs list fully */
    1193                 :        4371 :             rte->groupexprs = (List *)
    1194                 :        4371 :                 preprocess_expression(root, (Node *) rte->groupexprs,
    1195                 :             :                                       EXPRKIND_GROUPEXPR);
    1196                 :             :         }
    1197                 :             : 
    1198                 :             :         /*
    1199                 :             :          * Process each element of the securityQuals list as if it were a
    1200                 :             :          * separate qual expression (as indeed it is).  We need to do it this
    1201                 :             :          * way to get proper canonicalization of AND/OR structure.  Note that
    1202                 :             :          * this converts each element into an implicit-AND sublist.
    1203                 :             :          */
    1204   [ +  +  +  +  :      701143 :         foreach(lcsq, rte->securityQuals)
                   +  + ]
    1205                 :             :         {
    1206                 :        2865 :             lfirst(lcsq) = preprocess_expression(root,
    1207                 :        2865 :                                                  (Node *) lfirst(lcsq),
    1208                 :             :                                                  EXPRKIND_QUAL);
    1209                 :             :         }
    1210                 :             :     }
    1211                 :             : 
    1212                 :             :     /*
    1213                 :             :      * Now that we are done preprocessing expressions, and in particular done
    1214                 :             :      * flattening join alias variables, get rid of the joinaliasvars lists.
    1215                 :             :      * They no longer match what expressions in the rest of the tree look
    1216                 :             :      * like, because we have not preprocessed expressions in those lists (and
    1217                 :             :      * do not want to; for example, expanding a SubLink there would result in
    1218                 :             :      * a useless unreferenced subplan).  Leaving them in place simply creates
    1219                 :             :      * a hazard for later scans of the tree.  We could try to prevent that by
    1220                 :             :      * using QTW_IGNORE_JOINALIASES in every tree scan done after this point,
    1221                 :             :      * but that doesn't sound very reliable.
    1222                 :             :      */
    1223         [ +  + ]:      394993 :     if (root->hasJoinRTEs)
    1224                 :             :     {
    1225   [ +  -  +  +  :      252583 :         foreach(l, parse->rtable)
                   +  + ]
    1226                 :             :         {
    1227                 :      207501 :             RangeTblEntry *rte = lfirst_node(RangeTblEntry, l);
    1228                 :             : 
    1229                 :      207501 :             rte->joinaliasvars = NIL;
    1230                 :             :         }
    1231                 :             :     }
    1232                 :             : 
    1233                 :             :     /*
    1234                 :             :      * Before we flatten GROUP Vars, identify HAVING clauses whose equality
    1235                 :             :      * semantics disagree with the GROUP BY's.  See find_having_conflicts.
    1236                 :             :      */
    1237         [ +  + ]:      394993 :     if (parse->hasGroupRTE)
    1238                 :        4371 :         havingPushdownConflicts = find_having_conflicts(parse,
    1239                 :        4371 :                                                         root->group_rtindex);
    1240                 :             :     else
    1241                 :      390622 :         havingPushdownConflicts = NULL;
    1242                 :             : 
    1243                 :             :     /*
    1244                 :             :      * Replace any Vars in the subquery's targetlist and havingQual that
    1245                 :             :      * reference GROUP outputs with the underlying grouping expressions.
    1246                 :             :      *
    1247                 :             :      * Note that we need to perform this replacement after we've preprocessed
    1248                 :             :      * the grouping expressions.  This is to ensure that there is only one
    1249                 :             :      * instance of SubPlan for each SubLink contained within the grouping
    1250                 :             :      * expressions.
    1251                 :             :      */
    1252         [ +  + ]:      394993 :     if (parse->hasGroupRTE)
    1253                 :             :     {
    1254                 :        4371 :         parse->targetList = (List *)
    1255                 :        4371 :             flatten_group_exprs(root, root->parse, (Node *) parse->targetList);
    1256                 :        4371 :         parse->havingQual =
    1257                 :        4371 :             flatten_group_exprs(root, root->parse, parse->havingQual);
    1258                 :             :     }
    1259                 :             : 
    1260                 :             :     /* Constant-folding might have removed all set-returning functions */
    1261         [ +  + ]:      394993 :     if (parse->hasTargetSRFs)
    1262                 :       10227 :         parse->hasTargetSRFs = expression_returns_set((Node *) parse->targetList);
    1263                 :             : 
    1264                 :             :     /*
    1265                 :             :      * If we have grouping sets, expand the groupingSets tree of this query to
    1266                 :             :      * a flat list of grouping sets.  We need to do this before optimizing
    1267                 :             :      * HAVING, since we can't easily tell if there's an empty grouping set
    1268                 :             :      * until we have this representation.
    1269                 :             :      */
    1270         [ +  + ]:      394993 :     if (parse->groupingSets)
    1271                 :             :     {
    1272                 :         910 :         parse->groupingSets =
    1273                 :         910 :             expand_grouping_sets(parse->groupingSets, parse->groupDistinct, -1);
    1274                 :             :     }
    1275                 :             : 
    1276                 :             :     /*
    1277                 :             :      * In some cases we may want to transfer a HAVING clause into WHERE. We
    1278                 :             :      * cannot do so if the HAVING clause contains aggregates (obviously) or
    1279                 :             :      * volatile functions (since a HAVING clause is supposed to be executed
    1280                 :             :      * only once per group).  We also can't do this if there are any grouping
    1281                 :             :      * sets and the clause references any columns that are nullable by the
    1282                 :             :      * grouping sets; the nulled values of those columns are not available
    1283                 :             :      * before the grouping step.  (The test on groupClause might seem wrong,
    1284                 :             :      * but it's okay: it's just an optimization to avoid running pull_varnos
    1285                 :             :      * when there cannot be any Vars in the HAVING clause.)
    1286                 :             :      *
    1287                 :             :      * We also cannot do this for HAVING clauses that conflict with GROUP BY
    1288                 :             :      * on collation or operator family.  Both kinds of conflict are detected
    1289                 :             :      * before flatten_group_exprs (see find_having_conflicts above) and
    1290                 :             :      * recorded in the havingPushdownConflicts bitmapset.  The bitmapset
    1291                 :             :      * indexes remain valid here because flatten_group_exprs uses
    1292                 :             :      * expression_tree_mutator, which preserves the list length and ordering
    1293                 :             :      * of havingQual.
    1294                 :             :      *
    1295                 :             :      * Also, it may be that the clause is so expensive to execute that we're
    1296                 :             :      * better off doing it only once per group, despite the loss of
    1297                 :             :      * selectivity.  This is hard to estimate short of doing the entire
    1298                 :             :      * planning process twice, so we use a heuristic: clauses containing
    1299                 :             :      * subplans are left in HAVING.  Otherwise, we move or copy the HAVING
    1300                 :             :      * clause into WHERE, in hopes of eliminating tuples before aggregation
    1301                 :             :      * instead of after.
    1302                 :             :      *
    1303                 :             :      * If the query has no empty grouping set then we can simply move such a
    1304                 :             :      * clause into WHERE; any group that fails the clause will not be in the
    1305                 :             :      * output because none of its tuples will reach the grouping or
    1306                 :             :      * aggregation stage.  Otherwise we have to keep the clause in HAVING to
    1307                 :             :      * ensure that we don't emit a bogus aggregated row.  But then the HAVING
    1308                 :             :      * clause must be degenerate (variable-free), so we can copy it into WHERE
    1309                 :             :      * so that query_planner() can use it in a gating Result node. (This could
    1310                 :             :      * be done better, but it seems not worth optimizing.)
    1311                 :             :      *
    1312                 :             :      * Note that a HAVING clause may contain expressions that are not fully
    1313                 :             :      * preprocessed.  This can happen if these expressions are part of
    1314                 :             :      * grouping items.  In such cases, they are replaced with GROUP Vars in
    1315                 :             :      * the parser and then replaced back after we're done with expression
    1316                 :             :      * preprocessing on havingQual.  This is not an issue if the clause
    1317                 :             :      * remains in HAVING, because these expressions will be matched to lower
    1318                 :             :      * target items in setrefs.c.  However, if the clause is moved or copied
    1319                 :             :      * into WHERE, we need to ensure that these expressions are fully
    1320                 :             :      * preprocessed.
    1321                 :             :      *
    1322                 :             :      * Note that both havingQual and parse->jointree->quals are in
    1323                 :             :      * implicitly-ANDed-list form at this point, even though they are declared
    1324                 :             :      * as Node *.
    1325                 :             :      */
    1326                 :      394993 :     newHaving = NIL;
    1327                 :      394993 :     havingIdx = 0;
    1328   [ +  +  +  +  :      396305 :     foreach(l, (List *) parse->havingQual)
                   +  + ]
    1329                 :             :     {
    1330                 :        1312 :         Node       *havingclause = (Node *) lfirst(l);
    1331                 :             : 
    1332   [ +  +  +  - ]:        1943 :         if (contain_agg_clause(havingclause) ||
    1333         [ +  - ]:        1262 :             contain_volatile_functions(havingclause) ||
    1334         [ +  + ]:        1262 :             contain_subplans(havingclause) ||
    1335                 :         631 :             bms_is_member(havingIdx, havingPushdownConflicts) ||
    1336   [ +  +  +  +  :         611 :             (parse->groupClause && parse->groupingSets &&
                   +  + ]
    1337                 :         100 :              bms_is_member(root->group_rtindex, pull_varnos(root, havingclause))))
    1338                 :             :         {
    1339                 :             :             /* keep it in HAVING */
    1340                 :         861 :             newHaving = lappend(newHaving, havingclause);
    1341                 :             :         }
    1342         [ +  + ]:         451 :         else if (parse->groupClause &&
    1343         [ +  + ]:         421 :                  (parse->groupingSets == NIL ||
    1344         [ +  + ]:          40 :                   (List *) linitial(parse->groupingSets) != NIL))
    1345                 :         411 :         {
    1346                 :             :             /* There is GROUP BY, but no empty grouping set */
    1347                 :             :             Node       *whereclause;
    1348                 :             : 
    1349                 :             :             /* Preprocess the HAVING clause fully */
    1350                 :         411 :             whereclause = preprocess_expression(root, havingclause,
    1351                 :             :                                                 EXPRKIND_QUAL);
    1352                 :             :             /* ... and move it to WHERE */
    1353                 :         411 :             parse->jointree->quals = (Node *)
    1354                 :         411 :                 list_concat((List *) parse->jointree->quals,
    1355                 :             :                             (List *) whereclause);
    1356                 :             :         }
    1357                 :             :         else
    1358                 :             :         {
    1359                 :             :             /* There is an empty grouping set (perhaps implicitly) */
    1360                 :             :             Node       *whereclause;
    1361                 :             : 
    1362                 :             :             /* Preprocess the HAVING clause fully */
    1363                 :          40 :             whereclause = preprocess_expression(root, copyObject(havingclause),
    1364                 :             :                                                 EXPRKIND_QUAL);
    1365                 :             :             /* ... and put a copy in WHERE */
    1366                 :          80 :             parse->jointree->quals = (Node *)
    1367                 :          40 :                 list_concat((List *) parse->jointree->quals,
    1368                 :             :                             (List *) whereclause);
    1369                 :             :             /* ... and also keep it in HAVING */
    1370                 :          40 :             newHaving = lappend(newHaving, havingclause);
    1371                 :             :         }
    1372                 :             : 
    1373                 :        1312 :         havingIdx++;
    1374                 :             :     }
    1375                 :      394993 :     parse->havingQual = (Node *) newHaving;
    1376                 :             : 
    1377                 :             :     /*
    1378                 :             :      * If we have any outer joins, try to reduce them to plain inner joins.
    1379                 :             :      * This step is most easily done after we've done expression
    1380                 :             :      * preprocessing.
    1381                 :             :      */
    1382         [ +  + ]:      394993 :     if (hasOuterJoins)
    1383                 :       25353 :         reduce_outer_joins(root);
    1384                 :             : 
    1385                 :             :     /*
    1386                 :             :      * If we have any RTE_RESULT relations, see if they can be deleted from
    1387                 :             :      * the jointree.  We also rely on this processing to flatten single-child
    1388                 :             :      * FromExprs underneath outer joins.  This step is most effectively done
    1389                 :             :      * after we've done expression preprocessing and outer join reduction.
    1390                 :             :      */
    1391   [ +  +  +  + ]:      394993 :     if (hasResultRTEs || hasOuterJoins)
    1392                 :      170405 :         remove_useless_result_rtes(root);
    1393                 :             : 
    1394                 :             :     /*
    1395                 :             :      * Do the main planning.
    1396                 :             :      */
    1397                 :      394993 :     grouping_planner(root, tuple_fraction, setops);
    1398                 :             : 
    1399                 :             :     /*
    1400                 :             :      * Capture the set of outer-level param IDs we have access to, for use in
    1401                 :             :      * extParam/allParam calculations later.
    1402                 :             :      */
    1403                 :      394946 :     SS_identify_outer_params(root);
    1404                 :             : 
    1405                 :             :     /*
    1406                 :             :      * If any initPlans were created in this query level, adjust the surviving
    1407                 :             :      * Paths' costs and parallel-safety flags to account for them.  The
    1408                 :             :      * initPlans won't actually get attached to the plan tree till
    1409                 :             :      * create_plan() runs, but we must include their effects now.
    1410                 :             :      */
    1411                 :      394946 :     final_rel = fetch_upper_rel(root, UPPERREL_FINAL, NULL);
    1412                 :      394946 :     SS_charge_for_initplans(root, final_rel);
    1413                 :             : 
    1414                 :             :     /*
    1415                 :             :      * Make sure we've identified the cheapest Path for the final rel.  (By
    1416                 :             :      * doing this here not in grouping_planner, we include initPlan costs in
    1417                 :             :      * the decision, though it's unlikely that will change anything.)
    1418                 :             :      */
    1419                 :      394946 :     set_cheapest(final_rel);
    1420                 :             : 
    1421                 :      394946 :     return root;
    1422                 :             : }
    1423                 :             : 
    1424                 :             : /*
    1425                 :             :  * preprocess_expression
    1426                 :             :  *      Do subquery_planner's preprocessing work for an expression,
    1427                 :             :  *      which can be a targetlist, a WHERE clause (including JOIN/ON
    1428                 :             :  *      conditions), a HAVING clause, or a few other things.
    1429                 :             :  */
    1430                 :             : static Node *
    1431                 :     3334994 : preprocess_expression(PlannerInfo *root, Node *expr, int kind)
    1432                 :             : {
    1433                 :             :     /*
    1434                 :             :      * Fall out quickly if expression is empty.  This occurs often enough to
    1435                 :             :      * be worth checking.  Note that null->null is the correct conversion for
    1436                 :             :      * implicit-AND result format, too.
    1437                 :             :      */
    1438         [ +  + ]:     3334994 :     if (expr == NULL)
    1439                 :     2622318 :         return NULL;
    1440                 :             : 
    1441                 :             :     /*
    1442                 :             :      * If the query has any join RTEs, replace join alias variables with
    1443                 :             :      * base-relation variables.  We must do this first, since any expressions
    1444                 :             :      * we may extract from the joinaliasvars lists have not been preprocessed.
    1445                 :             :      * For example, if we did this after sublink processing, sublinks expanded
    1446                 :             :      * out from join aliases would not get processed.  But we can skip this in
    1447                 :             :      * non-lateral RTE functions, VALUES lists, and TABLESAMPLE clauses, since
    1448                 :             :      * they can't contain any Vars of the current query level.
    1449                 :             :      */
    1450   [ +  +  +  + ]:      712676 :     if (root->hasJoinRTEs &&
    1451   [ +  +  +  - ]:      326756 :         !(kind == EXPRKIND_RTFUNC ||
    1452         [ +  + ]:      163223 :           kind == EXPRKIND_VALUES ||
    1453                 :             :           kind == EXPRKIND_TABLESAMPLE ||
    1454                 :             :           kind == EXPRKIND_TABLEFUNC))
    1455                 :      163208 :         expr = flatten_join_alias_vars(root, root->parse, expr);
    1456                 :             : 
    1457                 :             :     /*
    1458                 :             :      * Simplify constant expressions.  For function RTEs, this was already
    1459                 :             :      * done by preprocess_function_rtes.  (But note we must do it again for
    1460                 :             :      * EXPRKIND_RTFUNC_LATERAL, because those might by now contain
    1461                 :             :      * un-simplified subexpressions inserted by flattening of subqueries or
    1462                 :             :      * join alias variables.)
    1463                 :             :      *
    1464                 :             :      * Note: an essential effect of this is to convert named-argument function
    1465                 :             :      * calls to positional notation and insert the current actual values of
    1466                 :             :      * any default arguments for functions.  To ensure that happens, we *must*
    1467                 :             :      * process all expressions here.  Previous PG versions sometimes skipped
    1468                 :             :      * const-simplification if it didn't seem worth the trouble, but we can't
    1469                 :             :      * do that anymore.
    1470                 :             :      *
    1471                 :             :      * Note: this also flattens nested AND and OR expressions into N-argument
    1472                 :             :      * form.  All processing of a qual expression after this point must be
    1473                 :             :      * careful to maintain AND/OR flatness --- that is, do not generate a tree
    1474                 :             :      * with AND directly under AND, nor OR directly under OR.
    1475                 :             :      */
    1476         [ +  + ]:      712676 :     if (kind != EXPRKIND_RTFUNC)
    1477                 :      682129 :         expr = eval_const_expressions(root, expr);
    1478                 :             : 
    1479                 :             :     /*
    1480                 :             :      * If it's a qual or havingQual, canonicalize it.
    1481                 :             :      */
    1482         [ +  + ]:      709991 :     if (kind == EXPRKIND_QUAL)
    1483                 :             :     {
    1484                 :      262246 :         expr = (Node *) canonicalize_qual((Expr *) expr, false);
    1485                 :             : 
    1486                 :             : #ifdef OPTIMIZER_DEBUG
    1487                 :             :         printf("After canonicalize_qual()\n");
    1488                 :             :         pprint(expr);
    1489                 :             : #endif
    1490                 :             :     }
    1491                 :             : 
    1492                 :             :     /*
    1493                 :             :      * Check for ANY ScalarArrayOpExpr with Const arrays and set the
    1494                 :             :      * hashfuncid of any that might execute more quickly by using hash lookups
    1495                 :             :      * instead of a linear search.
    1496                 :             :      */
    1497   [ +  +  +  + ]:      709991 :     if (kind == EXPRKIND_QUAL || kind == EXPRKIND_TARGET)
    1498                 :             :     {
    1499                 :      651310 :         convert_saop_to_hashed_saop(expr);
    1500                 :             :     }
    1501                 :             : 
    1502                 :             :     /* Expand SubLinks to SubPlans */
    1503         [ +  + ]:      709983 :     if (root->parse->hasSubLinks)
    1504                 :       91974 :         expr = SS_process_sublinks(root, expr, (kind == EXPRKIND_QUAL));
    1505                 :             : 
    1506                 :             :     /*
    1507                 :             :      * XXX do not insert anything here unless you have grokked the comments in
    1508                 :             :      * SS_replace_correlation_vars ...
    1509                 :             :      */
    1510                 :             : 
    1511                 :             :     /* Replace uplevel vars with Param nodes (this IS possible in VALUES) */
    1512         [ +  + ]:      709983 :     if (root->query_level > 1)
    1513                 :      146559 :         expr = SS_replace_correlation_vars(root, expr);
    1514                 :             : 
    1515                 :             :     /*
    1516                 :             :      * If it's a qual or havingQual, convert it to implicit-AND format. (We
    1517                 :             :      * don't want to do this before eval_const_expressions, since the latter
    1518                 :             :      * would be unable to simplify a top-level AND correctly. Also,
    1519                 :             :      * SS_process_sublinks expects explicit-AND format.)
    1520                 :             :      */
    1521         [ +  + ]:      709983 :     if (kind == EXPRKIND_QUAL)
    1522                 :      262246 :         expr = (Node *) make_ands_implicit((Expr *) expr);
    1523                 :             : 
    1524                 :      709983 :     return expr;
    1525                 :             : }
    1526                 :             : 
    1527                 :             : /*
    1528                 :             :  * preprocess_qual_conditions
    1529                 :             :  *      Recursively scan the query's jointree and do subquery_planner's
    1530                 :             :  *      preprocessing work on each qual condition found therein.
    1531                 :             :  */
    1532                 :             : static void
    1533                 :     1007283 : preprocess_qual_conditions(PlannerInfo *root, Node *jtnode)
    1534                 :             : {
    1535         [ -  + ]:     1007283 :     if (jtnode == NULL)
    1536                 :           0 :         return;
    1537         [ +  + ]:     1007283 :     if (IsA(jtnode, RangeTblRef))
    1538                 :             :     {
    1539                 :             :         /* nothing to do here */
    1540                 :             :     }
    1541         [ +  + ]:      496128 :     else if (IsA(jtnode, FromExpr))
    1542                 :             :     {
    1543                 :      412847 :         FromExpr   *f = (FromExpr *) jtnode;
    1544                 :             :         ListCell   *l;
    1545                 :             : 
    1546   [ +  +  +  +  :      858554 :         foreach(l, f->fromlist)
                   +  + ]
    1547                 :      445707 :             preprocess_qual_conditions(root, lfirst(l));
    1548                 :             : 
    1549                 :      412847 :         f->quals = preprocess_expression(root, f->quals, EXPRKIND_QUAL);
    1550                 :             :     }
    1551         [ +  - ]:       83281 :     else if (IsA(jtnode, JoinExpr))
    1552                 :             :     {
    1553                 :       83281 :         JoinExpr   *j = (JoinExpr *) jtnode;
    1554                 :             : 
    1555                 :       83281 :         preprocess_qual_conditions(root, j->larg);
    1556                 :       83281 :         preprocess_qual_conditions(root, j->rarg);
    1557                 :             : 
    1558                 :       83281 :         j->quals = preprocess_expression(root, j->quals, EXPRKIND_QUAL);
    1559                 :             :     }
    1560                 :             :     else
    1561         [ #  # ]:           0 :         elog(ERROR, "unrecognized node type: %d",
    1562                 :             :              (int) nodeTag(jtnode));
    1563                 :             : }
    1564                 :             : 
    1565                 :             : /*
    1566                 :             :  * find_having_conflicts
    1567                 :             :  *    Identify HAVING clauses that must not be moved to WHERE because they
    1568                 :             :  *    apply a different equivalence relation than GROUP BY.  Pushing such a
    1569                 :             :  *    clause to WHERE would filter individual rows before grouping happens,
    1570                 :             :  *    eliminating rows that GROUP BY would have merged into a single group
    1571                 :             :  *    and thereby changing aggregate results.
    1572                 :             :  *
    1573                 :             :  * The actual walking is done by expression_has_grouping_conflict; see that
    1574                 :             :  * function for the kinds of conflict it looks for.  We just iterate over
    1575                 :             :  * havingQual and supply a HAVING-specific callback that identifies GROUP
    1576                 :             :  * Vars.
    1577                 :             :  *
    1578                 :             :  * This must be called before flatten_group_exprs, while the HAVING clause
    1579                 :             :  * still contains GROUP Vars (Vars referencing RTE_GROUP).  These GROUP Vars
    1580                 :             :  * carry the GROUP BY collation as their varcollid and let us recover the
    1581                 :             :  * grouping eqop via varattno.  After flattening, those Vars are replaced by
    1582                 :             :  * the underlying expressions, and matching back to grouping expressions is
    1583                 :             :  * much harder.
    1584                 :             :  *
    1585                 :             :  * Returns a Bitmapset of zero-based indexes into the havingQual list for
    1586                 :             :  * clauses that conflict and must stay in HAVING.
    1587                 :             :  */
    1588                 :             : static Bitmapset *
    1589                 :        4371 : find_having_conflicts(Query *parse, Index group_rtindex)
    1590                 :             : {
    1591                 :        4371 :     Bitmapset  *result = NULL;
    1592                 :             :     having_grouping_ctx ctx;
    1593                 :             :     int         idx;
    1594                 :             : 
    1595         [ +  + ]:        4371 :     if (parse->havingQual == NULL)
    1596                 :        3493 :         return NULL;
    1597                 :             : 
    1598                 :         878 :     ctx.parse = parse;
    1599                 :         878 :     ctx.group_rtindex = group_rtindex;
    1600                 :             : 
    1601                 :         878 :     idx = 0;
    1602   [ +  -  +  +  :        2773 :     foreach_ptr(Node, clause, (List *) parse->havingQual)
                   +  + ]
    1603                 :             :     {
    1604         [ +  + ]:        1017 :         if (expression_has_grouping_conflict(clause, having_var_grouping_eqop,
    1605                 :             :                                              &ctx))
    1606                 :         120 :             result = bms_add_member(result, idx);
    1607                 :        1017 :         idx++;
    1608                 :             :     }
    1609                 :             : 
    1610                 :         878 :     return result;
    1611                 :             : }
    1612                 :             : 
    1613                 :             : /*
    1614                 :             :  * having_var_grouping_eqop
    1615                 :             :  *    grouping_eqop_callback for find_having_conflicts.
    1616                 :             :  *
    1617                 :             :  * Returns the GROUP BY equality operator for 'var' if it references the
    1618                 :             :  * query's RTE_GROUP, or InvalidOid otherwise.
    1619                 :             :  */
    1620                 :             : static Oid
    1621                 :         968 : having_var_grouping_eqop(Var *var, void *context)
    1622                 :             : {
    1623                 :         968 :     having_grouping_ctx *ctx = (having_grouping_ctx *) context;
    1624                 :             : 
    1625   [ +  +  -  + ]:         968 :     if (var->varno != ctx->group_rtindex || var->varlevelsup != 0)
    1626                 :         384 :         return InvalidOid;
    1627                 :             : 
    1628                 :         584 :     return group_var_eqop(ctx->parse, var);
    1629                 :             : }
    1630                 :             : 
    1631                 :             : /*
    1632                 :             :  * group_var_eqop
    1633                 :             :  *    Return the equality operator that GROUP BY uses for the given GROUP Var.
    1634                 :             :  *
    1635                 :             :  * A GROUP Var's varattno is its 1-based position in the RTE_GROUP's groupexprs
    1636                 :             :  * list, which addRangeTableEntryForGroup built by iterating parse->groupClause
    1637                 :             :  * and including every SortGroupClause whose TLE was present in the targetlist.
    1638                 :             :  * Replay that traversal here to recover the SortGroupClause for the given
    1639                 :             :  * varattno.
    1640                 :             :  */
    1641                 :             : static Oid
    1642                 :         584 : group_var_eqop(Query *parse, Var *var)
    1643                 :             : {
    1644                 :         584 :     int         counter = 0;
    1645                 :             : 
    1646                 :             :     Assert(var->varlevelsup == 0);
    1647                 :             : 
    1648   [ +  -  +  -  :         926 :     foreach_node(SortGroupClause, sgc, parse->groupClause)
                   +  - ]
    1649                 :             :     {
    1650         [ -  + ]:         926 :         if (get_sortgroupclause_tle(sgc, parse->targetList) == NULL)
    1651                 :           0 :             continue;
    1652         [ +  + ]:         926 :         if (++counter == var->varattno)
    1653                 :         584 :             return sgc->eqop;
    1654                 :             :     }
    1655                 :             : 
    1656         [ #  # ]:           0 :     elog(ERROR, "could not find GROUP clause for GROUP Var attno %d",
    1657                 :             :          var->varattno);
    1658                 :             :     return InvalidOid;          /* keep compiler quiet */
    1659                 :             : }
    1660                 :             : 
    1661                 :             : /*
    1662                 :             :  * preprocess_phv_expression
    1663                 :             :  *    Do preprocessing on a PlaceHolderVar expression that's been pulled up.
    1664                 :             :  *
    1665                 :             :  * If a LATERAL subquery references an output of another subquery, and that
    1666                 :             :  * output must be wrapped in a PlaceHolderVar because of an intermediate outer
    1667                 :             :  * join, then we'll push the PlaceHolderVar expression down into the subquery
    1668                 :             :  * and later pull it back up during find_lateral_references, which runs after
    1669                 :             :  * subquery_planner has preprocessed all the expressions that were in the
    1670                 :             :  * current query level to start with.  So we need to preprocess it then.
    1671                 :             :  */
    1672                 :             : Expr *
    1673                 :          75 : preprocess_phv_expression(PlannerInfo *root, Expr *expr)
    1674                 :             : {
    1675                 :          75 :     return (Expr *) preprocess_expression(root, (Node *) expr, EXPRKIND_PHV);
    1676                 :             : }
    1677                 :             : 
    1678                 :             : /*--------------------
    1679                 :             :  * grouping_planner
    1680                 :             :  *    Perform planning steps related to grouping, aggregation, etc.
    1681                 :             :  *
    1682                 :             :  * This function adds all required top-level processing to the scan/join
    1683                 :             :  * Path(s) produced by query_planner.
    1684                 :             :  *
    1685                 :             :  * tuple_fraction is the fraction of tuples we expect will be retrieved.
    1686                 :             :  * tuple_fraction is interpreted as follows:
    1687                 :             :  *    0: expect all tuples to be retrieved (normal case)
    1688                 :             :  *    0 < tuple_fraction < 1: expect the given fraction of tuples available
    1689                 :             :  *      from the plan to be retrieved
    1690                 :             :  *    tuple_fraction >= 1: tuple_fraction is the absolute number of tuples
    1691                 :             :  *      expected to be retrieved (ie, a LIMIT specification).
    1692                 :             :  * setops is used for set operation subqueries to provide the subquery with
    1693                 :             :  * the context in which it's being used so that Paths correctly sorted for the
    1694                 :             :  * set operation can be generated.  NULL when not planning a set operation
    1695                 :             :  * child, or when a child of a set op that isn't interested in sorted input.
    1696                 :             :  *
    1697                 :             :  * Returns nothing; the useful output is in the Paths we attach to the
    1698                 :             :  * (UPPERREL_FINAL, NULL) upperrel in *root.  In addition,
    1699                 :             :  * root->processed_tlist contains the final processed targetlist.
    1700                 :             :  *
    1701                 :             :  * Note that we have not done set_cheapest() on the final rel; it's convenient
    1702                 :             :  * to leave this to the caller.
    1703                 :             :  *--------------------
    1704                 :             :  */
    1705                 :             : static void
    1706                 :      394994 : grouping_planner(PlannerInfo *root, double tuple_fraction,
    1707                 :             :                  SetOperationStmt *setops)
    1708                 :             : {
    1709                 :      394994 :     Query      *parse = root->parse;
    1710                 :      394994 :     int64       offset_est = 0;
    1711                 :      394994 :     int64       count_est = 0;
    1712                 :      394994 :     double      limit_tuples = -1.0;
    1713                 :      394994 :     bool        have_postponed_srfs = false;
    1714                 :             :     PathTarget *final_target;
    1715                 :             :     List       *final_targets;
    1716                 :             :     List       *final_targets_contain_srfs;
    1717                 :             :     bool        final_target_parallel_safe;
    1718                 :             :     RelOptInfo *current_rel;
    1719                 :             :     RelOptInfo *final_rel;
    1720                 :             :     FinalPathExtraData extra;
    1721                 :             :     ListCell   *lc;
    1722                 :             : 
    1723                 :             :     /* Tweak caller-supplied tuple_fraction if have LIMIT/OFFSET */
    1724   [ +  +  +  + ]:      394994 :     if (parse->limitCount || parse->limitOffset)
    1725                 :             :     {
    1726                 :        3740 :         tuple_fraction = preprocess_limit(root, tuple_fraction,
    1727                 :             :                                           &offset_est, &count_est);
    1728                 :             : 
    1729                 :             :         /*
    1730                 :             :          * If we have a known LIMIT, and don't have an unknown OFFSET, we can
    1731                 :             :          * estimate the effects of using a bounded sort.
    1732                 :             :          */
    1733   [ +  +  +  + ]:        3740 :         if (count_est > 0 && offset_est >= 0)
    1734                 :        3258 :             limit_tuples = (double) count_est + (double) offset_est;
    1735                 :             :     }
    1736                 :             : 
    1737                 :             :     /* Make tuple_fraction accessible to lower-level routines */
    1738                 :      394994 :     root->tuple_fraction = tuple_fraction;
    1739                 :             : 
    1740         [ +  + ]:      394994 :     if (parse->setOperations)
    1741                 :             :     {
    1742                 :             :         /*
    1743                 :             :          * Construct Paths for set operations.  The results will not need any
    1744                 :             :          * work except perhaps a top-level sort and/or LIMIT.  Note that any
    1745                 :             :          * special work for recursive unions is the responsibility of
    1746                 :             :          * plan_set_operations.
    1747                 :             :          */
    1748                 :        4951 :         current_rel = plan_set_operations(root);
    1749                 :             : 
    1750                 :             :         /*
    1751                 :             :          * We should not need to call preprocess_targetlist, since we must be
    1752                 :             :          * in a SELECT query node.  Instead, use the processed_tlist returned
    1753                 :             :          * by plan_set_operations (since this tells whether it returned any
    1754                 :             :          * resjunk columns!), and transfer any sort key information from the
    1755                 :             :          * original tlist.
    1756                 :             :          */
    1757                 :             :         Assert(parse->commandType == CMD_SELECT);
    1758                 :             : 
    1759                 :             :         /* for safety, copy processed_tlist instead of modifying in-place */
    1760                 :        4947 :         root->processed_tlist =
    1761                 :        4947 :             postprocess_setop_tlist(copyObject(root->processed_tlist),
    1762                 :             :                                     parse->targetList);
    1763                 :             : 
    1764                 :             :         /* Also extract the PathTarget form of the setop result tlist */
    1765                 :        4947 :         final_target = current_rel->cheapest_total_path->pathtarget;
    1766                 :             : 
    1767                 :             :         /* And check whether it's parallel safe */
    1768                 :             :         final_target_parallel_safe =
    1769                 :        4947 :             is_parallel_safe(root, (Node *) final_target->exprs);
    1770                 :             : 
    1771                 :             :         /* The setop result tlist couldn't contain any SRFs */
    1772                 :             :         Assert(!parse->hasTargetSRFs);
    1773                 :        4947 :         final_targets = final_targets_contain_srfs = NIL;
    1774                 :             : 
    1775                 :             :         /*
    1776                 :             :          * Can't handle FOR [KEY] UPDATE/SHARE here (parser should have
    1777                 :             :          * checked already, but let's make sure).
    1778                 :             :          */
    1779         [ -  + ]:        4947 :         if (parse->rowMarks)
    1780         [ #  # ]:           0 :             ereport(ERROR,
    1781                 :             :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1782                 :             :             /*------
    1783                 :             :               translator: %s is a SQL row locking clause such as FOR UPDATE */
    1784                 :             :                      errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
    1785                 :             :                             LCS_asString(linitial_node(RowMarkClause,
    1786                 :             :                                                        parse->rowMarks)->strength))));
    1787                 :             : 
    1788                 :             :         /*
    1789                 :             :          * Calculate pathkeys that represent result ordering requirements
    1790                 :             :          */
    1791                 :             :         Assert(parse->distinctClause == NIL);
    1792                 :        4947 :         root->sort_pathkeys = make_pathkeys_for_sortclauses(root,
    1793                 :             :                                                             parse->sortClause,
    1794                 :             :                                                             root->processed_tlist);
    1795                 :             :     }
    1796                 :             :     else
    1797                 :             :     {
    1798                 :             :         /* No set operations, do regular planning */
    1799                 :             :         PathTarget *sort_input_target;
    1800                 :             :         List       *sort_input_targets;
    1801                 :             :         List       *sort_input_targets_contain_srfs;
    1802                 :             :         bool        sort_input_target_parallel_safe;
    1803                 :             :         PathTarget *grouping_target;
    1804                 :             :         List       *grouping_targets;
    1805                 :             :         List       *grouping_targets_contain_srfs;
    1806                 :             :         bool        grouping_target_parallel_safe;
    1807                 :             :         PathTarget *scanjoin_target;
    1808                 :             :         List       *scanjoin_targets;
    1809                 :             :         List       *scanjoin_targets_contain_srfs;
    1810                 :             :         bool        scanjoin_target_parallel_safe;
    1811                 :             :         bool        scanjoin_target_same_exprs;
    1812                 :             :         bool        have_grouping;
    1813                 :      390043 :         WindowFuncLists *wflists = NULL;
    1814                 :      390043 :         List       *activeWindows = NIL;
    1815                 :      390043 :         grouping_sets_data *gset_data = NULL;
    1816                 :             :         standard_qp_extra qp_extra;
    1817                 :             : 
    1818                 :             :         /* A recursive query should always have setOperations */
    1819                 :             :         Assert(!root->hasRecursion);
    1820                 :             : 
    1821                 :             :         /* Preprocess grouping sets and GROUP BY clause, if any */
    1822         [ +  + ]:      390043 :         if (parse->groupingSets)
    1823                 :             :         {
    1824                 :         910 :             gset_data = preprocess_grouping_sets(root);
    1825                 :             :         }
    1826         [ +  + ]:      389133 :         else if (parse->groupClause)
    1827                 :             :         {
    1828                 :             :             /* Preprocess regular GROUP BY clause, if any */
    1829                 :        3531 :             root->processed_groupClause = preprocess_groupclause(root, NIL);
    1830                 :             :         }
    1831                 :             : 
    1832                 :             :         /*
    1833                 :             :          * Preprocess targetlist.  Note that much of the remaining planning
    1834                 :             :          * work will be done with the PathTarget representation of tlists, but
    1835                 :             :          * we must also maintain the full representation of the final tlist so
    1836                 :             :          * that we can transfer its decoration (resnames etc) to the topmost
    1837                 :             :          * tlist of the finished Plan.  This is kept in processed_tlist.
    1838                 :             :          */
    1839                 :      390039 :         preprocess_targetlist(root);
    1840                 :             : 
    1841                 :             :         /*
    1842                 :             :          * Mark all the aggregates with resolved aggtranstypes, and detect
    1843                 :             :          * aggregates that are duplicates or can share transition state.  We
    1844                 :             :          * must do this before slicing and dicing the tlist into various
    1845                 :             :          * pathtargets, else some copies of the Aggref nodes might escape
    1846                 :             :          * being marked.
    1847                 :             :          */
    1848         [ +  + ]:      390039 :         if (parse->hasAggs)
    1849                 :             :         {
    1850                 :       33408 :             preprocess_aggrefs(root, (Node *) root->processed_tlist);
    1851                 :       33408 :             preprocess_aggrefs(root, (Node *) parse->havingQual);
    1852                 :             :         }
    1853                 :             : 
    1854                 :             :         /*
    1855                 :             :          * Locate any window functions in the tlist.  (We don't need to look
    1856                 :             :          * anywhere else, since expressions used in ORDER BY will be in there
    1857                 :             :          * too.)  Note that they could all have been eliminated by constant
    1858                 :             :          * folding, in which case we don't need to do any more work.
    1859                 :             :          */
    1860         [ +  + ]:      390039 :         if (parse->hasWindowFuncs)
    1861                 :             :         {
    1862                 :        2331 :             wflists = find_window_functions((Node *) root->processed_tlist,
    1863                 :        2331 :                                             list_length(parse->windowClause));
    1864         [ +  + ]:        2331 :             if (wflists->numWindowFuncs > 0)
    1865                 :             :             {
    1866                 :             :                 /*
    1867                 :             :                  * See if any modifications can be made to each WindowClause
    1868                 :             :                  * to allow the executor to execute the WindowFuncs more
    1869                 :             :                  * quickly.
    1870                 :             :                  */
    1871                 :        2326 :                 optimize_window_clauses(root, wflists);
    1872                 :             : 
    1873                 :             :                 /* Extract the list of windows actually in use. */
    1874                 :        2326 :                 activeWindows = select_active_windows(root, wflists);
    1875                 :             : 
    1876                 :             :                 /* Make sure they all have names, for EXPLAIN's use. */
    1877                 :        2326 :                 name_active_windows(activeWindows);
    1878                 :             :             }
    1879                 :             :             else
    1880                 :           5 :                 parse->hasWindowFuncs = false;
    1881                 :             :         }
    1882                 :             : 
    1883                 :             :         /*
    1884                 :             :          * Preprocess MIN/MAX aggregates, if any.  Note: be careful about
    1885                 :             :          * adding logic between here and the query_planner() call.  Anything
    1886                 :             :          * that is needed in MIN/MAX-optimizable cases will have to be
    1887                 :             :          * duplicated in planagg.c.
    1888                 :             :          */
    1889         [ +  + ]:      390039 :         if (parse->hasAggs)
    1890                 :       33408 :             preprocess_minmax_aggregates(root);
    1891                 :             : 
    1892                 :             :         /*
    1893                 :             :          * Figure out whether there's a hard limit on the number of rows that
    1894                 :             :          * query_planner's result subplan needs to return.  Even if we know a
    1895                 :             :          * hard limit overall, it doesn't apply if the query has any
    1896                 :             :          * grouping/aggregation operations, or SRFs in the tlist.
    1897                 :             :          */
    1898         [ +  + ]:      390039 :         if (parse->groupClause ||
    1899         [ +  + ]:      385672 :             parse->groupingSets ||
    1900         [ +  + ]:      385602 :             parse->distinctClause ||
    1901         [ +  + ]:      383612 :             parse->hasAggs ||
    1902         [ +  + ]:      353958 :             parse->hasWindowFuncs ||
    1903         [ +  + ]:      351748 :             parse->hasTargetSRFs ||
    1904         [ +  + ]:      341850 :             root->hasHavingQual)
    1905                 :       48209 :             root->limit_tuples = -1.0;
    1906                 :             :         else
    1907                 :      341830 :             root->limit_tuples = limit_tuples;
    1908                 :             : 
    1909                 :             :         /* Set up data needed by standard_qp_callback */
    1910                 :      390039 :         qp_extra.activeWindows = activeWindows;
    1911                 :      390039 :         qp_extra.gset_data = gset_data;
    1912                 :             : 
    1913                 :             :         /*
    1914                 :             :          * If we're a subquery for a set operation, store the SetOperationStmt
    1915                 :             :          * in qp_extra.
    1916                 :             :          */
    1917                 :      390039 :         qp_extra.setop = setops;
    1918                 :             : 
    1919                 :             :         /*
    1920                 :             :          * Generate the best unsorted and presorted paths for the scan/join
    1921                 :             :          * portion of this Query, ie the processing represented by the
    1922                 :             :          * FROM/WHERE clauses.  (Note there may not be any presorted paths.)
    1923                 :             :          * We also generate (in standard_qp_callback) pathkey representations
    1924                 :             :          * of the query's sort clause, distinct clause, etc.
    1925                 :             :          */
    1926                 :      390039 :         current_rel = query_planner(root, standard_qp_callback, &qp_extra);
    1927                 :             : 
    1928                 :             :         /*
    1929                 :             :          * Convert the query's result tlist into PathTarget format.
    1930                 :             :          *
    1931                 :             :          * Note: this cannot be done before query_planner() has performed
    1932                 :             :          * appendrel expansion, because that might add resjunk entries to
    1933                 :             :          * root->processed_tlist.  Waiting till afterwards is also helpful
    1934                 :             :          * because the target width estimates can use per-Var width numbers
    1935                 :             :          * that were obtained within query_planner().
    1936                 :             :          */
    1937                 :      390004 :         final_target = create_pathtarget(root, root->processed_tlist);
    1938                 :             :         final_target_parallel_safe =
    1939                 :      390004 :             is_parallel_safe(root, (Node *) final_target->exprs);
    1940                 :             : 
    1941                 :             :         /*
    1942                 :             :          * If ORDER BY was given, consider whether we should use a post-sort
    1943                 :             :          * projection, and compute the adjusted target for preceding steps if
    1944                 :             :          * so.
    1945                 :             :          */
    1946         [ +  + ]:      390004 :         if (parse->sortClause)
    1947                 :             :         {
    1948                 :       58046 :             sort_input_target = make_sort_input_target(root,
    1949                 :             :                                                        final_target,
    1950                 :             :                                                        &have_postponed_srfs);
    1951                 :             :             sort_input_target_parallel_safe =
    1952                 :       58046 :                 is_parallel_safe(root, (Node *) sort_input_target->exprs);
    1953                 :             :         }
    1954                 :             :         else
    1955                 :             :         {
    1956                 :      331958 :             sort_input_target = final_target;
    1957                 :      331958 :             sort_input_target_parallel_safe = final_target_parallel_safe;
    1958                 :             :         }
    1959                 :             : 
    1960                 :             :         /*
    1961                 :             :          * If we have window functions to deal with, the output from any
    1962                 :             :          * grouping step needs to be what the window functions want;
    1963                 :             :          * otherwise, it should be sort_input_target.
    1964                 :             :          */
    1965         [ +  + ]:      390004 :         if (activeWindows)
    1966                 :             :         {
    1967                 :        2326 :             grouping_target = make_window_input_target(root,
    1968                 :             :                                                        final_target,
    1969                 :             :                                                        activeWindows);
    1970                 :             :             grouping_target_parallel_safe =
    1971                 :        2326 :                 is_parallel_safe(root, (Node *) grouping_target->exprs);
    1972                 :             :         }
    1973                 :             :         else
    1974                 :             :         {
    1975                 :      387678 :             grouping_target = sort_input_target;
    1976                 :      387678 :             grouping_target_parallel_safe = sort_input_target_parallel_safe;
    1977                 :             :         }
    1978                 :             : 
    1979                 :             :         /*
    1980                 :             :          * If we have grouping or aggregation to do, the topmost scan/join
    1981                 :             :          * plan node must emit what the grouping step wants; otherwise, it
    1982                 :             :          * should emit grouping_target.
    1983                 :             :          */
    1984         [ +  + ]:      385637 :         have_grouping = (parse->groupClause || parse->groupingSets ||
    1985   [ +  +  +  +  :      775641 :                          parse->hasAggs || root->hasHavingQual);
                   +  + ]
    1986         [ +  + ]:      390004 :         if (have_grouping)
    1987                 :             :         {
    1988                 :       34142 :             scanjoin_target = make_group_input_target(root, final_target);
    1989                 :             :             scanjoin_target_parallel_safe =
    1990                 :       34142 :                 is_parallel_safe(root, (Node *) scanjoin_target->exprs);
    1991                 :             :         }
    1992                 :             :         else
    1993                 :             :         {
    1994                 :      355862 :             scanjoin_target = grouping_target;
    1995                 :      355862 :             scanjoin_target_parallel_safe = grouping_target_parallel_safe;
    1996                 :             :         }
    1997                 :             : 
    1998                 :             :         /*
    1999                 :             :          * If there are any SRFs in the targetlist, we must separate each of
    2000                 :             :          * these PathTargets into SRF-computing and SRF-free targets.  Replace
    2001                 :             :          * each of the named targets with a SRF-free version, and remember the
    2002                 :             :          * list of additional projection steps we need to add afterwards.
    2003                 :             :          */
    2004         [ +  + ]:      390004 :         if (parse->hasTargetSRFs)
    2005                 :             :         {
    2006                 :             :             /* final_target doesn't recompute any SRFs in sort_input_target */
    2007                 :       10227 :             split_pathtarget_at_srfs(root, final_target, sort_input_target,
    2008                 :             :                                      &final_targets,
    2009                 :             :                                      &final_targets_contain_srfs);
    2010                 :       10227 :             final_target = linitial_node(PathTarget, final_targets);
    2011                 :             :             Assert(!linitial_int(final_targets_contain_srfs));
    2012                 :             :             /* likewise for sort_input_target vs. grouping_target */
    2013                 :       10227 :             split_pathtarget_at_srfs(root, sort_input_target, grouping_target,
    2014                 :             :                                      &sort_input_targets,
    2015                 :             :                                      &sort_input_targets_contain_srfs);
    2016                 :       10227 :             sort_input_target = linitial_node(PathTarget, sort_input_targets);
    2017                 :             :             Assert(!linitial_int(sort_input_targets_contain_srfs));
    2018                 :             :             /* likewise for grouping_target vs. scanjoin_target */
    2019                 :       10227 :             split_pathtarget_at_srfs_grouping(root,
    2020                 :             :                                               grouping_target, scanjoin_target,
    2021                 :             :                                               &grouping_targets,
    2022                 :             :                                               &grouping_targets_contain_srfs);
    2023                 :       10227 :             grouping_target = linitial_node(PathTarget, grouping_targets);
    2024                 :             :             Assert(!linitial_int(grouping_targets_contain_srfs));
    2025                 :             :             /* scanjoin_target will not have any SRFs precomputed for it */
    2026                 :       10227 :             split_pathtarget_at_srfs(root, scanjoin_target, NULL,
    2027                 :             :                                      &scanjoin_targets,
    2028                 :             :                                      &scanjoin_targets_contain_srfs);
    2029                 :       10227 :             scanjoin_target = linitial_node(PathTarget, scanjoin_targets);
    2030                 :             :             Assert(!linitial_int(scanjoin_targets_contain_srfs));
    2031                 :             :         }
    2032                 :             :         else
    2033                 :             :         {
    2034                 :             :             /* initialize lists; for most of these, dummy values are OK */
    2035                 :      379777 :             final_targets = final_targets_contain_srfs = NIL;
    2036                 :      379777 :             sort_input_targets = sort_input_targets_contain_srfs = NIL;
    2037                 :      379777 :             grouping_targets = grouping_targets_contain_srfs = NIL;
    2038                 :      379777 :             scanjoin_targets = list_make1(scanjoin_target);
    2039                 :      379777 :             scanjoin_targets_contain_srfs = NIL;
    2040                 :             :         }
    2041                 :             : 
    2042                 :             :         /* Apply scan/join target. */
    2043                 :      390004 :         scanjoin_target_same_exprs = list_length(scanjoin_targets) == 1
    2044   [ +  +  +  + ]:      390004 :             && equal(scanjoin_target->exprs, current_rel->reltarget->exprs);
    2045                 :      390004 :         apply_scanjoin_target_to_paths(root, current_rel, scanjoin_targets,
    2046                 :             :                                        scanjoin_targets_contain_srfs,
    2047                 :             :                                        scanjoin_target_parallel_safe,
    2048                 :             :                                        scanjoin_target_same_exprs);
    2049                 :             : 
    2050                 :             :         /*
    2051                 :             :          * Save the various upper-rel PathTargets we just computed into
    2052                 :             :          * root->upper_targets[].  The core code doesn't use this, but it
    2053                 :             :          * provides a convenient place for extensions to get at the info.  For
    2054                 :             :          * consistency, we save all the intermediate targets, even though some
    2055                 :             :          * of the corresponding upperrels might not be needed for this query.
    2056                 :             :          */
    2057                 :      390004 :         root->upper_targets[UPPERREL_FINAL] = final_target;
    2058                 :      390004 :         root->upper_targets[UPPERREL_ORDERED] = final_target;
    2059                 :      390004 :         root->upper_targets[UPPERREL_DISTINCT] = sort_input_target;
    2060                 :      390004 :         root->upper_targets[UPPERREL_PARTIAL_DISTINCT] = sort_input_target;
    2061                 :      390004 :         root->upper_targets[UPPERREL_WINDOW] = sort_input_target;
    2062                 :      390004 :         root->upper_targets[UPPERREL_GROUP_AGG] = grouping_target;
    2063                 :             : 
    2064                 :             :         /*
    2065                 :             :          * If we have grouping and/or aggregation, consider ways to implement
    2066                 :             :          * that.  We build a new upperrel representing the output of this
    2067                 :             :          * phase.
    2068                 :             :          */
    2069         [ +  + ]:      390004 :         if (have_grouping)
    2070                 :             :         {
    2071                 :       34142 :             current_rel = create_grouping_paths(root,
    2072                 :             :                                                 current_rel,
    2073                 :             :                                                 grouping_target,
    2074                 :             :                                                 grouping_target_parallel_safe,
    2075                 :             :                                                 gset_data);
    2076                 :             :             /* Fix things up if grouping_target contains SRFs */
    2077         [ +  + ]:       34138 :             if (parse->hasTargetSRFs)
    2078                 :         294 :                 adjust_paths_for_srfs(root, current_rel,
    2079                 :             :                                       grouping_targets,
    2080                 :             :                                       grouping_targets_contain_srfs);
    2081                 :             :         }
    2082                 :             : 
    2083                 :             :         /*
    2084                 :             :          * If we have window functions, consider ways to implement those.  We
    2085                 :             :          * build a new upperrel representing the output of this phase.
    2086                 :             :          */
    2087         [ +  + ]:      390000 :         if (activeWindows)
    2088                 :             :         {
    2089                 :        2326 :             current_rel = create_window_paths(root,
    2090                 :             :                                               current_rel,
    2091                 :             :                                               grouping_target,
    2092                 :             :                                               sort_input_target,
    2093                 :             :                                               sort_input_target_parallel_safe,
    2094                 :             :                                               wflists,
    2095                 :             :                                               activeWindows);
    2096                 :             :             /* Fix things up if sort_input_target contains SRFs */
    2097         [ +  + ]:        2326 :             if (parse->hasTargetSRFs)
    2098                 :           5 :                 adjust_paths_for_srfs(root, current_rel,
    2099                 :             :                                       sort_input_targets,
    2100                 :             :                                       sort_input_targets_contain_srfs);
    2101                 :             :         }
    2102                 :             : 
    2103                 :             :         /*
    2104                 :             :          * If there is a DISTINCT clause, consider ways to implement that. We
    2105                 :             :          * build a new upperrel representing the output of this phase.
    2106                 :             :          */
    2107         [ +  + ]:      390000 :         if (parse->distinctClause)
    2108                 :             :         {
    2109                 :        2017 :             current_rel = create_distinct_paths(root,
    2110                 :             :                                                 current_rel,
    2111                 :             :                                                 sort_input_target);
    2112                 :             :         }
    2113                 :             :     }                           /* end of if (setOperations) */
    2114                 :             : 
    2115                 :             :     /*
    2116                 :             :      * If ORDER BY was given, consider ways to implement that, and generate a
    2117                 :             :      * new upperrel containing only paths that emit the correct ordering and
    2118                 :             :      * project the correct final_target.  We can apply the original
    2119                 :             :      * limit_tuples limit in sort costing here, but only if there are no
    2120                 :             :      * postponed SRFs.
    2121                 :             :      */
    2122         [ +  + ]:      394947 :     if (parse->sortClause)
    2123                 :             :     {
    2124         [ +  + ]:       61265 :         current_rel = create_ordered_paths(root,
    2125                 :             :                                            current_rel,
    2126                 :             :                                            final_target,
    2127                 :             :                                            final_target_parallel_safe,
    2128                 :             :                                            have_postponed_srfs ? -1.0 :
    2129                 :             :                                            limit_tuples);
    2130                 :             :         /* Fix things up if final_target contains SRFs */
    2131         [ +  + ]:       61265 :         if (parse->hasTargetSRFs)
    2132                 :         182 :             adjust_paths_for_srfs(root, current_rel,
    2133                 :             :                                   final_targets,
    2134                 :             :                                   final_targets_contain_srfs);
    2135                 :             :     }
    2136                 :             : 
    2137                 :             :     /*
    2138                 :             :      * Now we are prepared to build the final-output upperrel.
    2139                 :             :      */
    2140                 :      394947 :     final_rel = fetch_upper_rel(root, UPPERREL_FINAL, NULL);
    2141                 :             : 
    2142                 :             :     /*
    2143                 :             :      * If the input rel is marked consider_parallel and there's nothing that's
    2144                 :             :      * not parallel-safe in the LIMIT clause, then the final_rel can be marked
    2145                 :             :      * consider_parallel as well.  Note that if the query has rowMarks or is
    2146                 :             :      * not a SELECT, consider_parallel will be false for every relation in the
    2147                 :             :      * query.
    2148                 :             :      */
    2149   [ +  +  +  + ]:      530948 :     if (current_rel->consider_parallel &&
    2150         [ +  + ]:      271982 :         is_parallel_safe(root, parse->limitOffset) &&
    2151                 :      135981 :         is_parallel_safe(root, parse->limitCount))
    2152                 :      135976 :         final_rel->consider_parallel = true;
    2153                 :             : 
    2154                 :             :     /*
    2155                 :             :      * If the current_rel belongs to a single FDW, so does the final_rel.
    2156                 :             :      */
    2157                 :      394947 :     final_rel->serverid = current_rel->serverid;
    2158                 :      394947 :     final_rel->userid = current_rel->userid;
    2159                 :      394947 :     final_rel->useridiscurrent = current_rel->useridiscurrent;
    2160                 :      394947 :     final_rel->fdwroutine = current_rel->fdwroutine;
    2161                 :             : 
    2162                 :             :     /*
    2163                 :             :      * Generate paths for the final_rel.  Insert all surviving paths, with
    2164                 :             :      * LockRows, Limit, and/or ModifyTable steps added if needed.
    2165                 :             :      */
    2166   [ +  -  +  +  :      806403 :     foreach(lc, current_rel->pathlist)
                   +  + ]
    2167                 :             :     {
    2168                 :      411456 :         Path       *path = (Path *) lfirst(lc);
    2169                 :             : 
    2170                 :             :         /*
    2171                 :             :          * If there is a FOR [KEY] UPDATE/SHARE clause, add the LockRows node.
    2172                 :             :          * (Note: we intentionally test parse->rowMarks not root->rowMarks
    2173                 :             :          * here.  If there are only non-locking rowmarks, they should be
    2174                 :             :          * handled by the ModifyTable node instead.  However, root->rowMarks
    2175                 :             :          * is what goes into the LockRows node.)
    2176                 :             :          */
    2177         [ +  + ]:      411456 :         if (parse->rowMarks)
    2178                 :             :         {
    2179                 :        6827 :             path = (Path *) create_lockrows_path(root, final_rel, path,
    2180                 :             :                                                  root->rowMarks,
    2181                 :             :                                                  assign_special_exec_param(root));
    2182                 :             :         }
    2183                 :             : 
    2184                 :             :         /*
    2185                 :             :          * If there is a LIMIT/OFFSET clause, add the LIMIT node.
    2186                 :             :          */
    2187         [ +  + ]:      411456 :         if (limit_needed(parse))
    2188                 :             :         {
    2189                 :        4197 :             path = (Path *) create_limit_path(root, final_rel, path,
    2190                 :             :                                               parse->limitOffset,
    2191                 :             :                                               parse->limitCount,
    2192                 :             :                                               parse->limitOption,
    2193                 :             :                                               offset_est, count_est);
    2194                 :             :         }
    2195                 :             : 
    2196                 :             :         /*
    2197                 :             :          * If this is an INSERT/UPDATE/DELETE/MERGE, add the ModifyTable node.
    2198                 :             :          */
    2199         [ +  + ]:      411456 :         if (parse->commandType != CMD_SELECT)
    2200                 :             :         {
    2201                 :             :             Index       rootRelation;
    2202                 :       65687 :             List       *resultRelations = NIL;
    2203                 :       65687 :             List       *updateColnosLists = NIL;
    2204                 :       65687 :             List       *withCheckOptionLists = NIL;
    2205                 :       65687 :             List       *returningLists = NIL;
    2206                 :       65687 :             List       *mergeActionLists = NIL;
    2207                 :       65687 :             List       *mergeJoinConditions = NIL;
    2208                 :             :             List       *rowMarks;
    2209                 :             : 
    2210         [ +  + ]:       65687 :             if (bms_membership(root->all_result_relids) == BMS_MULTIPLE)
    2211                 :             :             {
    2212                 :             :                 /* Inherited UPDATE/DELETE/MERGE */
    2213                 :        2327 :                 RelOptInfo *top_result_rel = find_base_rel(root,
    2214                 :             :                                                            parse->resultRelation);
    2215                 :        2327 :                 int         resultRelation = -1;
    2216                 :             : 
    2217                 :             :                 /* Pass the root result rel forward to the executor. */
    2218                 :        2327 :                 rootRelation = parse->resultRelation;
    2219                 :             : 
    2220                 :             :                 /* Add only leaf children to ModifyTable. */
    2221                 :        6821 :                 while ((resultRelation = bms_next_member(root->leaf_result_relids,
    2222         [ +  + ]:        6821 :                                                          resultRelation)) >= 0)
    2223                 :             :                 {
    2224                 :        4494 :                     RelOptInfo *this_result_rel = find_base_rel(root,
    2225                 :             :                                                                 resultRelation);
    2226                 :             : 
    2227                 :             :                     /*
    2228                 :             :                      * Also exclude any leaf rels that have turned dummy since
    2229                 :             :                      * being added to the list, for example, by being excluded
    2230                 :             :                      * by constraint exclusion.
    2231                 :             :                      */
    2232         [ +  + ]:        4494 :                     if (IS_DUMMY_REL(this_result_rel))
    2233                 :         153 :                         continue;
    2234                 :             : 
    2235                 :             :                     /* Build per-target-rel lists needed by ModifyTable */
    2236                 :        4341 :                     resultRelations = lappend_int(resultRelations,
    2237                 :             :                                                   resultRelation);
    2238         [ +  + ]:        4341 :                     if (parse->commandType == CMD_UPDATE)
    2239                 :             :                     {
    2240                 :        2968 :                         List       *update_colnos = root->update_colnos;
    2241                 :             : 
    2242         [ +  - ]:        2968 :                         if (this_result_rel != top_result_rel)
    2243                 :             :                             update_colnos =
    2244                 :        2968 :                                 adjust_inherited_attnums_multilevel(root,
    2245                 :             :                                                                     update_colnos,
    2246                 :             :                                                                     this_result_rel->relid,
    2247                 :             :                                                                     top_result_rel->relid);
    2248                 :        2968 :                         updateColnosLists = lappend(updateColnosLists,
    2249                 :             :                                                     update_colnos);
    2250                 :             :                     }
    2251         [ +  + ]:        4341 :                     if (parse->withCheckOptions)
    2252                 :             :                     {
    2253                 :         416 :                         List       *withCheckOptions = parse->withCheckOptions;
    2254                 :             : 
    2255         [ +  - ]:         416 :                         if (this_result_rel != top_result_rel)
    2256                 :             :                             withCheckOptions = (List *)
    2257                 :         416 :                                 adjust_appendrel_attrs_multilevel(root,
    2258                 :             :                                                                   (Node *) withCheckOptions,
    2259                 :             :                                                                   this_result_rel,
    2260                 :             :                                                                   top_result_rel);
    2261                 :         416 :                         withCheckOptionLists = lappend(withCheckOptionLists,
    2262                 :             :                                                        withCheckOptions);
    2263                 :             :                     }
    2264         [ +  + ]:        4341 :                     if (parse->returningList)
    2265                 :             :                     {
    2266                 :         674 :                         List       *returningList = parse->returningList;
    2267                 :             : 
    2268         [ +  - ]:         674 :                         if (this_result_rel != top_result_rel)
    2269                 :             :                             returningList = (List *)
    2270                 :         674 :                                 adjust_appendrel_attrs_multilevel(root,
    2271                 :             :                                                                   (Node *) returningList,
    2272                 :             :                                                                   this_result_rel,
    2273                 :             :                                                                   top_result_rel);
    2274                 :         674 :                         returningLists = lappend(returningLists,
    2275                 :             :                                                  returningList);
    2276                 :             :                     }
    2277         [ +  + ]:        4341 :                     if (parse->mergeActionList)
    2278                 :             :                     {
    2279                 :             :                         ListCell   *l;
    2280                 :         427 :                         List       *mergeActionList = NIL;
    2281                 :             : 
    2282                 :             :                         /*
    2283                 :             :                          * Copy MergeActions and translate stuff that
    2284                 :             :                          * references attribute numbers.
    2285                 :             :                          */
    2286   [ +  -  +  +  :        1340 :                         foreach(l, parse->mergeActionList)
                   +  + ]
    2287                 :             :                         {
    2288                 :         913 :                             MergeAction *action = lfirst(l),
    2289                 :         913 :                                        *leaf_action = copyObject(action);
    2290                 :             : 
    2291                 :         913 :                             leaf_action->qual =
    2292                 :         913 :                                 adjust_appendrel_attrs_multilevel(root,
    2293                 :             :                                                                   (Node *) action->qual,
    2294                 :             :                                                                   this_result_rel,
    2295                 :             :                                                                   top_result_rel);
    2296                 :         913 :                             leaf_action->targetList = (List *)
    2297                 :         913 :                                 adjust_appendrel_attrs_multilevel(root,
    2298                 :         913 :                                                                   (Node *) action->targetList,
    2299                 :             :                                                                   this_result_rel,
    2300                 :             :                                                                   top_result_rel);
    2301         [ +  + ]:         913 :                             if (leaf_action->commandType == CMD_UPDATE)
    2302                 :         497 :                                 leaf_action->updateColnos =
    2303                 :         497 :                                     adjust_inherited_attnums_multilevel(root,
    2304                 :             :                                                                         action->updateColnos,
    2305                 :             :                                                                         this_result_rel->relid,
    2306                 :             :                                                                         top_result_rel->relid);
    2307                 :         913 :                             mergeActionList = lappend(mergeActionList,
    2308                 :             :                                                       leaf_action);
    2309                 :             :                         }
    2310                 :             : 
    2311                 :         427 :                         mergeActionLists = lappend(mergeActionLists,
    2312                 :             :                                                    mergeActionList);
    2313                 :             :                     }
    2314         [ +  + ]:        4341 :                     if (parse->commandType == CMD_MERGE)
    2315                 :             :                     {
    2316                 :         427 :                         Node       *mergeJoinCondition = parse->mergeJoinCondition;
    2317                 :             : 
    2318         [ +  - ]:         427 :                         if (this_result_rel != top_result_rel)
    2319                 :             :                             mergeJoinCondition =
    2320                 :         427 :                                 adjust_appendrel_attrs_multilevel(root,
    2321                 :             :                                                                   mergeJoinCondition,
    2322                 :             :                                                                   this_result_rel,
    2323                 :             :                                                                   top_result_rel);
    2324                 :         427 :                         mergeJoinConditions = lappend(mergeJoinConditions,
    2325                 :             :                                                       mergeJoinCondition);
    2326                 :             :                     }
    2327                 :             :                 }
    2328                 :             : 
    2329         [ +  + ]:        2327 :                 if (resultRelations == NIL)
    2330                 :             :                 {
    2331                 :             :                     /*
    2332                 :             :                      * We managed to exclude every child rel, so generate a
    2333                 :             :                      * dummy one-relation plan using info for the top target
    2334                 :             :                      * rel (even though that may not be a leaf target).
    2335                 :             :                      * Although it's clear that no data will be updated or
    2336                 :             :                      * deleted, we still need to have a ModifyTable node so
    2337                 :             :                      * that any statement triggers will be executed.  (This
    2338                 :             :                      * could be cleaner if we fixed nodeModifyTable.c to allow
    2339                 :             :                      * zero target relations, but that probably wouldn't be a
    2340                 :             :                      * net win.)
    2341                 :             :                      */
    2342                 :          28 :                     resultRelations = list_make1_int(parse->resultRelation);
    2343         [ +  + ]:          28 :                     if (parse->commandType == CMD_UPDATE)
    2344                 :          26 :                         updateColnosLists = list_make1(root->update_colnos);
    2345         [ -  + ]:          28 :                     if (parse->withCheckOptions)
    2346                 :           0 :                         withCheckOptionLists = list_make1(parse->withCheckOptions);
    2347         [ +  + ]:          28 :                     if (parse->returningList)
    2348                 :          15 :                         returningLists = list_make1(parse->returningList);
    2349         [ +  + ]:          28 :                     if (parse->mergeActionList)
    2350                 :           1 :                         mergeActionLists = list_make1(parse->mergeActionList);
    2351         [ +  + ]:          28 :                     if (parse->commandType == CMD_MERGE)
    2352                 :           1 :                         mergeJoinConditions = list_make1(parse->mergeJoinCondition);
    2353                 :             :                 }
    2354                 :             :             }
    2355                 :             :             else
    2356                 :             :             {
    2357                 :             :                 /* Single-relation INSERT/UPDATE/DELETE/MERGE. */
    2358                 :       63360 :                 rootRelation = 0;   /* there's no separate root rel */
    2359                 :       63360 :                 resultRelations = list_make1_int(parse->resultRelation);
    2360         [ +  + ]:       63360 :                 if (parse->commandType == CMD_UPDATE)
    2361                 :        8885 :                     updateColnosLists = list_make1(root->update_colnos);
    2362         [ +  + ]:       63360 :                 if (parse->withCheckOptions)
    2363                 :         919 :                     withCheckOptionLists = list_make1(parse->withCheckOptions);
    2364         [ +  + ]:       63360 :                 if (parse->returningList)
    2365                 :        2216 :                     returningLists = list_make1(parse->returningList);
    2366         [ +  + ]:       63360 :                 if (parse->mergeActionList)
    2367                 :        1289 :                     mergeActionLists = list_make1(parse->mergeActionList);
    2368         [ +  + ]:       63360 :                 if (parse->commandType == CMD_MERGE)
    2369                 :        1289 :                     mergeJoinConditions = list_make1(parse->mergeJoinCondition);
    2370                 :             :             }
    2371                 :             : 
    2372                 :             :             /*
    2373                 :             :              * If there was a FOR [KEY] UPDATE/SHARE clause, the LockRows node
    2374                 :             :              * will have dealt with fetching non-locked marked rows, else we
    2375                 :             :              * need to have ModifyTable do that.
    2376                 :             :              */
    2377         [ -  + ]:       65687 :             if (parse->rowMarks)
    2378                 :           0 :                 rowMarks = NIL;
    2379                 :             :             else
    2380                 :       65687 :                 rowMarks = root->rowMarks;
    2381                 :             : 
    2382                 :             :             path = (Path *)
    2383                 :       65687 :                 create_modifytable_path(root, final_rel,
    2384                 :             :                                         path,
    2385                 :             :                                         parse->commandType,
    2386                 :       65687 :                                         parse->canSetTag,
    2387                 :       65687 :                                         parse->resultRelation,
    2388                 :             :                                         rootRelation,
    2389                 :             :                                         resultRelations,
    2390                 :             :                                         updateColnosLists,
    2391                 :             :                                         withCheckOptionLists,
    2392                 :             :                                         returningLists,
    2393                 :             :                                         rowMarks,
    2394                 :             :                                         parse->onConflict,
    2395                 :             :                                         mergeActionLists,
    2396                 :             :                                         mergeJoinConditions,
    2397                 :             :                                         parse->forPortionOf,
    2398                 :             :                                         assign_special_exec_param(root));
    2399                 :             :         }
    2400                 :             : 
    2401                 :             :         /* And shove it into final_rel */
    2402                 :      411456 :         add_path(final_rel, path);
    2403                 :             :     }
    2404                 :             : 
    2405                 :             :     /*
    2406                 :             :      * Generate partial paths for final_rel, too, if outer query levels might
    2407                 :             :      * be able to make use of them.
    2408                 :             :      */
    2409   [ +  +  +  + ]:      394947 :     if (final_rel->consider_parallel && root->query_level > 1 &&
    2410         [ +  + ]:       23383 :         !limit_needed(parse))
    2411                 :             :     {
    2412                 :             :         Assert(!parse->rowMarks && parse->commandType == CMD_SELECT);
    2413   [ +  +  +  +  :       23317 :         foreach(lc, current_rel->partial_pathlist)
                   +  + ]
    2414                 :             :         {
    2415                 :         112 :             Path       *partial_path = (Path *) lfirst(lc);
    2416                 :             : 
    2417                 :         112 :             add_partial_path(final_rel, partial_path);
    2418                 :             :         }
    2419                 :             :     }
    2420                 :             : 
    2421                 :      394947 :     extra.limit_needed = limit_needed(parse);
    2422                 :      394947 :     extra.limit_tuples = limit_tuples;
    2423                 :      394947 :     extra.count_est = count_est;
    2424                 :      394947 :     extra.offset_est = offset_est;
    2425                 :             : 
    2426                 :             :     /*
    2427                 :             :      * If there is an FDW that's responsible for all baserels of the query,
    2428                 :             :      * let it consider adding ForeignPaths.
    2429                 :             :      */
    2430         [ +  + ]:      394947 :     if (final_rel->fdwroutine &&
    2431         [ +  + ]:         669 :         final_rel->fdwroutine->GetForeignUpperPaths)
    2432                 :         632 :         final_rel->fdwroutine->GetForeignUpperPaths(root, UPPERREL_FINAL,
    2433                 :             :                                                     current_rel, final_rel,
    2434                 :             :                                                     &extra);
    2435                 :             : 
    2436                 :             :     /* Let extensions possibly add some more paths */
    2437         [ -  + ]:      394947 :     if (create_upper_paths_hook)
    2438                 :           0 :         (*create_upper_paths_hook) (root, UPPERREL_FINAL,
    2439                 :             :                                     current_rel, final_rel, &extra);
    2440                 :             : 
    2441                 :             :     /* Note: currently, we leave it to callers to do set_cheapest() */
    2442                 :      394947 : }
    2443                 :             : 
    2444                 :             : /*
    2445                 :             :  * Do preprocessing for groupingSets clause and related data.
    2446                 :             :  *
    2447                 :             :  * We expect that parse->groupingSets has already been expanded into a flat
    2448                 :             :  * list of grouping sets (that is, just integer Lists of ressortgroupref
    2449                 :             :  * numbers) by expand_grouping_sets().  This function handles the preliminary
    2450                 :             :  * steps of organizing the grouping sets into lists of rollups, and preparing
    2451                 :             :  * annotations which will later be filled in with size estimates.
    2452                 :             :  */
    2453                 :             : static grouping_sets_data *
    2454                 :         910 : preprocess_grouping_sets(PlannerInfo *root)
    2455                 :             : {
    2456                 :         910 :     Query      *parse = root->parse;
    2457                 :             :     List       *sets;
    2458                 :         910 :     int         maxref = 0;
    2459                 :             :     ListCell   *lc_set;
    2460                 :         910 :     grouping_sets_data *gd = palloc0_object(grouping_sets_data);
    2461                 :             : 
    2462                 :             :     /*
    2463                 :             :      * We don't currently make any attempt to optimize the groupClause when
    2464                 :             :      * there are grouping sets, so just duplicate it in processed_groupClause.
    2465                 :             :      */
    2466                 :         910 :     root->processed_groupClause = parse->groupClause;
    2467                 :             : 
    2468                 :             :     /* Detect unhashable and unsortable grouping expressions */
    2469                 :         910 :     gd->any_hashable = false;
    2470                 :         910 :     gd->unhashable_refs = NULL;
    2471                 :         910 :     gd->unsortable_refs = NULL;
    2472                 :         910 :     gd->unsortable_sets = NIL;
    2473                 :             : 
    2474         [ +  + ]:         910 :     if (parse->groupClause)
    2475                 :             :     {
    2476                 :             :         ListCell   *lc;
    2477                 :             : 
    2478   [ +  -  +  +  :        2651 :         foreach(lc, parse->groupClause)
                   +  + ]
    2479                 :             :         {
    2480                 :        1811 :             SortGroupClause *gc = lfirst_node(SortGroupClause, lc);
    2481                 :        1811 :             Index       ref = gc->tleSortGroupRef;
    2482                 :             : 
    2483         [ +  + ]:        1811 :             if (ref > maxref)
    2484                 :        1771 :                 maxref = ref;
    2485                 :             : 
    2486         [ +  + ]:        1811 :             if (!gc->hashable)
    2487                 :          24 :                 gd->unhashable_refs = bms_add_member(gd->unhashable_refs, ref);
    2488                 :             : 
    2489         [ +  + ]:        1811 :             if (!OidIsValid(gc->sortop))
    2490                 :          33 :                 gd->unsortable_refs = bms_add_member(gd->unsortable_refs, ref);
    2491                 :             :         }
    2492                 :             :     }
    2493                 :             : 
    2494                 :             :     /* Allocate workspace array for remapping */
    2495                 :         910 :     gd->tleref_to_colnum_map = (int *) palloc((maxref + 1) * sizeof(int));
    2496                 :             : 
    2497                 :             :     /*
    2498                 :             :      * If we have any unsortable sets, we must extract them before trying to
    2499                 :             :      * prepare rollups. Unsortable sets don't go through
    2500                 :             :      * reorder_grouping_sets, so we must apply the GroupingSetData annotation
    2501                 :             :      * here.
    2502                 :             :      */
    2503         [ +  + ]:         910 :     if (!bms_is_empty(gd->unsortable_refs))
    2504                 :             :     {
    2505                 :          33 :         List       *sortable_sets = NIL;
    2506                 :             :         ListCell   *lc;
    2507                 :             : 
    2508   [ +  -  +  +  :          99 :         foreach(lc, parse->groupingSets)
                   +  + ]
    2509                 :             :         {
    2510                 :          70 :             List       *gset = (List *) lfirst(lc);
    2511                 :             : 
    2512         [ +  + ]:          70 :             if (bms_overlap_list(gd->unsortable_refs, gset))
    2513                 :             :             {
    2514                 :          38 :                 GroupingSetData *gs = makeNode(GroupingSetData);
    2515                 :             : 
    2516                 :          38 :                 gs->set = gset;
    2517                 :          38 :                 gd->unsortable_sets = lappend(gd->unsortable_sets, gs);
    2518                 :             : 
    2519                 :             :                 /*
    2520                 :             :                  * We must enforce here that an unsortable set is hashable;
    2521                 :             :                  * later code assumes this.  Parse analysis only checks that
    2522                 :             :                  * every individual column is either hashable or sortable.
    2523                 :             :                  *
    2524                 :             :                  * Note that passing this test doesn't guarantee we can
    2525                 :             :                  * generate a plan; there might be other showstoppers.
    2526                 :             :                  */
    2527         [ +  + ]:          38 :                 if (bms_overlap_list(gd->unhashable_refs, gset))
    2528         [ +  - ]:           4 :                     ereport(ERROR,
    2529                 :             :                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    2530                 :             :                              errmsg("could not implement GROUP BY"),
    2531                 :             :                              errdetail("Some of the datatypes only support hashing, while others only support sorting.")));
    2532                 :             :             }
    2533                 :             :             else
    2534                 :          32 :                 sortable_sets = lappend(sortable_sets, gset);
    2535                 :             :         }
    2536                 :             : 
    2537         [ +  + ]:          29 :         if (sortable_sets)
    2538                 :          24 :             sets = extract_rollup_sets(sortable_sets);
    2539                 :             :         else
    2540                 :           5 :             sets = NIL;
    2541                 :             :     }
    2542                 :             :     else
    2543                 :         877 :         sets = extract_rollup_sets(parse->groupingSets);
    2544                 :             : 
    2545   [ +  +  +  +  :        2386 :     foreach(lc_set, sets)
                   +  + ]
    2546                 :             :     {
    2547                 :        1480 :         List       *current_sets = (List *) lfirst(lc_set);
    2548                 :        1480 :         RollupData *rollup = makeNode(RollupData);
    2549                 :             :         GroupingSetData *gs;
    2550                 :             : 
    2551                 :             :         /*
    2552                 :             :          * Reorder the current list of grouping sets into correct prefix
    2553                 :             :          * order.  If only one aggregation pass is needed, try to make the
    2554                 :             :          * list match the ORDER BY clause; if more than one pass is needed, we
    2555                 :             :          * don't bother with that.
    2556                 :             :          *
    2557                 :             :          * Note that this reorders the sets from smallest-member-first to
    2558                 :             :          * largest-member-first, and applies the GroupingSetData annotations,
    2559                 :             :          * though the data will be filled in later.
    2560                 :             :          */
    2561         [ +  + ]:        1480 :         current_sets = reorder_grouping_sets(current_sets,
    2562                 :        1480 :                                              (list_length(sets) == 1
    2563                 :             :                                               ? parse->sortClause
    2564                 :             :                                               : NIL));
    2565                 :             : 
    2566                 :             :         /*
    2567                 :             :          * Get the initial (and therefore largest) grouping set.
    2568                 :             :          */
    2569                 :        1480 :         gs = linitial_node(GroupingSetData, current_sets);
    2570                 :             : 
    2571                 :             :         /*
    2572                 :             :          * Order the groupClause appropriately.  If the first grouping set is
    2573                 :             :          * empty, then the groupClause must also be empty; otherwise we have
    2574                 :             :          * to force the groupClause to match that grouping set's order.
    2575                 :             :          *
    2576                 :             :          * (The first grouping set can be empty even though parse->groupClause
    2577                 :             :          * is not empty only if all non-empty grouping sets are unsortable.
    2578                 :             :          * The groupClauses for hashed grouping sets are built later on.)
    2579                 :             :          */
    2580         [ +  + ]:        1480 :         if (gs->set)
    2581                 :        1410 :             rollup->groupClause = preprocess_groupclause(root, gs->set);
    2582                 :             :         else
    2583                 :          70 :             rollup->groupClause = NIL;
    2584                 :             : 
    2585                 :             :         /*
    2586                 :             :          * Is it hashable? We pretend empty sets are hashable even though we
    2587                 :             :          * actually force them not to be hashed later. But don't bother if
    2588                 :             :          * there's nothing but empty sets (since in that case we can't hash
    2589                 :             :          * anything).
    2590                 :             :          */
    2591         [ +  + ]:        1480 :         if (gs->set &&
    2592         [ +  + ]:        1410 :             !bms_overlap_list(gd->unhashable_refs, gs->set))
    2593                 :             :         {
    2594                 :        1390 :             rollup->hashable = true;
    2595                 :        1390 :             gd->any_hashable = true;
    2596                 :             :         }
    2597                 :             : 
    2598                 :             :         /*
    2599                 :             :          * Now that we've pinned down an order for the groupClause for this
    2600                 :             :          * list of grouping sets, we need to remap the entries in the grouping
    2601                 :             :          * sets from sortgrouprefs to plain indices (0-based) into the
    2602                 :             :          * groupClause for this collection of grouping sets. We keep the
    2603                 :             :          * original form for later use, though.
    2604                 :             :          */
    2605                 :        1480 :         rollup->gsets = remap_to_groupclause_idx(rollup->groupClause,
    2606                 :             :                                                  current_sets,
    2607                 :             :                                                  gd->tleref_to_colnum_map);
    2608                 :        1480 :         rollup->gsets_data = current_sets;
    2609                 :             : 
    2610                 :        1480 :         gd->rollups = lappend(gd->rollups, rollup);
    2611                 :             :     }
    2612                 :             : 
    2613         [ +  + ]:         906 :     if (gd->unsortable_sets)
    2614                 :             :     {
    2615                 :             :         /*
    2616                 :             :          * We have not yet pinned down a groupclause for this, but we will
    2617                 :             :          * need index-based lists for estimation purposes. Construct
    2618                 :             :          * hash_sets_idx based on the entire original groupclause for now.
    2619                 :             :          */
    2620                 :          29 :         gd->hash_sets_idx = remap_to_groupclause_idx(parse->groupClause,
    2621                 :             :                                                      gd->unsortable_sets,
    2622                 :             :                                                      gd->tleref_to_colnum_map);
    2623                 :          29 :         gd->any_hashable = true;
    2624                 :             :     }
    2625                 :             : 
    2626                 :         906 :     return gd;
    2627                 :             : }
    2628                 :             : 
    2629                 :             : /*
    2630                 :             :  * Given a groupclause and a list of GroupingSetData, return equivalent sets
    2631                 :             :  * (without annotation) mapped to indexes into the given groupclause.
    2632                 :             :  */
    2633                 :             : static List *
    2634                 :        4152 : remap_to_groupclause_idx(List *groupClause,
    2635                 :             :                          List *gsets,
    2636                 :             :                          int *tleref_to_colnum_map)
    2637                 :             : {
    2638                 :        4152 :     int         ref = 0;
    2639                 :        4152 :     List       *result = NIL;
    2640                 :             :     ListCell   *lc;
    2641                 :             : 
    2642   [ +  +  +  +  :        9866 :     foreach(lc, groupClause)
                   +  + ]
    2643                 :             :     {
    2644                 :        5714 :         SortGroupClause *gc = lfirst_node(SortGroupClause, lc);
    2645                 :             : 
    2646                 :        5714 :         tleref_to_colnum_map[gc->tleSortGroupRef] = ref++;
    2647                 :             :     }
    2648                 :             : 
    2649   [ +  -  +  +  :        9454 :     foreach(lc, gsets)
                   +  + ]
    2650                 :             :     {
    2651                 :        5302 :         List       *set = NIL;
    2652                 :             :         ListCell   *lc2;
    2653                 :        5302 :         GroupingSetData *gs = lfirst_node(GroupingSetData, lc);
    2654                 :             : 
    2655   [ +  +  +  +  :       11725 :         foreach(lc2, gs->set)
                   +  + ]
    2656                 :             :         {
    2657                 :        6423 :             set = lappend_int(set, tleref_to_colnum_map[lfirst_int(lc2)]);
    2658                 :             :         }
    2659                 :             : 
    2660                 :        5302 :         result = lappend(result, set);
    2661                 :             :     }
    2662                 :             : 
    2663                 :        4152 :     return result;
    2664                 :             : }
    2665                 :             : 
    2666                 :             : 
    2667                 :             : /*
    2668                 :             :  * preprocess_rowmarks - set up PlanRowMarks if needed
    2669                 :             :  */
    2670                 :             : static void
    2671                 :      397687 : preprocess_rowmarks(PlannerInfo *root)
    2672                 :             : {
    2673                 :      397687 :     Query      *parse = root->parse;
    2674                 :             :     Bitmapset  *rels;
    2675                 :             :     List       *prowmarks;
    2676                 :             :     ListCell   *l;
    2677                 :             :     int         i;
    2678                 :             : 
    2679         [ +  + ]:      397687 :     if (parse->rowMarks)
    2680                 :             :     {
    2681                 :             :         /*
    2682                 :             :          * We've got trouble if FOR [KEY] UPDATE/SHARE appears inside
    2683                 :             :          * grouping, since grouping renders a reference to individual tuple
    2684                 :             :          * CTIDs invalid.  This is also checked at parse time, but that's
    2685                 :             :          * insufficient because of rule substitution, query pullup, etc.
    2686                 :             :          */
    2687                 :        6580 :         CheckSelectLocking(parse, linitial_node(RowMarkClause,
    2688                 :             :                                                 parse->rowMarks)->strength);
    2689                 :             :     }
    2690                 :             :     else
    2691                 :             :     {
    2692                 :             :         /*
    2693                 :             :          * We only need rowmarks for UPDATE, DELETE, MERGE, or FOR [KEY]
    2694                 :             :          * UPDATE/SHARE.
    2695                 :             :          */
    2696         [ +  + ]:      391107 :         if (parse->commandType != CMD_UPDATE &&
    2697         [ +  + ]:      380598 :             parse->commandType != CMD_DELETE &&
    2698         [ +  + ]:      376823 :             parse->commandType != CMD_MERGE)
    2699                 :      375339 :             return;
    2700                 :             :     }
    2701                 :             : 
    2702                 :             :     /*
    2703                 :             :      * We need to have rowmarks for all base relations except the target. We
    2704                 :             :      * make a bitmapset of all base rels and then remove the items we don't
    2705                 :             :      * need or have FOR [KEY] UPDATE/SHARE marks for.
    2706                 :             :      */
    2707                 :       22348 :     rels = get_relids_in_jointree((Node *) parse->jointree, false, false);
    2708         [ +  + ]:       22348 :     if (parse->resultRelation)
    2709                 :       15768 :         rels = bms_del_member(rels, parse->resultRelation);
    2710                 :             : 
    2711                 :             :     /*
    2712                 :             :      * Convert RowMarkClauses to PlanRowMark representation.
    2713                 :             :      */
    2714                 :       22348 :     prowmarks = NIL;
    2715   [ +  +  +  +  :       29063 :     foreach(l, parse->rowMarks)
                   +  + ]
    2716                 :             :     {
    2717                 :        6715 :         RowMarkClause *rc = lfirst_node(RowMarkClause, l);
    2718                 :        6715 :         RangeTblEntry *rte = rt_fetch(rc->rti, parse->rtable);
    2719                 :             :         PlanRowMark *newrc;
    2720                 :             : 
    2721                 :             :         /*
    2722                 :             :          * Currently, it is syntactically impossible to have FOR UPDATE et al
    2723                 :             :          * applied to an update/delete target rel.  If that ever becomes
    2724                 :             :          * possible, we should drop the target from the PlanRowMark list.
    2725                 :             :          */
    2726                 :             :         Assert(rc->rti != parse->resultRelation);
    2727                 :             : 
    2728                 :             :         /*
    2729                 :             :          * Ignore RowMarkClauses for subqueries; they aren't real tables and
    2730                 :             :          * can't support true locking.  Subqueries that got flattened into the
    2731                 :             :          * main query should be ignored completely.  Any that didn't will get
    2732                 :             :          * ROW_MARK_COPY items in the next loop.
    2733                 :             :          */
    2734         [ +  + ]:        6715 :         if (rte->rtekind != RTE_RELATION)
    2735                 :          46 :             continue;
    2736                 :             : 
    2737                 :        6669 :         rels = bms_del_member(rels, rc->rti);
    2738                 :             : 
    2739                 :        6669 :         newrc = makeNode(PlanRowMark);
    2740                 :        6669 :         newrc->rti = newrc->prti = rc->rti;
    2741                 :        6669 :         newrc->rowmarkId = ++(root->glob->lastRowMarkId);
    2742                 :        6669 :         newrc->markType = select_rowmark_type(rte, rc->strength);
    2743                 :        6669 :         newrc->allMarkTypes = (1 << newrc->markType);
    2744                 :        6669 :         newrc->strength = rc->strength;
    2745                 :        6669 :         newrc->waitPolicy = rc->waitPolicy;
    2746                 :        6669 :         newrc->isParent = false;
    2747                 :             : 
    2748                 :        6669 :         prowmarks = lappend(prowmarks, newrc);
    2749                 :             :     }
    2750                 :             : 
    2751                 :             :     /*
    2752                 :             :      * Now, add rowmarks for any non-target, non-locked base relations.
    2753                 :             :      */
    2754                 :       22348 :     i = 0;
    2755   [ +  -  +  +  :       53315 :     foreach(l, parse->rtable)
                   +  + ]
    2756                 :             :     {
    2757                 :       30967 :         RangeTblEntry *rte = lfirst_node(RangeTblEntry, l);
    2758                 :             :         PlanRowMark *newrc;
    2759                 :             : 
    2760                 :       30967 :         i++;
    2761         [ +  + ]:       30967 :         if (!bms_is_member(i, rels))
    2762                 :       28015 :             continue;
    2763                 :             : 
    2764                 :        2952 :         newrc = makeNode(PlanRowMark);
    2765                 :        2952 :         newrc->rti = newrc->prti = i;
    2766                 :        2952 :         newrc->rowmarkId = ++(root->glob->lastRowMarkId);
    2767                 :        2952 :         newrc->markType = select_rowmark_type(rte, LCS_NONE);
    2768                 :        2952 :         newrc->allMarkTypes = (1 << newrc->markType);
    2769                 :        2952 :         newrc->strength = LCS_NONE;
    2770                 :        2952 :         newrc->waitPolicy = LockWaitBlock;   /* doesn't matter */
    2771                 :        2952 :         newrc->isParent = false;
    2772                 :             : 
    2773                 :        2952 :         prowmarks = lappend(prowmarks, newrc);
    2774                 :             :     }
    2775                 :             : 
    2776                 :       22348 :     root->rowMarks = prowmarks;
    2777                 :             : }
    2778                 :             : 
    2779                 :             : /*
    2780                 :             :  * Select RowMarkType to use for a given table
    2781                 :             :  */
    2782                 :             : RowMarkType
    2783                 :       11512 : select_rowmark_type(RangeTblEntry *rte, LockClauseStrength strength)
    2784                 :             : {
    2785         [ +  + ]:       11512 :     if (rte->rtekind != RTE_RELATION)
    2786                 :             :     {
    2787                 :             :         /* If it's not a table at all, use ROW_MARK_COPY */
    2788                 :        1113 :         return ROW_MARK_COPY;
    2789                 :             :     }
    2790         [ +  + ]:       10399 :     else if (rte->relkind == RELKIND_FOREIGN_TABLE)
    2791                 :             :     {
    2792                 :             :         /* Let the FDW select the rowmark type, if it wants to */
    2793                 :         114 :         FdwRoutine *fdwroutine = GetFdwRoutineByRelId(rte->relid);
    2794                 :             : 
    2795         [ -  + ]:         114 :         if (fdwroutine->GetForeignRowMarkType != NULL)
    2796                 :           0 :             return fdwroutine->GetForeignRowMarkType(rte, strength);
    2797                 :             :         /* Otherwise, use ROW_MARK_COPY by default */
    2798                 :         114 :         return ROW_MARK_COPY;
    2799                 :             :     }
    2800                 :             :     else
    2801                 :             :     {
    2802                 :             :         /* Regular table, apply the appropriate lock type */
    2803   [ +  +  +  +  :       10285 :         switch (strength)
                   +  - ]
    2804                 :             :         {
    2805                 :        2048 :             case LCS_NONE:
    2806                 :             : 
    2807                 :             :                 /*
    2808                 :             :                  * We don't need a tuple lock, only the ability to re-fetch
    2809                 :             :                  * the row.
    2810                 :             :                  */
    2811                 :        2048 :                 return ROW_MARK_REFERENCE;
    2812                 :             :                 break;
    2813                 :        7057 :             case LCS_FORKEYSHARE:
    2814                 :        7057 :                 return ROW_MARK_KEYSHARE;
    2815                 :             :                 break;
    2816                 :         205 :             case LCS_FORSHARE:
    2817                 :         205 :                 return ROW_MARK_SHARE;
    2818                 :             :                 break;
    2819                 :          41 :             case LCS_FORNOKEYUPDATE:
    2820                 :          41 :                 return ROW_MARK_NOKEYEXCLUSIVE;
    2821                 :             :                 break;
    2822                 :         934 :             case LCS_FORUPDATE:
    2823                 :         934 :                 return ROW_MARK_EXCLUSIVE;
    2824                 :             :                 break;
    2825                 :             :         }
    2826         [ #  # ]:           0 :         elog(ERROR, "unrecognized LockClauseStrength %d", (int) strength);
    2827                 :             :         return ROW_MARK_EXCLUSIVE;  /* keep compiler quiet */
    2828                 :             :     }
    2829                 :             : }
    2830                 :             : 
    2831                 :             : /*
    2832                 :             :  * preprocess_limit - do pre-estimation for LIMIT and/or OFFSET clauses
    2833                 :             :  *
    2834                 :             :  * We try to estimate the values of the LIMIT/OFFSET clauses, and pass the
    2835                 :             :  * results back in *count_est and *offset_est.  These variables are set to
    2836                 :             :  * 0 if the corresponding clause is not present, and -1 if it's present
    2837                 :             :  * but we couldn't estimate the value for it.  (The "0" convention is OK
    2838                 :             :  * for OFFSET but a little bit bogus for LIMIT: effectively we estimate
    2839                 :             :  * LIMIT 0 as though it were LIMIT 1.  But this is in line with the planner's
    2840                 :             :  * usual practice of never estimating less than one row.)  These values will
    2841                 :             :  * be passed to create_limit_path, which see if you change this code.
    2842                 :             :  *
    2843                 :             :  * The return value is the suitably adjusted tuple_fraction to use for
    2844                 :             :  * planning the query.  This adjustment is not overridable, since it reflects
    2845                 :             :  * plan actions that grouping_planner() will certainly take, not assumptions
    2846                 :             :  * about context.
    2847                 :             :  */
    2848                 :             : static double
    2849                 :        3740 : preprocess_limit(PlannerInfo *root, double tuple_fraction,
    2850                 :             :                  int64 *offset_est, int64 *count_est)
    2851                 :             : {
    2852                 :        3740 :     Query      *parse = root->parse;
    2853                 :             :     Node       *est;
    2854                 :             :     double      limit_fraction;
    2855                 :             : 
    2856                 :             :     /* Should not be called unless LIMIT or OFFSET */
    2857                 :             :     Assert(parse->limitCount || parse->limitOffset);
    2858                 :             : 
    2859                 :             :     /*
    2860                 :             :      * Try to obtain the clause values.  We use estimate_expression_value
    2861                 :             :      * primarily because it can sometimes do something useful with Params.
    2862                 :             :      */
    2863         [ +  + ]:        3740 :     if (parse->limitCount)
    2864                 :             :     {
    2865                 :        3278 :         est = estimate_expression_value(root, parse->limitCount);
    2866   [ +  -  +  + ]:        3278 :         if (est && IsA(est, Const))
    2867                 :             :         {
    2868         [ -  + ]:        3273 :             if (((Const *) est)->constisnull)
    2869                 :             :             {
    2870                 :             :                 /* NULL indicates LIMIT ALL, ie, no limit */
    2871                 :           0 :                 *count_est = 0; /* treat as not present */
    2872                 :             :             }
    2873                 :             :             else
    2874                 :             :             {
    2875                 :        3273 :                 *count_est = DatumGetInt64(((Const *) est)->constvalue);
    2876         [ +  + ]:        3273 :                 if (*count_est <= 0)
    2877                 :         190 :                     *count_est = 1; /* force to at least 1 */
    2878                 :             :             }
    2879                 :             :         }
    2880                 :             :         else
    2881                 :           5 :             *count_est = -1;    /* can't estimate */
    2882                 :             :     }
    2883                 :             :     else
    2884                 :         462 :         *count_est = 0;         /* not present */
    2885                 :             : 
    2886         [ +  + ]:        3740 :     if (parse->limitOffset)
    2887                 :             :     {
    2888                 :         672 :         est = estimate_expression_value(root, parse->limitOffset);
    2889   [ +  -  +  + ]:         672 :         if (est && IsA(est, Const))
    2890                 :             :         {
    2891         [ -  + ]:         652 :             if (((Const *) est)->constisnull)
    2892                 :             :             {
    2893                 :             :                 /* Treat NULL as no offset; the executor will too */
    2894                 :           0 :                 *offset_est = 0;    /* treat as not present */
    2895                 :             :             }
    2896                 :             :             else
    2897                 :             :             {
    2898                 :         652 :                 *offset_est = DatumGetInt64(((Const *) est)->constvalue);
    2899         [ -  + ]:         652 :                 if (*offset_est < 0)
    2900                 :           0 :                     *offset_est = 0;    /* treat as not present */
    2901                 :             :             }
    2902                 :             :         }
    2903                 :             :         else
    2904                 :          20 :             *offset_est = -1;   /* can't estimate */
    2905                 :             :     }
    2906                 :             :     else
    2907                 :        3068 :         *offset_est = 0;        /* not present */
    2908                 :             : 
    2909         [ +  + ]:        3740 :     if (*count_est != 0)
    2910                 :             :     {
    2911                 :             :         /*
    2912                 :             :          * A LIMIT clause limits the absolute number of tuples returned.
    2913                 :             :          * However, if it's not a constant LIMIT then we have to guess; for
    2914                 :             :          * lack of a better idea, assume 10% of the plan's result is wanted.
    2915                 :             :          */
    2916   [ +  +  +  + ]:        3278 :         if (*count_est < 0 || *offset_est < 0)
    2917                 :             :         {
    2918                 :             :             /* LIMIT or OFFSET is an expression ... punt ... */
    2919                 :          20 :             limit_fraction = 0.10;
    2920                 :             :         }
    2921                 :             :         else
    2922                 :             :         {
    2923                 :             :             /* LIMIT (plus OFFSET, if any) is max number of tuples needed */
    2924                 :        3258 :             limit_fraction = (double) *count_est + (double) *offset_est;
    2925                 :             :         }
    2926                 :             : 
    2927                 :             :         /*
    2928                 :             :          * If we have absolute limits from both caller and LIMIT, use the
    2929                 :             :          * smaller value; likewise if they are both fractional.  If one is
    2930                 :             :          * fractional and the other absolute, we can't easily determine which
    2931                 :             :          * is smaller, but we use the heuristic that the absolute will usually
    2932                 :             :          * be smaller.
    2933                 :             :          */
    2934         [ +  + ]:        3278 :         if (tuple_fraction >= 1.0)
    2935                 :             :         {
    2936         [ +  - ]:           5 :             if (limit_fraction >= 1.0)
    2937                 :             :             {
    2938                 :             :                 /* both absolute */
    2939         [ -  + ]:           5 :                 tuple_fraction = Min(tuple_fraction, limit_fraction);
    2940                 :             :             }
    2941                 :             :             else
    2942                 :             :             {
    2943                 :             :                 /* caller absolute, limit fractional; use caller's value */
    2944                 :             :             }
    2945                 :             :         }
    2946         [ +  + ]:        3273 :         else if (tuple_fraction > 0.0)
    2947                 :             :         {
    2948         [ +  - ]:          83 :             if (limit_fraction >= 1.0)
    2949                 :             :             {
    2950                 :             :                 /* caller fractional, limit absolute; use limit */
    2951                 :          83 :                 tuple_fraction = limit_fraction;
    2952                 :             :             }
    2953                 :             :             else
    2954                 :             :             {
    2955                 :             :                 /* both fractional */
    2956         [ #  # ]:           0 :                 tuple_fraction = Min(tuple_fraction, limit_fraction);
    2957                 :             :             }
    2958                 :             :         }
    2959                 :             :         else
    2960                 :             :         {
    2961                 :             :             /* no info from caller, just use limit */
    2962                 :        3190 :             tuple_fraction = limit_fraction;
    2963                 :             :         }
    2964                 :             :     }
    2965   [ +  +  +  + ]:         462 :     else if (*offset_est != 0 && tuple_fraction > 0.0)
    2966                 :             :     {
    2967                 :             :         /*
    2968                 :             :          * We have an OFFSET but no LIMIT.  This acts entirely differently
    2969                 :             :          * from the LIMIT case: here, we need to increase rather than decrease
    2970                 :             :          * the caller's tuple_fraction, because the OFFSET acts to cause more
    2971                 :             :          * tuples to be fetched instead of fewer.  This only matters if we got
    2972                 :             :          * a tuple_fraction > 0, however.
    2973                 :             :          *
    2974                 :             :          * As above, use 10% if OFFSET is present but unestimatable.
    2975                 :             :          */
    2976         [ -  + ]:          12 :         if (*offset_est < 0)
    2977                 :           0 :             limit_fraction = 0.10;
    2978                 :             :         else
    2979                 :          12 :             limit_fraction = (double) *offset_est;
    2980                 :             : 
    2981                 :             :         /*
    2982                 :             :          * If we have absolute counts from both caller and OFFSET, add them
    2983                 :             :          * together; likewise if they are both fractional.  If one is
    2984                 :             :          * fractional and the other absolute, we want to take the larger, and
    2985                 :             :          * we heuristically assume that's the fractional one.
    2986                 :             :          */
    2987         [ -  + ]:          12 :         if (tuple_fraction >= 1.0)
    2988                 :             :         {
    2989         [ #  # ]:           0 :             if (limit_fraction >= 1.0)
    2990                 :             :             {
    2991                 :             :                 /* both absolute, so add them together */
    2992                 :           0 :                 tuple_fraction += limit_fraction;
    2993                 :             :             }
    2994                 :             :             else
    2995                 :             :             {
    2996                 :             :                 /* caller absolute, limit fractional; use limit */
    2997                 :           0 :                 tuple_fraction = limit_fraction;
    2998                 :             :             }
    2999                 :             :         }
    3000                 :             :         else
    3001                 :             :         {
    3002         [ -  + ]:          12 :             if (limit_fraction >= 1.0)
    3003                 :             :             {
    3004                 :             :                 /* caller fractional, limit absolute; use caller's value */
    3005                 :             :             }
    3006                 :             :             else
    3007                 :             :             {
    3008                 :             :                 /* both fractional, so add them together */
    3009                 :           0 :                 tuple_fraction += limit_fraction;
    3010         [ #  # ]:           0 :                 if (tuple_fraction >= 1.0)
    3011                 :           0 :                     tuple_fraction = 0.0;   /* assume fetch all */
    3012                 :             :             }
    3013                 :             :         }
    3014                 :             :     }
    3015                 :             : 
    3016                 :        3740 :     return tuple_fraction;
    3017                 :             : }
    3018                 :             : 
    3019                 :             : /*
    3020                 :             :  * limit_needed - do we actually need a Limit plan node?
    3021                 :             :  *
    3022                 :             :  * If we have constant-zero OFFSET and constant-null LIMIT, we can skip adding
    3023                 :             :  * a Limit node.  This is worth checking for because "OFFSET 0" is a common
    3024                 :             :  * locution for an optimization fence.  (Because other places in the planner
    3025                 :             :  * merely check whether parse->limitOffset isn't NULL, it will still work as
    3026                 :             :  * an optimization fence --- we're just suppressing unnecessary run-time
    3027                 :             :  * overhead.)
    3028                 :             :  *
    3029                 :             :  * This might look like it could be merged into preprocess_limit, but there's
    3030                 :             :  * a key distinction: here we need hard constants in OFFSET/LIMIT, whereas
    3031                 :             :  * in preprocess_limit it's good enough to consider estimated values.
    3032                 :             :  */
    3033                 :             : bool
    3034                 :      845636 : limit_needed(Query *parse)
    3035                 :             : {
    3036                 :             :     Node       *node;
    3037                 :             : 
    3038                 :      845636 :     node = parse->limitCount;
    3039         [ +  + ]:      845636 :     if (node)
    3040                 :             :     {
    3041         [ +  + ]:        7793 :         if (IsA(node, Const))
    3042                 :             :         {
    3043                 :             :             /* NULL indicates LIMIT ALL, ie, no limit */
    3044         [ +  - ]:        7572 :             if (!((Const *) node)->constisnull)
    3045                 :        7572 :                 return true;    /* LIMIT with a constant value */
    3046                 :             :         }
    3047                 :             :         else
    3048                 :         221 :             return true;        /* non-constant LIMIT */
    3049                 :             :     }
    3050                 :             : 
    3051                 :      837843 :     node = parse->limitOffset;
    3052         [ +  + ]:      837843 :     if (node)
    3053                 :             :     {
    3054         [ +  + ]:        1403 :         if (IsA(node, Const))
    3055                 :             :         {
    3056                 :             :             /* Treat NULL as no offset; the executor would too */
    3057         [ +  - ]:        1125 :             if (!((Const *) node)->constisnull)
    3058                 :             :             {
    3059                 :        1125 :                 int64       offset = DatumGetInt64(((Const *) node)->constvalue);
    3060                 :             : 
    3061         [ +  + ]:        1125 :                 if (offset != 0)
    3062                 :         107 :                     return true;    /* OFFSET with a nonzero value */
    3063                 :             :             }
    3064                 :             :         }
    3065                 :             :         else
    3066                 :         278 :             return true;        /* non-constant OFFSET */
    3067                 :             :     }
    3068                 :             : 
    3069                 :      837458 :     return false;               /* don't need a Limit plan node */
    3070                 :             : }
    3071                 :             : 
    3072                 :             : /*
    3073                 :             :  * preprocess_groupclause - do preparatory work on GROUP BY clause
    3074                 :             :  *
    3075                 :             :  * The idea here is to adjust the ordering of the GROUP BY elements
    3076                 :             :  * (which in itself is semantically insignificant) to match ORDER BY,
    3077                 :             :  * thereby allowing a single sort operation to both implement the ORDER BY
    3078                 :             :  * requirement and set up for a Unique step that implements GROUP BY.
    3079                 :             :  * We also consider partial match between GROUP BY and ORDER BY elements,
    3080                 :             :  * which could allow to implement ORDER BY using the incremental sort.
    3081                 :             :  *
    3082                 :             :  * We also consider other orderings of the GROUP BY elements, which could
    3083                 :             :  * match the sort ordering of other possible plans (eg an indexscan) and
    3084                 :             :  * thereby reduce cost.  This is implemented during the generation of grouping
    3085                 :             :  * paths.  See get_useful_group_keys_orderings() for details.
    3086                 :             :  *
    3087                 :             :  * Note: we need no comparable processing of the distinctClause because
    3088                 :             :  * the parser already enforced that that matches ORDER BY.
    3089                 :             :  *
    3090                 :             :  * Note: we return a fresh List, but its elements are the same
    3091                 :             :  * SortGroupClauses appearing in parse->groupClause.  This is important
    3092                 :             :  * because later processing may modify the processed_groupClause list.
    3093                 :             :  *
    3094                 :             :  * For grouping sets, the order of items is instead forced to agree with that
    3095                 :             :  * of the grouping set (and items not in the grouping set are skipped). The
    3096                 :             :  * work of sorting the order of grouping set elements to match the ORDER BY if
    3097                 :             :  * possible is done elsewhere.
    3098                 :             :  */
    3099                 :             : static List *
    3100                 :        7584 : preprocess_groupclause(PlannerInfo *root, List *force)
    3101                 :             : {
    3102                 :        7584 :     Query      *parse = root->parse;
    3103                 :        7584 :     List       *new_groupclause = NIL;
    3104                 :             :     ListCell   *sl;
    3105                 :             :     ListCell   *gl;
    3106                 :             : 
    3107                 :             :     /* For grouping sets, we need to force the ordering */
    3108         [ +  + ]:        7584 :     if (force)
    3109                 :             :     {
    3110   [ +  -  +  +  :        9704 :         foreach(sl, force)
                   +  + ]
    3111                 :             :         {
    3112                 :        5651 :             Index       ref = lfirst_int(sl);
    3113                 :        5651 :             SortGroupClause *cl = get_sortgroupref_clause(ref, parse->groupClause);
    3114                 :             : 
    3115                 :        5651 :             new_groupclause = lappend(new_groupclause, cl);
    3116                 :             :         }
    3117                 :             : 
    3118                 :        4053 :         return new_groupclause;
    3119                 :             :     }
    3120                 :             : 
    3121                 :             :     /* If no ORDER BY, nothing useful to do here */
    3122         [ +  + ]:        3531 :     if (parse->sortClause == NIL)
    3123                 :        2004 :         return list_copy(parse->groupClause);
    3124                 :             : 
    3125                 :             :     /*
    3126                 :             :      * Scan the ORDER BY clause and construct a list of matching GROUP BY
    3127                 :             :      * items, but only as far as we can make a matching prefix.
    3128                 :             :      *
    3129                 :             :      * This code assumes that the sortClause contains no duplicate items.
    3130                 :             :      */
    3131   [ +  -  +  +  :        3001 :     foreach(sl, parse->sortClause)
                   +  + ]
    3132                 :             :     {
    3133                 :        1995 :         SortGroupClause *sc = lfirst_node(SortGroupClause, sl);
    3134                 :             : 
    3135   [ +  -  +  +  :        2907 :         foreach(gl, parse->groupClause)
                   +  + ]
    3136                 :             :         {
    3137                 :        2386 :             SortGroupClause *gc = lfirst_node(SortGroupClause, gl);
    3138                 :             : 
    3139         [ +  + ]:        2386 :             if (equal(gc, sc))
    3140                 :             :             {
    3141                 :        1474 :                 new_groupclause = lappend(new_groupclause, gc);
    3142                 :        1474 :                 break;
    3143                 :             :             }
    3144                 :             :         }
    3145         [ +  + ]:        1995 :         if (gl == NULL)
    3146                 :         521 :             break;              /* no match, so stop scanning */
    3147                 :             :     }
    3148                 :             : 
    3149                 :             : 
    3150                 :             :     /* If no match at all, no point in reordering GROUP BY */
    3151         [ +  + ]:        1527 :     if (new_groupclause == NIL)
    3152                 :         233 :         return list_copy(parse->groupClause);
    3153                 :             : 
    3154                 :             :     /*
    3155                 :             :      * Add any remaining GROUP BY items to the new list.  We don't require a
    3156                 :             :      * complete match, because even partial match allows ORDER BY to be
    3157                 :             :      * implemented using incremental sort.  Also, give up if there are any
    3158                 :             :      * non-sortable GROUP BY items, since then there's no hope anyway.
    3159                 :             :      */
    3160   [ +  -  +  +  :        2905 :     foreach(gl, parse->groupClause)
                   +  + ]
    3161                 :             :     {
    3162                 :        1611 :         SortGroupClause *gc = lfirst_node(SortGroupClause, gl);
    3163                 :             : 
    3164         [ +  + ]:        1611 :         if (list_member_ptr(new_groupclause, gc))
    3165                 :        1474 :             continue;           /* it matched an ORDER BY item */
    3166         [ -  + ]:         137 :         if (!OidIsValid(gc->sortop)) /* give up, GROUP BY can't be sorted */
    3167                 :           0 :             return list_copy(parse->groupClause);
    3168                 :         137 :         new_groupclause = lappend(new_groupclause, gc);
    3169                 :             :     }
    3170                 :             : 
    3171                 :             :     /* Success --- install the rearranged GROUP BY list */
    3172                 :             :     Assert(list_length(parse->groupClause) == list_length(new_groupclause));
    3173                 :        1294 :     return new_groupclause;
    3174                 :             : }
    3175                 :             : 
    3176                 :             : /*
    3177                 :             :  * Extract lists of grouping sets that can be implemented using a single
    3178                 :             :  * rollup-type aggregate pass each. Returns a list of lists of grouping sets.
    3179                 :             :  *
    3180                 :             :  * Input must be sorted with smallest sets first. Result has each sublist
    3181                 :             :  * sorted with smallest sets first.
    3182                 :             :  *
    3183                 :             :  * We want to produce the absolute minimum possible number of lists here to
    3184                 :             :  * avoid excess sorts. Fortunately, there is an algorithm for this; the problem
    3185                 :             :  * of finding the minimal partition of a partially-ordered set into chains
    3186                 :             :  * (which is what we need, taking the list of grouping sets as a poset ordered
    3187                 :             :  * by set inclusion) can be mapped to the problem of finding the maximum
    3188                 :             :  * cardinality matching on a bipartite graph, which is solvable in polynomial
    3189                 :             :  * time with a worst case of no worse than O(n^2.5) and usually much
    3190                 :             :  * better. Since our N is at most 4096, we don't need to consider fallbacks to
    3191                 :             :  * heuristic or approximate methods.  (Planning time for a 12-d cube is under
    3192                 :             :  * half a second on my modest system even with optimization off and assertions
    3193                 :             :  * on.)
    3194                 :             :  */
    3195                 :             : static List *
    3196                 :         901 : extract_rollup_sets(List *groupingSets)
    3197                 :             : {
    3198                 :         901 :     int         num_sets_raw = list_length(groupingSets);
    3199                 :         901 :     int         num_empty = 0;
    3200                 :         901 :     int         num_sets = 0;   /* distinct sets */
    3201                 :         901 :     int         num_chains = 0;
    3202                 :         901 :     List       *result = NIL;
    3203                 :             :     List      **results;
    3204                 :             :     List      **orig_sets;
    3205                 :             :     Bitmapset **set_masks;
    3206                 :             :     int        *chains;
    3207                 :             :     short     **adjacency;
    3208                 :             :     short      *adjacency_buf;
    3209                 :             :     BipartiteMatchState *state;
    3210                 :             :     int         i;
    3211                 :             :     int         j;
    3212                 :             :     int         j_size;
    3213                 :         901 :     ListCell   *lc1 = list_head(groupingSets);
    3214                 :             :     ListCell   *lc;
    3215                 :             : 
    3216                 :             :     /*
    3217                 :             :      * Start by stripping out empty sets.  The algorithm doesn't require this,
    3218                 :             :      * but the planner currently needs all empty sets to be returned in the
    3219                 :             :      * first list, so we strip them here and add them back after.
    3220                 :             :      */
    3221   [ +  +  +  + ]:        1496 :     while (lc1 && lfirst(lc1) == NIL)
    3222                 :             :     {
    3223                 :         595 :         ++num_empty;
    3224                 :         595 :         lc1 = lnext(groupingSets, lc1);
    3225                 :             :     }
    3226                 :             : 
    3227                 :             :     /* bail out now if it turns out that all we had were empty sets. */
    3228         [ +  + ]:         901 :     if (!lc1)
    3229                 :          70 :         return list_make1(groupingSets);
    3230                 :             : 
    3231                 :             :     /*----------
    3232                 :             :      * We don't strictly need to remove duplicate sets here, but if we don't,
    3233                 :             :      * they tend to become scattered through the result, which is a bit
    3234                 :             :      * confusing (and irritating if we ever decide to optimize them out).
    3235                 :             :      * So we remove them here and add them back after.
    3236                 :             :      *
    3237                 :             :      * For each non-duplicate set, we fill in the following:
    3238                 :             :      *
    3239                 :             :      * orig_sets[i] = list of the original set lists
    3240                 :             :      * set_masks[i] = bitmapset for testing inclusion
    3241                 :             :      * adjacency[i] = array [n, v1, v2, ... vn] of adjacency indices
    3242                 :             :      *
    3243                 :             :      * chains[i] will be the result group this set is assigned to.
    3244                 :             :      *
    3245                 :             :      * We index all of these from 1 rather than 0 because it is convenient
    3246                 :             :      * to leave 0 free for the NIL node in the graph algorithm.
    3247                 :             :      *----------
    3248                 :             :      */
    3249                 :         831 :     orig_sets = palloc0((num_sets_raw + 1) * sizeof(List *));
    3250                 :         831 :     set_masks = palloc0((num_sets_raw + 1) * sizeof(Bitmapset *));
    3251                 :         831 :     adjacency = palloc0((num_sets_raw + 1) * sizeof(short *));
    3252                 :         831 :     adjacency_buf = palloc((num_sets_raw + 1) * sizeof(short));
    3253                 :             : 
    3254                 :         831 :     j_size = 0;
    3255                 :         831 :     j = 0;
    3256                 :         831 :     i = 1;
    3257                 :             : 
    3258   [ +  -  +  +  :        2861 :     for_each_cell(lc, groupingSets, lc1)
                   +  + ]
    3259                 :             :     {
    3260                 :        2030 :         List       *candidate = (List *) lfirst(lc);
    3261                 :        2030 :         Bitmapset  *candidate_set = NULL;
    3262                 :             :         ListCell   *lc2;
    3263                 :        2030 :         int         dup_of = 0;
    3264                 :             : 
    3265   [ +  -  +  +  :        4827 :         foreach(lc2, candidate)
                   +  + ]
    3266                 :             :         {
    3267                 :        2797 :             candidate_set = bms_add_member(candidate_set, lfirst_int(lc2));
    3268                 :             :         }
    3269                 :             : 
    3270                 :             :         /* we can only be a dup if we're the same length as a previous set */
    3271         [ +  + ]:        2030 :         if (j_size == list_length(candidate))
    3272                 :             :         {
    3273                 :             :             int         k;
    3274                 :             : 
    3275         [ +  + ]:        1828 :             for (k = j; k < i; ++k)
    3276                 :             :             {
    3277         [ +  + ]:        1169 :                 if (bms_equal(set_masks[k], candidate_set))
    3278                 :             :                 {
    3279                 :         129 :                     dup_of = k;
    3280                 :         129 :                     break;
    3281                 :             :                 }
    3282                 :             :             }
    3283                 :             :         }
    3284         [ +  - ]:        1242 :         else if (j_size < list_length(candidate))
    3285                 :             :         {
    3286                 :        1242 :             j_size = list_length(candidate);
    3287                 :        1242 :             j = i;
    3288                 :             :         }
    3289                 :             : 
    3290         [ +  + ]:        2030 :         if (dup_of > 0)
    3291                 :             :         {
    3292                 :         129 :             orig_sets[dup_of] = lappend(orig_sets[dup_of], candidate);
    3293                 :         129 :             bms_free(candidate_set);
    3294                 :             :         }
    3295                 :             :         else
    3296                 :             :         {
    3297                 :             :             int         k;
    3298                 :        1901 :             int         n_adj = 0;
    3299                 :             : 
    3300                 :        1901 :             orig_sets[i] = list_make1(candidate);
    3301                 :        1901 :             set_masks[i] = candidate_set;
    3302                 :             : 
    3303                 :             :             /* fill in adjacency list; no need to compare equal-size sets */
    3304                 :             : 
    3305         [ +  + ]:        2973 :             for (k = j - 1; k > 0; --k)
    3306                 :             :             {
    3307         [ +  + ]:        1072 :                 if (bms_is_subset(set_masks[k], candidate_set))
    3308                 :         937 :                     adjacency_buf[++n_adj] = k;
    3309                 :             :             }
    3310                 :             : 
    3311         [ +  + ]:        1901 :             if (n_adj > 0)
    3312                 :             :             {
    3313                 :         513 :                 adjacency_buf[0] = n_adj;
    3314                 :         513 :                 adjacency[i] = palloc((n_adj + 1) * sizeof(short));
    3315                 :         513 :                 memcpy(adjacency[i], adjacency_buf, (n_adj + 1) * sizeof(short));
    3316                 :             :             }
    3317                 :             :             else
    3318                 :        1388 :                 adjacency[i] = NULL;
    3319                 :             : 
    3320                 :        1901 :             ++i;
    3321                 :             :         }
    3322                 :             :     }
    3323                 :             : 
    3324                 :         831 :     num_sets = i - 1;
    3325                 :             : 
    3326                 :             :     /*
    3327                 :             :      * Apply the graph matching algorithm to do the work.
    3328                 :             :      */
    3329                 :         831 :     state = BipartiteMatch(num_sets, num_sets, adjacency);
    3330                 :             : 
    3331                 :             :     /*
    3332                 :             :      * Now, the state->pair* fields have the info we need to assign sets to
    3333                 :             :      * chains. Two sets (u,v) belong to the same chain if pair_uv[u] = v or
    3334                 :             :      * pair_vu[v] = u (both will be true, but we check both so that we can do
    3335                 :             :      * it in one pass)
    3336                 :             :      */
    3337                 :         831 :     chains = palloc0((num_sets + 1) * sizeof(int));
    3338                 :             : 
    3339         [ +  + ]:        2732 :     for (i = 1; i <= num_sets; ++i)
    3340                 :             :     {
    3341                 :        1901 :         int         u = state->pair_vu[i];
    3342                 :        1901 :         int         v = state->pair_uv[i];
    3343                 :             : 
    3344   [ +  +  -  + ]:        1901 :         if (u > 0 && u < i)
    3345                 :           0 :             chains[i] = chains[u];
    3346   [ +  +  +  - ]:        1901 :         else if (v > 0 && v < i)
    3347                 :         491 :             chains[i] = chains[v];
    3348                 :             :         else
    3349                 :        1410 :             chains[i] = ++num_chains;
    3350                 :             :     }
    3351                 :             : 
    3352                 :             :     /* build result lists. */
    3353                 :         831 :     results = palloc0((num_chains + 1) * sizeof(List *));
    3354                 :             : 
    3355         [ +  + ]:        2732 :     for (i = 1; i <= num_sets; ++i)
    3356                 :             :     {
    3357                 :        1901 :         int         c = chains[i];
    3358                 :             : 
    3359                 :             :         Assert(c > 0);
    3360                 :             : 
    3361                 :        1901 :         results[c] = list_concat(results[c], orig_sets[i]);
    3362                 :             :     }
    3363                 :             : 
    3364                 :             :     /* push any empty sets back on the first list. */
    3365         [ +  + ]:        1306 :     while (num_empty-- > 0)
    3366                 :         475 :         results[1] = lcons(NIL, results[1]);
    3367                 :             : 
    3368                 :             :     /* make result list */
    3369         [ +  + ]:        2241 :     for (i = 1; i <= num_chains; ++i)
    3370                 :        1410 :         result = lappend(result, results[i]);
    3371                 :             : 
    3372                 :             :     /*
    3373                 :             :      * Free all the things.
    3374                 :             :      *
    3375                 :             :      * (This is over-fussy for small sets but for large sets we could have
    3376                 :             :      * tied up a nontrivial amount of memory.)
    3377                 :             :      */
    3378                 :         831 :     BipartiteMatchFree(state);
    3379                 :         831 :     pfree(results);
    3380                 :         831 :     pfree(chains);
    3381         [ +  + ]:        2732 :     for (i = 1; i <= num_sets; ++i)
    3382         [ +  + ]:        1901 :         if (adjacency[i])
    3383                 :         513 :             pfree(adjacency[i]);
    3384                 :         831 :     pfree(adjacency);
    3385                 :         831 :     pfree(adjacency_buf);
    3386                 :         831 :     pfree(orig_sets);
    3387         [ +  + ]:        2732 :     for (i = 1; i <= num_sets; ++i)
    3388                 :        1901 :         bms_free(set_masks[i]);
    3389                 :         831 :     pfree(set_masks);
    3390                 :             : 
    3391                 :         831 :     return result;
    3392                 :             : }
    3393                 :             : 
    3394                 :             : /*
    3395                 :             :  * Reorder the elements of a list of grouping sets such that they have correct
    3396                 :             :  * prefix relationships. Also inserts the GroupingSetData annotations.
    3397                 :             :  *
    3398                 :             :  * The input must be ordered with smallest sets first; the result is returned
    3399                 :             :  * with largest sets first.  Note that the result shares no list substructure
    3400                 :             :  * with the input, so it's safe for the caller to modify it later.
    3401                 :             :  *
    3402                 :             :  * If we're passed in a sortclause, we follow its order of columns to the
    3403                 :             :  * extent possible, to minimize the chance that we add unnecessary sorts.
    3404                 :             :  * (We're trying here to ensure that GROUPING SETS ((a,b,c),(c)) ORDER BY c,b,a
    3405                 :             :  * gets implemented in one pass.)
    3406                 :             :  */
    3407                 :             : static List *
    3408                 :        1480 : reorder_grouping_sets(List *groupingSets, List *sortclause)
    3409                 :             : {
    3410                 :             :     ListCell   *lc;
    3411                 :        1480 :     List       *previous = NIL;
    3412                 :        1480 :     List       *result = NIL;
    3413                 :             : 
    3414   [ +  -  +  +  :        4105 :     foreach(lc, groupingSets)
                   +  + ]
    3415                 :             :     {
    3416                 :        2625 :         List       *candidate = (List *) lfirst(lc);
    3417                 :        2625 :         List       *new_elems = list_difference_int(candidate, previous);
    3418                 :        2625 :         GroupingSetData *gs = makeNode(GroupingSetData);
    3419                 :             : 
    3420   [ +  +  +  + ]:        2769 :         while (list_length(sortclause) > list_length(previous) &&
    3421                 :             :                new_elems != NIL)
    3422                 :             :         {
    3423                 :         244 :             SortGroupClause *sc = list_nth(sortclause, list_length(previous));
    3424                 :         244 :             int         ref = sc->tleSortGroupRef;
    3425                 :             : 
    3426         [ +  + ]:         244 :             if (list_member_int(new_elems, ref))
    3427                 :             :             {
    3428                 :         144 :                 previous = lappend_int(previous, ref);
    3429                 :         144 :                 new_elems = list_delete_int(new_elems, ref);
    3430                 :             :             }
    3431                 :             :             else
    3432                 :             :             {
    3433                 :             :                 /* diverged from the sortclause; give up on it */
    3434                 :         100 :                 sortclause = NIL;
    3435                 :         100 :                 break;
    3436                 :             :             }
    3437                 :             :         }
    3438                 :             : 
    3439                 :        2625 :         previous = list_concat(previous, new_elems);
    3440                 :             : 
    3441                 :        2625 :         gs->set = list_copy(previous);
    3442                 :        2625 :         result = lcons(gs, result);
    3443                 :             :     }
    3444                 :             : 
    3445                 :        1480 :     list_free(previous);
    3446                 :             : 
    3447                 :        1480 :     return result;
    3448                 :             : }
    3449                 :             : 
    3450                 :             : /*
    3451                 :             :  * has_volatile_pathkey
    3452                 :             :  *      Returns true if any PathKey in 'keys' has an EquivalenceClass
    3453                 :             :  *      containing a volatile function.  Otherwise returns false.
    3454                 :             :  */
    3455                 :             : static bool
    3456                 :        2031 : has_volatile_pathkey(List *keys)
    3457                 :             : {
    3458                 :             :     ListCell   *lc;
    3459                 :             : 
    3460   [ +  +  +  +  :        4184 :     foreach(lc, keys)
                   +  + ]
    3461                 :             :     {
    3462                 :        2166 :         PathKey    *pathkey = lfirst_node(PathKey, lc);
    3463                 :             : 
    3464         [ +  + ]:        2166 :         if (pathkey->pk_eclass->ec_has_volatile)
    3465                 :          13 :             return true;
    3466                 :             :     }
    3467                 :             : 
    3468                 :        2018 :     return false;
    3469                 :             : }
    3470                 :             : 
    3471                 :             : /*
    3472                 :             :  * adjust_group_pathkeys_for_groupagg
    3473                 :             :  *      Add pathkeys to root->group_pathkeys to reflect the best set of
    3474                 :             :  *      pre-ordered input for ordered aggregates.
    3475                 :             :  *
    3476                 :             :  * We define "best" as the pathkeys that suit the largest number of
    3477                 :             :  * aggregate functions.  We find these by looking at the first ORDER BY /
    3478                 :             :  * DISTINCT aggregate and take the pathkeys for that before searching for
    3479                 :             :  * other aggregates that require the same or a more strict variation of the
    3480                 :             :  * same pathkeys.  We then repeat that process for any remaining aggregates
    3481                 :             :  * with different pathkeys and if we find another set of pathkeys that suits a
    3482                 :             :  * larger number of aggregates then we select those pathkeys instead.
    3483                 :             :  *
    3484                 :             :  * When the best pathkeys are found we also mark each Aggref that can use
    3485                 :             :  * those pathkeys as aggpresorted = true.
    3486                 :             :  *
    3487                 :             :  * Note: When an aggregate function's ORDER BY / DISTINCT clause contains any
    3488                 :             :  * volatile functions, we never make use of these pathkeys.  We want to ensure
    3489                 :             :  * that sorts using volatile functions are done independently in each Aggref
    3490                 :             :  * rather than once at the query level.  If we were to allow this then Aggrefs
    3491                 :             :  * with compatible sort orders would all transition their rows in the same
    3492                 :             :  * order if those pathkeys were deemed to be the best pathkeys to sort on.
    3493                 :             :  * Whereas, if some other set of Aggref's pathkeys happened to be deemed
    3494                 :             :  * better pathkeys to sort on, then the volatile function Aggrefs would be
    3495                 :             :  * left to perform their sorts individually.  To avoid this inconsistent
    3496                 :             :  * behavior which could make Aggref results depend on what other Aggrefs the
    3497                 :             :  * query contains, we always force Aggrefs with volatile functions to perform
    3498                 :             :  * their own sorts.
    3499                 :             :  */
    3500                 :             : static void
    3501                 :        1675 : adjust_group_pathkeys_for_groupagg(PlannerInfo *root)
    3502                 :             : {
    3503                 :        1675 :     List       *grouppathkeys = root->group_pathkeys;
    3504                 :             :     List       *bestpathkeys;
    3505                 :             :     Bitmapset  *bestaggs;
    3506                 :             :     Bitmapset  *unprocessed_aggs;
    3507                 :             :     ListCell   *lc;
    3508                 :             :     int         i;
    3509                 :             : 
    3510                 :             :     /* Shouldn't be here if there are grouping sets */
    3511                 :             :     Assert(root->parse->groupingSets == NIL);
    3512                 :             :     /* Shouldn't be here unless there are some ordered aggregates */
    3513                 :             :     Assert(root->numOrderedAggs > 0);
    3514                 :             : 
    3515                 :             :     /* Do nothing if disabled */
    3516         [ +  + ]:        1675 :     if (!enable_presorted_aggregate)
    3517                 :           5 :         return;
    3518                 :             : 
    3519                 :             :     /*
    3520                 :             :      * Make a first pass over all AggInfos to collect a Bitmapset containing
    3521                 :             :      * the indexes of all AggInfos to be processed below.
    3522                 :             :      */
    3523                 :        1670 :     unprocessed_aggs = NULL;
    3524   [ +  -  +  +  :        3946 :     foreach(lc, root->agginfos)
                   +  + ]
    3525                 :             :     {
    3526                 :        2276 :         AggInfo    *agginfo = lfirst_node(AggInfo, lc);
    3527                 :        2276 :         Aggref     *aggref = linitial_node(Aggref, agginfo->aggrefs);
    3528                 :             : 
    3529         [ +  + ]:        2276 :         if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
    3530                 :         214 :             continue;
    3531                 :             : 
    3532                 :             :         /* Skip unless there's a DISTINCT or ORDER BY clause */
    3533   [ +  +  +  + ]:        2062 :         if (aggref->aggdistinct == NIL && aggref->aggorder == NIL)
    3534                 :         268 :             continue;
    3535                 :             : 
    3536                 :             :         /* Additional safety checks are needed if there's a FILTER clause */
    3537         [ +  + ]:        1794 :         if (aggref->aggfilter != NULL)
    3538                 :             :         {
    3539                 :             :             ListCell   *lc2;
    3540                 :          43 :             bool        allow_presort = true;
    3541                 :             : 
    3542                 :             :             /*
    3543                 :             :              * When the Aggref has a FILTER clause, it's possible that the
    3544                 :             :              * filter removes rows that cannot be sorted because the
    3545                 :             :              * expression to sort by results in an error during its
    3546                 :             :              * evaluation.  This is a problem for presorting as that happens
    3547                 :             :              * before the FILTER, whereas without presorting, the Aggregate
    3548                 :             :              * node will apply the FILTER *before* sorting.  So that we never
    3549                 :             :              * try to sort anything that might error, here we aim to skip over
    3550                 :             :              * any Aggrefs with arguments with expressions which, when
    3551                 :             :              * evaluated, could cause an ERROR.  Vars and Consts are ok. There
    3552                 :             :              * may be more cases that should be allowed, but more thought
    3553                 :             :              * needs to be given.  Err on the side of caution.
    3554                 :             :              */
    3555   [ +  -  +  +  :          83 :             foreach(lc2, aggref->args)
                   +  + ]
    3556                 :             :             {
    3557                 :          58 :                 TargetEntry *tle = (TargetEntry *) lfirst(lc2);
    3558                 :          58 :                 Expr       *expr = tle->expr;
    3559                 :             : 
    3560         [ +  + ]:          68 :                 while (IsA(expr, RelabelType))
    3561                 :          10 :                     expr = (Expr *) (castNode(RelabelType, expr))->arg;
    3562                 :             : 
    3563                 :             :                 /* Common case, Vars and Consts are ok */
    3564   [ +  +  +  + ]:          58 :                 if (IsA(expr, Var) || IsA(expr, Const))
    3565                 :          40 :                     continue;
    3566                 :             : 
    3567                 :             :                 /* Unsupported.  Don't try to presort for this Aggref */
    3568                 :          18 :                 allow_presort = false;
    3569                 :          18 :                 break;
    3570                 :             :             }
    3571                 :             : 
    3572                 :             :             /* Skip unsupported Aggrefs */
    3573         [ +  + ]:          43 :             if (!allow_presort)
    3574                 :          18 :                 continue;
    3575                 :             :         }
    3576                 :             : 
    3577                 :        1776 :         unprocessed_aggs = bms_add_member(unprocessed_aggs,
    3578                 :             :                                           foreach_current_index(lc));
    3579                 :             :     }
    3580                 :             : 
    3581                 :             :     /*
    3582                 :             :      * Now process all the unprocessed_aggs to find the best set of pathkeys
    3583                 :             :      * for the given set of aggregates.
    3584                 :             :      *
    3585                 :             :      * On the first outer loop here 'bestaggs' will be empty.   We'll populate
    3586                 :             :      * this during the first loop using the pathkeys for the very first
    3587                 :             :      * AggInfo then taking any stronger pathkeys from any other AggInfos with
    3588                 :             :      * a more strict set of compatible pathkeys.  Once the outer loop is
    3589                 :             :      * complete, we mark off all the aggregates with compatible pathkeys then
    3590                 :             :      * remove those from the unprocessed_aggs and repeat the process to try to
    3591                 :             :      * find another set of pathkeys that are suitable for a larger number of
    3592                 :             :      * aggregates.  The outer loop will stop when there are not enough
    3593                 :             :      * unprocessed aggregates for it to be possible to find a set of pathkeys
    3594                 :             :      * to suit a larger number of aggregates.
    3595                 :             :      */
    3596                 :        1670 :     bestpathkeys = NIL;
    3597                 :        1670 :     bestaggs = NULL;
    3598         [ +  + ]:        3291 :     while (bms_num_members(unprocessed_aggs) > bms_num_members(bestaggs))
    3599                 :             :     {
    3600                 :        1621 :         Bitmapset  *aggindexes = NULL;
    3601                 :        1621 :         List       *currpathkeys = NIL;
    3602                 :             : 
    3603                 :        1621 :         i = -1;
    3604         [ +  + ]:        3652 :         while ((i = bms_next_member(unprocessed_aggs, i)) >= 0)
    3605                 :             :         {
    3606                 :        2031 :             AggInfo    *agginfo = list_nth_node(AggInfo, root->agginfos, i);
    3607                 :        2031 :             Aggref     *aggref = linitial_node(Aggref, agginfo->aggrefs);
    3608                 :             :             List       *sortlist;
    3609                 :             :             List       *pathkeys;
    3610                 :             : 
    3611         [ +  + ]:        2031 :             if (aggref->aggdistinct != NIL)
    3612                 :         599 :                 sortlist = aggref->aggdistinct;
    3613                 :             :             else
    3614                 :        1432 :                 sortlist = aggref->aggorder;
    3615                 :             : 
    3616                 :        2031 :             pathkeys = make_pathkeys_for_sortclauses(root, sortlist,
    3617                 :             :                                                      aggref->args);
    3618                 :             : 
    3619                 :             :             /*
    3620                 :             :              * Ignore Aggrefs which have volatile functions in their ORDER BY
    3621                 :             :              * or DISTINCT clause.
    3622                 :             :              */
    3623         [ +  + ]:        2031 :             if (has_volatile_pathkey(pathkeys))
    3624                 :             :             {
    3625                 :          13 :                 unprocessed_aggs = bms_del_member(unprocessed_aggs, i);
    3626                 :          13 :                 continue;
    3627                 :             :             }
    3628                 :             : 
    3629                 :             :             /*
    3630                 :             :              * When not set yet, take the pathkeys from the first unprocessed
    3631                 :             :              * aggregate.
    3632                 :             :              */
    3633         [ +  + ]:        2018 :             if (currpathkeys == NIL)
    3634                 :             :             {
    3635                 :        1618 :                 currpathkeys = pathkeys;
    3636                 :             : 
    3637                 :             :                 /* include the GROUP BY pathkeys, if they exist */
    3638         [ +  + ]:        1618 :                 if (grouppathkeys != NIL)
    3639                 :         236 :                     currpathkeys = append_pathkeys(list_copy(grouppathkeys),
    3640                 :             :                                                    currpathkeys);
    3641                 :             : 
    3642                 :             :                 /* record that we found pathkeys for this aggregate */
    3643                 :        1618 :                 aggindexes = bms_add_member(aggindexes, i);
    3644                 :             :             }
    3645                 :             :             else
    3646                 :             :             {
    3647                 :             :                 /* now look for a stronger set of matching pathkeys */
    3648                 :             : 
    3649                 :             :                 /* include the GROUP BY pathkeys, if they exist */
    3650         [ +  + ]:         400 :                 if (grouppathkeys != NIL)
    3651                 :         260 :                     pathkeys = append_pathkeys(list_copy(grouppathkeys),
    3652                 :             :                                                pathkeys);
    3653                 :             : 
    3654                 :             :                 /* are 'pathkeys' compatible or better than 'currpathkeys'? */
    3655   [ +  +  +  - ]:         400 :                 switch (compare_pathkeys(currpathkeys, pathkeys))
    3656                 :             :                 {
    3657                 :          10 :                     case PATHKEYS_BETTER2:
    3658                 :             :                         /* 'pathkeys' are stronger, use these ones instead */
    3659                 :          10 :                         currpathkeys = pathkeys;
    3660                 :             :                         pg_fallthrough;
    3661                 :             : 
    3662                 :          75 :                     case PATHKEYS_BETTER1:
    3663                 :             :                         /* 'pathkeys' are less strict */
    3664                 :             :                         pg_fallthrough;
    3665                 :             : 
    3666                 :             :                     case PATHKEYS_EQUAL:
    3667                 :             :                         /* mark this aggregate as covered by 'currpathkeys' */
    3668                 :          75 :                         aggindexes = bms_add_member(aggindexes, i);
    3669                 :          75 :                         break;
    3670                 :             : 
    3671                 :         325 :                     case PATHKEYS_DIFFERENT:
    3672                 :         325 :                         break;
    3673                 :             :                 }
    3674                 :             :             }
    3675                 :             :         }
    3676                 :             : 
    3677                 :             :         /* remove the aggregates that we've just processed */
    3678                 :        1621 :         unprocessed_aggs = bms_del_members(unprocessed_aggs, aggindexes);
    3679                 :             : 
    3680                 :             :         /*
    3681                 :             :          * If this pass included more aggregates than the previous best then
    3682                 :             :          * use these ones as the best set.
    3683                 :             :          */
    3684         [ +  + ]:        1621 :         if (bms_num_members(aggindexes) > bms_num_members(bestaggs))
    3685                 :             :         {
    3686                 :        1533 :             bestaggs = aggindexes;
    3687                 :        1533 :             bestpathkeys = currpathkeys;
    3688                 :             :         }
    3689                 :             :     }
    3690                 :             : 
    3691                 :             :     /*
    3692                 :             :      * If we found any ordered aggregates, update root->group_pathkeys to add
    3693                 :             :      * the best set of aggregate pathkeys.  Note that bestpathkeys includes
    3694                 :             :      * the original GROUP BY pathkeys already.
    3695                 :             :      */
    3696         [ +  + ]:        1670 :     if (bestpathkeys != NIL)
    3697                 :        1483 :         root->group_pathkeys = bestpathkeys;
    3698                 :             : 
    3699                 :             :     /*
    3700                 :             :      * Now that we've found the best set of aggregates we can set the
    3701                 :             :      * presorted flag to indicate to the executor that it needn't bother
    3702                 :             :      * performing a sort for these Aggrefs.  We're able to do this now as
    3703                 :             :      * there's no chance of a Hash Aggregate plan as create_grouping_paths
    3704                 :             :      * will not mark the GROUP BY as GROUPING_CAN_USE_HASH due to the presence
    3705                 :             :      * of ordered aggregates.
    3706                 :             :      */
    3707                 :        1670 :     i = -1;
    3708         [ +  + ]:        3253 :     while ((i = bms_next_member(bestaggs, i)) >= 0)
    3709                 :             :     {
    3710                 :        1583 :         AggInfo    *agginfo = list_nth_node(AggInfo, root->agginfos, i);
    3711                 :             : 
    3712   [ +  -  +  +  :        3181 :         foreach(lc, agginfo->aggrefs)
                   +  + ]
    3713                 :             :         {
    3714                 :        1598 :             Aggref     *aggref = lfirst_node(Aggref, lc);
    3715                 :             : 
    3716                 :        1598 :             aggref->aggpresorted = true;
    3717                 :             :         }
    3718                 :             :     }
    3719                 :             : }
    3720                 :             : 
    3721                 :             : /*
    3722                 :             :  * Compute query_pathkeys and other pathkeys during plan generation
    3723                 :             :  */
    3724                 :             : static void
    3725                 :      390027 : standard_qp_callback(PlannerInfo *root, void *extra)
    3726                 :             : {
    3727                 :      390027 :     Query      *parse = root->parse;
    3728                 :      390027 :     standard_qp_extra *qp_extra = (standard_qp_extra *) extra;
    3729                 :      390027 :     List       *tlist = root->processed_tlist;
    3730                 :      390027 :     List       *activeWindows = qp_extra->activeWindows;
    3731                 :             : 
    3732                 :             :     /*
    3733                 :             :      * Calculate pathkeys that represent grouping/ordering and/or ordered
    3734                 :             :      * aggregate requirements.
    3735                 :             :      */
    3736         [ +  + ]:      390027 :     if (qp_extra->gset_data)
    3737                 :             :     {
    3738                 :             :         /*
    3739                 :             :          * With grouping sets, just use the first RollupData's groupClause. We
    3740                 :             :          * don't make any effort to optimize grouping clauses when there are
    3741                 :             :          * grouping sets, nor can we combine aggregate ordering keys with
    3742                 :             :          * grouping.
    3743                 :             :          */
    3744                 :         906 :         List       *rollups = qp_extra->gset_data->rollups;
    3745         [ +  + ]:         906 :         List       *groupClause = (rollups ? linitial_node(RollupData, rollups)->groupClause : NIL);
    3746                 :             : 
    3747         [ +  - ]:         906 :         if (grouping_is_sortable(groupClause))
    3748                 :             :         {
    3749                 :             :             bool        sortable;
    3750                 :             : 
    3751                 :             :             /*
    3752                 :             :              * The groupClause is logically below the grouping step.  So if
    3753                 :             :              * there is an RTE entry for the grouping step, we need to remove
    3754                 :             :              * its RT index from the sort expressions before we make PathKeys
    3755                 :             :              * for them.
    3756                 :             :              */
    3757                 :         906 :             root->group_pathkeys =
    3758                 :         906 :                 make_pathkeys_for_sortclauses_extended(root,
    3759                 :             :                                                        &groupClause,
    3760                 :             :                                                        tlist,
    3761                 :             :                                                        false,
    3762                 :         906 :                                                        parse->hasGroupRTE,
    3763                 :             :                                                        &sortable,
    3764                 :             :                                                        false);
    3765                 :             :             Assert(sortable);
    3766                 :         906 :             root->num_groupby_pathkeys = list_length(root->group_pathkeys);
    3767                 :             :         }
    3768                 :             :         else
    3769                 :             :         {
    3770                 :           0 :             root->group_pathkeys = NIL;
    3771                 :           0 :             root->num_groupby_pathkeys = 0;
    3772                 :             :         }
    3773                 :             :     }
    3774   [ +  +  +  + ]:      389121 :     else if (parse->groupClause || root->numOrderedAggs > 0)
    3775                 :        5008 :     {
    3776                 :             :         /*
    3777                 :             :          * With a plain GROUP BY list, we can remove any grouping items that
    3778                 :             :          * are proven redundant by EquivalenceClass processing.  For example,
    3779                 :             :          * we can remove y given "WHERE x = y GROUP BY x, y".  These aren't
    3780                 :             :          * especially common cases, but they're nearly free to detect.  Note
    3781                 :             :          * that we remove redundant items from processed_groupClause but not
    3782                 :             :          * the original parse->groupClause.
    3783                 :             :          */
    3784                 :             :         bool        sortable;
    3785                 :             : 
    3786                 :             :         /*
    3787                 :             :          * Convert group clauses into pathkeys.  Set the ec_sortref field of
    3788                 :             :          * EquivalenceClass'es if it's not set yet.
    3789                 :             :          */
    3790                 :        5008 :         root->group_pathkeys =
    3791                 :        5008 :             make_pathkeys_for_sortclauses_extended(root,
    3792                 :             :                                                    &root->processed_groupClause,
    3793                 :             :                                                    tlist,
    3794                 :             :                                                    true,
    3795                 :             :                                                    false,
    3796                 :             :                                                    &sortable,
    3797                 :             :                                                    true);
    3798         [ -  + ]:        5008 :         if (!sortable)
    3799                 :             :         {
    3800                 :             :             /* Can't sort; no point in considering aggregate ordering either */
    3801                 :           0 :             root->group_pathkeys = NIL;
    3802                 :           0 :             root->num_groupby_pathkeys = 0;
    3803                 :             :         }
    3804                 :             :         else
    3805                 :             :         {
    3806                 :        5008 :             root->num_groupby_pathkeys = list_length(root->group_pathkeys);
    3807                 :             :             /* If we have ordered aggs, consider adding onto group_pathkeys */
    3808         [ +  + ]:        5008 :             if (root->numOrderedAggs > 0)
    3809                 :        1675 :                 adjust_group_pathkeys_for_groupagg(root);
    3810                 :             :         }
    3811                 :             :     }
    3812                 :             :     else
    3813                 :             :     {
    3814                 :      384113 :         root->group_pathkeys = NIL;
    3815                 :      384113 :         root->num_groupby_pathkeys = 0;
    3816                 :             :     }
    3817                 :             : 
    3818                 :             :     /* We consider only the first (bottom) window in pathkeys logic */
    3819         [ +  + ]:      390027 :     if (activeWindows != NIL)
    3820                 :             :     {
    3821                 :        2326 :         WindowClause *wc = linitial_node(WindowClause, activeWindows);
    3822                 :             : 
    3823                 :        2326 :         root->window_pathkeys = make_pathkeys_for_window(root,
    3824                 :             :                                                          wc,
    3825                 :             :                                                          tlist);
    3826                 :             :     }
    3827                 :             :     else
    3828                 :      387701 :         root->window_pathkeys = NIL;
    3829                 :             : 
    3830                 :             :     /*
    3831                 :             :      * As with GROUP BY, we can discard any DISTINCT items that are proven
    3832                 :             :      * redundant by EquivalenceClass processing.  The non-redundant list is
    3833                 :             :      * kept in root->processed_distinctClause, leaving the original
    3834                 :             :      * parse->distinctClause alone.
    3835                 :             :      */
    3836         [ +  + ]:      390027 :     if (parse->distinctClause)
    3837                 :             :     {
    3838                 :             :         bool        sortable;
    3839                 :             : 
    3840                 :             :         /* Make a copy since pathkey processing can modify the list */
    3841                 :        2017 :         root->processed_distinctClause = list_copy(parse->distinctClause);
    3842                 :        2017 :         root->distinct_pathkeys =
    3843                 :        2017 :             make_pathkeys_for_sortclauses_extended(root,
    3844                 :             :                                                    &root->processed_distinctClause,
    3845                 :             :                                                    tlist,
    3846                 :             :                                                    true,
    3847                 :             :                                                    false,
    3848                 :             :                                                    &sortable,
    3849                 :             :                                                    false);
    3850         [ +  + ]:        2017 :         if (!sortable)
    3851                 :           5 :             root->distinct_pathkeys = NIL;
    3852                 :             :     }
    3853                 :             :     else
    3854                 :      388010 :         root->distinct_pathkeys = NIL;
    3855                 :             : 
    3856                 :      390027 :     root->sort_pathkeys =
    3857                 :      390027 :         make_pathkeys_for_sortclauses(root,
    3858                 :             :                                       parse->sortClause,
    3859                 :             :                                       tlist);
    3860                 :             : 
    3861                 :             :     /* setting setop_pathkeys might be useful to the union planner */
    3862         [ +  + ]:      390027 :     if (qp_extra->setop != NULL)
    3863                 :             :     {
    3864                 :             :         List       *groupClauses;
    3865                 :             :         bool        sortable;
    3866                 :             : 
    3867                 :       10734 :         groupClauses = generate_setop_child_grouplist(qp_extra->setop, tlist);
    3868                 :             : 
    3869                 :       10734 :         root->setop_pathkeys =
    3870                 :       10734 :             make_pathkeys_for_sortclauses_extended(root,
    3871                 :             :                                                    &groupClauses,
    3872                 :             :                                                    tlist,
    3873                 :             :                                                    false,
    3874                 :             :                                                    false,
    3875                 :             :                                                    &sortable,
    3876                 :             :                                                    false);
    3877         [ +  + ]:       10734 :         if (!sortable)
    3878                 :         120 :             root->setop_pathkeys = NIL;
    3879                 :             :     }
    3880                 :             :     else
    3881                 :      379293 :         root->setop_pathkeys = NIL;
    3882                 :             : 
    3883                 :             :     /*
    3884                 :             :      * Figure out whether we want a sorted result from query_planner.
    3885                 :             :      *
    3886                 :             :      * If we have a sortable GROUP BY clause, then we want a result sorted
    3887                 :             :      * properly for grouping.  Otherwise, if we have window functions to
    3888                 :             :      * evaluate, we try to sort for the first window.  Otherwise, if there's a
    3889                 :             :      * sortable DISTINCT clause that's more rigorous than the ORDER BY clause,
    3890                 :             :      * we try to produce output that's sufficiently well sorted for the
    3891                 :             :      * DISTINCT.  Otherwise, if there is an ORDER BY clause, we want to sort
    3892                 :             :      * by the ORDER BY clause.  Otherwise, if we're a subquery being planned
    3893                 :             :      * for a set operation which can benefit from presorted results and have a
    3894                 :             :      * sortable targetlist, we want to sort by the target list.
    3895                 :             :      *
    3896                 :             :      * Note: if we have both ORDER BY and GROUP BY, and ORDER BY is a superset
    3897                 :             :      * of GROUP BY, it would be tempting to request sort by ORDER BY --- but
    3898                 :             :      * that might just leave us failing to exploit an available sort order at
    3899                 :             :      * all.  Needs more thought.  The choice for DISTINCT versus ORDER BY is
    3900                 :             :      * much easier, since we know that the parser ensured that one is a
    3901                 :             :      * superset of the other.
    3902                 :             :      */
    3903         [ +  + ]:      390027 :     if (root->group_pathkeys)
    3904                 :        5512 :         root->query_pathkeys = root->group_pathkeys;
    3905         [ +  + ]:      384515 :     else if (root->window_pathkeys)
    3906                 :        1871 :         root->query_pathkeys = root->window_pathkeys;
    3907         [ +  + ]:      765288 :     else if (list_length(root->distinct_pathkeys) >
    3908                 :      382644 :              list_length(root->sort_pathkeys))
    3909                 :        1607 :         root->query_pathkeys = root->distinct_pathkeys;
    3910         [ +  + ]:      381037 :     else if (root->sort_pathkeys)
    3911                 :       55779 :         root->query_pathkeys = root->sort_pathkeys;
    3912         [ +  + ]:      325258 :     else if (root->setop_pathkeys != NIL)
    3913                 :        9730 :         root->query_pathkeys = root->setop_pathkeys;
    3914                 :             :     else
    3915                 :      315528 :         root->query_pathkeys = NIL;
    3916                 :      390027 : }
    3917                 :             : 
    3918                 :             : /*
    3919                 :             :  * Estimate number of groups produced by grouping clauses (1 if not grouping)
    3920                 :             :  *
    3921                 :             :  * path_rows: number of output rows from scan/join step
    3922                 :             :  * gd: grouping sets data including list of grouping sets and their clauses
    3923                 :             :  * target_list: target list containing group clause references
    3924                 :             :  *
    3925                 :             :  * If doing grouping sets, we also annotate the gsets data with the estimates
    3926                 :             :  * for each set and each individual rollup list, with a view to later
    3927                 :             :  * determining whether some combination of them could be hashed instead.
    3928                 :             :  */
    3929                 :             : static double
    3930                 :       41134 : get_number_of_groups(PlannerInfo *root,
    3931                 :             :                      double path_rows,
    3932                 :             :                      grouping_sets_data *gd,
    3933                 :             :                      List *target_list)
    3934                 :             : {
    3935                 :       41134 :     Query      *parse = root->parse;
    3936                 :             :     double      dNumGroups;
    3937                 :             : 
    3938         [ +  + ]:       41134 :     if (parse->groupClause)
    3939                 :             :     {
    3940                 :             :         List       *groupExprs;
    3941                 :             : 
    3942         [ +  + ]:        8788 :         if (parse->groupingSets)
    3943                 :             :         {
    3944                 :             :             /* Add up the estimates for each grouping set */
    3945                 :             :             ListCell   *lc;
    3946                 :             : 
    3947                 :             :             Assert(gd);         /* keep Coverity happy */
    3948                 :             : 
    3949                 :         836 :             dNumGroups = 0;
    3950                 :             : 
    3951   [ +  +  +  +  :        2246 :             foreach(lc, gd->rollups)
                   +  + ]
    3952                 :             :             {
    3953                 :        1410 :                 RollupData *rollup = lfirst_node(RollupData, lc);
    3954                 :             :                 ListCell   *lc2;
    3955                 :             :                 ListCell   *lc3;
    3956                 :             : 
    3957                 :        1410 :                 groupExprs = get_sortgrouplist_exprs(rollup->groupClause,
    3958                 :             :                                                      target_list);
    3959                 :             : 
    3960                 :        1410 :                 rollup->numGroups = 0.0;
    3961                 :             : 
    3962   [ +  -  +  +  :        3915 :                 forboth(lc2, rollup->gsets, lc3, rollup->gsets_data)
          +  -  +  +  +  
             +  +  -  +  
                      + ]
    3963                 :             :                 {
    3964                 :        2505 :                     List       *gset = (List *) lfirst(lc2);
    3965                 :        2505 :                     GroupingSetData *gs = lfirst_node(GroupingSetData, lc3);
    3966                 :        2505 :                     double      numGroups = estimate_num_groups(root,
    3967                 :             :                                                                 groupExprs,
    3968                 :             :                                                                 path_rows,
    3969                 :             :                                                                 &gset,
    3970                 :             :                                                                 NULL);
    3971                 :             : 
    3972                 :        2505 :                     gs->numGroups = numGroups;
    3973                 :        2505 :                     rollup->numGroups += numGroups;
    3974                 :             :                 }
    3975                 :             : 
    3976                 :        1410 :                 dNumGroups += rollup->numGroups;
    3977                 :             :             }
    3978                 :             : 
    3979         [ +  + ]:         836 :             if (gd->hash_sets_idx)
    3980                 :             :             {
    3981                 :             :                 ListCell   *lc2;
    3982                 :             : 
    3983                 :          29 :                 gd->dNumHashGroups = 0;
    3984                 :             : 
    3985                 :          29 :                 groupExprs = get_sortgrouplist_exprs(parse->groupClause,
    3986                 :             :                                                      target_list);
    3987                 :             : 
    3988   [ +  -  +  +  :          63 :                 forboth(lc, gd->hash_sets_idx, lc2, gd->unsortable_sets)
          +  -  +  +  +  
             +  +  -  +  
                      + ]
    3989                 :             :                 {
    3990                 :          34 :                     List       *gset = (List *) lfirst(lc);
    3991                 :          34 :                     GroupingSetData *gs = lfirst_node(GroupingSetData, lc2);
    3992                 :          34 :                     double      numGroups = estimate_num_groups(root,
    3993                 :             :                                                                 groupExprs,
    3994                 :             :                                                                 path_rows,
    3995                 :             :                                                                 &gset,
    3996                 :             :                                                                 NULL);
    3997                 :             : 
    3998                 :          34 :                     gs->numGroups = numGroups;
    3999                 :          34 :                     gd->dNumHashGroups += numGroups;
    4000                 :             :                 }
    4001                 :             : 
    4002                 :          29 :                 dNumGroups += gd->dNumHashGroups;
    4003                 :             :             }
    4004                 :             :         }
    4005                 :             :         else
    4006                 :             :         {
    4007                 :             :             /* Plain GROUP BY -- estimate based on optimized groupClause */
    4008                 :        7952 :             groupExprs = get_sortgrouplist_exprs(root->processed_groupClause,
    4009                 :             :                                                  target_list);
    4010                 :             : 
    4011                 :        7952 :             dNumGroups = estimate_num_groups(root, groupExprs, path_rows,
    4012                 :             :                                              NULL, NULL);
    4013                 :             :         }
    4014                 :             :     }
    4015         [ +  + ]:       32346 :     else if (parse->groupingSets)
    4016                 :             :     {
    4017                 :             :         /* Empty grouping sets ... one result row for each one */
    4018                 :          45 :         dNumGroups = list_length(parse->groupingSets);
    4019                 :             :     }
    4020   [ -  +  -  - ]:       32301 :     else if (parse->hasAggs || root->hasHavingQual)
    4021                 :             :     {
    4022                 :             :         /* Plain aggregation, one result row */
    4023                 :       32301 :         dNumGroups = 1;
    4024                 :             :     }
    4025                 :             :     else
    4026                 :             :     {
    4027                 :             :         /* Not grouping */
    4028                 :           0 :         dNumGroups = 1;
    4029                 :             :     }
    4030                 :             : 
    4031                 :       41134 :     return dNumGroups;
    4032                 :             : }
    4033                 :             : 
    4034                 :             : /*
    4035                 :             :  * create_grouping_paths
    4036                 :             :  *
    4037                 :             :  * Build a new upperrel containing Paths for grouping and/or aggregation.
    4038                 :             :  * Along the way, we also build an upperrel for Paths which are partially
    4039                 :             :  * grouped and/or aggregated.  A partially grouped and/or aggregated path
    4040                 :             :  * needs a FinalizeAggregate node to complete the aggregation.  Currently,
    4041                 :             :  * the only partially grouped paths we build are also partial paths; that
    4042                 :             :  * is, they need a Gather and then a FinalizeAggregate.
    4043                 :             :  *
    4044                 :             :  * input_rel: contains the source-data Paths
    4045                 :             :  * target: the pathtarget for the result Paths to compute
    4046                 :             :  * gd: grouping sets data including list of grouping sets and their clauses
    4047                 :             :  *
    4048                 :             :  * Note: all Paths in input_rel are expected to return the target computed
    4049                 :             :  * by make_group_input_target.
    4050                 :             :  */
    4051                 :             : static RelOptInfo *
    4052                 :       34142 : create_grouping_paths(PlannerInfo *root,
    4053                 :             :                       RelOptInfo *input_rel,
    4054                 :             :                       PathTarget *target,
    4055                 :             :                       bool target_parallel_safe,
    4056                 :             :                       grouping_sets_data *gd)
    4057                 :             : {
    4058                 :       34142 :     Query      *parse = root->parse;
    4059                 :             :     RelOptInfo *grouped_rel;
    4060                 :             :     RelOptInfo *partially_grouped_rel;
    4061                 :             :     AggClauseCosts agg_costs;
    4062                 :             : 
    4063   [ +  -  +  -  :      204852 :     MemSet(&agg_costs, 0, sizeof(AggClauseCosts));
          +  -  +  -  +  
                      + ]
    4064                 :       34142 :     get_agg_clause_costs(root, AGGSPLIT_SIMPLE, &agg_costs);
    4065                 :             : 
    4066                 :             :     /*
    4067                 :             :      * Create grouping relation to hold fully aggregated grouping and/or
    4068                 :             :      * aggregation paths.
    4069                 :             :      */
    4070                 :       34142 :     grouped_rel = make_grouping_rel(root, input_rel, target,
    4071                 :             :                                     target_parallel_safe, parse->havingQual);
    4072                 :             : 
    4073                 :             :     /*
    4074                 :             :      * Create either paths for a degenerate grouping or paths for ordinary
    4075                 :             :      * grouping, as appropriate.
    4076                 :             :      */
    4077         [ +  + ]:       34142 :     if (is_degenerate_grouping(root))
    4078                 :          45 :         create_degenerate_grouping_paths(root, input_rel, grouped_rel);
    4079                 :             :     else
    4080                 :             :     {
    4081                 :       34097 :         int         flags = 0;
    4082                 :             :         GroupPathExtraData extra;
    4083                 :             : 
    4084                 :             :         /*
    4085                 :             :          * Determine whether it's possible to perform sort-based
    4086                 :             :          * implementations of grouping.  (Note that if processed_groupClause
    4087                 :             :          * is empty, grouping_is_sortable() is trivially true, and all the
    4088                 :             :          * pathkeys_contained_in() tests will succeed too, so that we'll
    4089                 :             :          * consider every surviving input path.)
    4090                 :             :          *
    4091                 :             :          * If we have grouping sets, we might be able to sort some but not all
    4092                 :             :          * of them; in this case, we need can_sort to be true as long as we
    4093                 :             :          * must consider any sorted-input plan.
    4094                 :             :          */
    4095   [ +  +  +  + ]:       34097 :         if ((gd && gd->rollups != NIL)
    4096         [ +  + ]:       33221 :             || grouping_is_sortable(root->processed_groupClause))
    4097                 :       34092 :             flags |= GROUPING_CAN_USE_SORT;
    4098                 :             : 
    4099                 :             :         /*
    4100                 :             :          * Determine whether we should consider hash-based implementations of
    4101                 :             :          * grouping.
    4102                 :             :          *
    4103                 :             :          * Hashed aggregation only applies if we're grouping. If we have
    4104                 :             :          * grouping sets, some groups might be hashable but others not; in
    4105                 :             :          * this case we set can_hash true as long as there is nothing globally
    4106                 :             :          * preventing us from hashing (and we should therefore consider plans
    4107                 :             :          * with hashes).
    4108                 :             :          *
    4109                 :             :          * Executor doesn't support hashed aggregation with DISTINCT or ORDER
    4110                 :             :          * BY aggregates.  (Doing so would imply storing *all* the input
    4111                 :             :          * values in the hash table, and/or running many sorts in parallel,
    4112                 :             :          * either of which seems like a certain loser.)  We similarly don't
    4113                 :             :          * support ordered-set aggregates in hashed aggregation, but that case
    4114                 :             :          * is also included in the numOrderedAggs count.
    4115                 :             :          *
    4116                 :             :          * Note: grouping_is_hashable() is much more expensive to check than
    4117                 :             :          * the other gating conditions, so we want to do it last.
    4118                 :             :          */
    4119         [ +  + ]:       34097 :         if ((parse->groupClause != NIL &&
    4120   [ +  +  +  +  :        7700 :              root->numOrderedAggs == 0 &&
                   +  + ]
    4121                 :        3333 :              (gd ? gd->any_hashable : grouping_is_hashable(root->processed_groupClause))))
    4122                 :        4137 :             flags |= GROUPING_CAN_USE_HASH;
    4123                 :             : 
    4124                 :             :         /*
    4125                 :             :          * Determine whether partial aggregation is possible.
    4126                 :             :          */
    4127         [ +  + ]:       34097 :         if (can_partial_agg(root))
    4128                 :       30161 :             flags |= GROUPING_CAN_PARTIAL_AGG;
    4129                 :             : 
    4130                 :       34097 :         extra.flags = flags;
    4131                 :       34097 :         extra.target_parallel_safe = target_parallel_safe;
    4132                 :       34097 :         extra.havingQual = parse->havingQual;
    4133                 :       34097 :         extra.targetList = parse->targetList;
    4134                 :       34097 :         extra.partial_costs_set = false;
    4135                 :             : 
    4136                 :             :         /*
    4137                 :             :          * Determine whether partitionwise aggregation is in theory possible.
    4138                 :             :          * It can be disabled by the user, and for now, we don't try to
    4139                 :             :          * support grouping sets.  create_ordinary_grouping_paths() will check
    4140                 :             :          * additional conditions, such as whether input_rel is partitioned.
    4141                 :             :          */
    4142   [ +  +  +  + ]:       34097 :         if (enable_partitionwise_aggregate && !parse->groupingSets)
    4143                 :         580 :             extra.patype = PARTITIONWISE_AGGREGATE_FULL;
    4144                 :             :         else
    4145                 :       33517 :             extra.patype = PARTITIONWISE_AGGREGATE_NONE;
    4146                 :             : 
    4147                 :       34097 :         create_ordinary_grouping_paths(root, input_rel, grouped_rel,
    4148                 :             :                                        &agg_costs, gd, &extra,
    4149                 :             :                                        &partially_grouped_rel);
    4150                 :             :     }
    4151                 :             : 
    4152                 :       34138 :     set_cheapest(grouped_rel);
    4153                 :       34138 :     return grouped_rel;
    4154                 :             : }
    4155                 :             : 
    4156                 :             : /*
    4157                 :             :  * make_grouping_rel
    4158                 :             :  *
    4159                 :             :  * Create a new grouping rel and set basic properties.
    4160                 :             :  *
    4161                 :             :  * input_rel represents the underlying scan/join relation.
    4162                 :             :  * target is the output expected from the grouping relation.
    4163                 :             :  */
    4164                 :             : static RelOptInfo *
    4165                 :       35937 : make_grouping_rel(PlannerInfo *root, RelOptInfo *input_rel,
    4166                 :             :                   PathTarget *target, bool target_parallel_safe,
    4167                 :             :                   Node *havingQual)
    4168                 :             : {
    4169                 :             :     RelOptInfo *grouped_rel;
    4170                 :             : 
    4171   [ +  +  +  +  :       35937 :     if (IS_OTHER_REL(input_rel))
                   -  + ]
    4172                 :             :     {
    4173                 :        1795 :         grouped_rel = fetch_upper_rel(root, UPPERREL_GROUP_AGG,
    4174                 :             :                                       input_rel->relids);
    4175                 :        1795 :         grouped_rel->reloptkind = RELOPT_OTHER_UPPER_REL;
    4176                 :             :     }
    4177                 :             :     else
    4178                 :             :     {
    4179                 :             :         /*
    4180                 :             :          * By tradition, the relids set for the main grouping relation is
    4181                 :             :          * NULL.  (This could be changed, but might require adjustments
    4182                 :             :          * elsewhere.)
    4183                 :             :          */
    4184                 :       34142 :         grouped_rel = fetch_upper_rel(root, UPPERREL_GROUP_AGG, NULL);
    4185                 :             :     }
    4186                 :             : 
    4187                 :             :     /* Set target. */
    4188                 :       35937 :     grouped_rel->reltarget = target;
    4189                 :             : 
    4190                 :             :     /*
    4191                 :             :      * If the input relation is not parallel-safe, then the grouped relation
    4192                 :             :      * can't be parallel-safe, either.  Otherwise, it's parallel-safe if the
    4193                 :             :      * target list and HAVING quals are parallel-safe.
    4194                 :             :      */
    4195   [ +  +  +  +  :       58994 :     if (input_rel->consider_parallel && target_parallel_safe &&
                   +  + ]
    4196                 :       23057 :         is_parallel_safe(root, havingQual))
    4197                 :       23032 :         grouped_rel->consider_parallel = true;
    4198                 :             : 
    4199                 :             :     /* Assume that the same path generation strategies are allowed */
    4200                 :       35937 :     grouped_rel->pgs_mask = input_rel->pgs_mask;
    4201                 :             : 
    4202                 :             :     /*
    4203                 :             :      * If the input rel belongs to a single FDW, so does the grouped rel.
    4204                 :             :      */
    4205                 :       35937 :     grouped_rel->serverid = input_rel->serverid;
    4206                 :       35937 :     grouped_rel->userid = input_rel->userid;
    4207                 :       35937 :     grouped_rel->useridiscurrent = input_rel->useridiscurrent;
    4208                 :       35937 :     grouped_rel->fdwroutine = input_rel->fdwroutine;
    4209                 :             : 
    4210                 :       35937 :     return grouped_rel;
    4211                 :             : }
    4212                 :             : 
    4213                 :             : /*
    4214                 :             :  * is_degenerate_grouping
    4215                 :             :  *
    4216                 :             :  * A degenerate grouping is one in which the query has a HAVING qual and/or
    4217                 :             :  * grouping sets, but no aggregates and no GROUP BY (which implies that the
    4218                 :             :  * grouping sets are all empty).
    4219                 :             :  */
    4220                 :             : static bool
    4221                 :       34142 : is_degenerate_grouping(PlannerInfo *root)
    4222                 :             : {
    4223                 :       34142 :     Query      *parse = root->parse;
    4224                 :             : 
    4225         [ +  + ]:       32959 :     return (root->hasHavingQual || parse->groupingSets) &&
    4226   [ +  +  +  +  :       67101 :         !parse->hasAggs && parse->groupClause == NIL;
                   +  + ]
    4227                 :             : }
    4228                 :             : 
    4229                 :             : /*
    4230                 :             :  * create_degenerate_grouping_paths
    4231                 :             :  *
    4232                 :             :  * When the grouping is degenerate (see is_degenerate_grouping), we are
    4233                 :             :  * supposed to emit either zero or one row for each grouping set depending on
    4234                 :             :  * whether HAVING succeeds.  Furthermore, there cannot be any variables in
    4235                 :             :  * either HAVING or the targetlist, so we actually do not need the FROM table
    4236                 :             :  * at all! We can just throw away the plan-so-far and generate a Result node.
    4237                 :             :  * This is a sufficiently unusual corner case that it's not worth contorting
    4238                 :             :  * the structure of this module to avoid having to generate the earlier paths
    4239                 :             :  * in the first place.
    4240                 :             :  */
    4241                 :             : static void
    4242                 :          45 : create_degenerate_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel,
    4243                 :             :                                  RelOptInfo *grouped_rel)
    4244                 :             : {
    4245                 :          45 :     Query      *parse = root->parse;
    4246                 :             :     int         nrows;
    4247                 :             :     Path       *path;
    4248                 :             : 
    4249                 :          45 :     nrows = list_length(parse->groupingSets);
    4250         [ +  + ]:          45 :     if (nrows > 1)
    4251                 :             :     {
    4252                 :             :         /*
    4253                 :             :          * Doesn't seem worthwhile writing code to cons up a generate_series
    4254                 :             :          * or a values scan to emit multiple rows. Instead just make N clones
    4255                 :             :          * and append them.  (With a volatile HAVING clause, this means you
    4256                 :             :          * might get between 0 and N output rows. Offhand I think that's
    4257                 :             :          * desired.)
    4258                 :             :          */
    4259                 :          10 :         AppendPathInput append = {0};
    4260                 :             : 
    4261         [ +  + ]:          30 :         while (--nrows >= 0)
    4262                 :             :         {
    4263                 :             :             path = (Path *)
    4264                 :          20 :                 create_group_result_path(root, grouped_rel,
    4265                 :          20 :                                          grouped_rel->reltarget,
    4266                 :          20 :                                          (List *) parse->havingQual);
    4267                 :          20 :             append.subpaths = lappend(append.subpaths, path);
    4268                 :             :         }
    4269                 :             :         path = (Path *)
    4270                 :          10 :             create_append_path(root,
    4271                 :             :                                grouped_rel,
    4272                 :             :                                append,
    4273                 :             :                                NIL,
    4274                 :             :                                NULL,
    4275                 :             :                                0,
    4276                 :             :                                false,
    4277                 :             :                                -1);
    4278                 :             :     }
    4279                 :             :     else
    4280                 :             :     {
    4281                 :             :         /* No grouping sets, or just one, so one output row */
    4282                 :             :         path = (Path *)
    4283                 :          35 :             create_group_result_path(root, grouped_rel,
    4284                 :          35 :                                      grouped_rel->reltarget,
    4285                 :          35 :                                      (List *) parse->havingQual);
    4286                 :             :     }
    4287                 :             : 
    4288                 :          45 :     add_path(grouped_rel, path);
    4289                 :          45 : }
    4290                 :             : 
    4291                 :             : /*
    4292                 :             :  * create_ordinary_grouping_paths
    4293                 :             :  *
    4294                 :             :  * Create grouping paths for the ordinary (that is, non-degenerate) case.
    4295                 :             :  *
    4296                 :             :  * We need to consider sorted and hashed aggregation in the same function,
    4297                 :             :  * because otherwise (1) it would be harder to throw an appropriate error
    4298                 :             :  * message if neither way works, and (2) we should not allow hashtable size
    4299                 :             :  * considerations to dissuade us from using hashing if sorting is not possible.
    4300                 :             :  *
    4301                 :             :  * *partially_grouped_rel_p will be set to the partially grouped rel which this
    4302                 :             :  * function creates, or to NULL if it doesn't create one.
    4303                 :             :  */
    4304                 :             : static void
    4305                 :       35892 : create_ordinary_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel,
    4306                 :             :                                RelOptInfo *grouped_rel,
    4307                 :             :                                const AggClauseCosts *agg_costs,
    4308                 :             :                                grouping_sets_data *gd,
    4309                 :             :                                GroupPathExtraData *extra,
    4310                 :             :                                RelOptInfo **partially_grouped_rel_p)
    4311                 :             : {
    4312                 :       35892 :     RelOptInfo *partially_grouped_rel = NULL;
    4313                 :       35892 :     PartitionwiseAggregateType patype = PARTITIONWISE_AGGREGATE_NONE;
    4314                 :             : 
    4315                 :             :     /*
    4316                 :             :      * If this is the topmost grouping relation or if the parent relation is
    4317                 :             :      * doing some form of partitionwise aggregation, then we may be able to do
    4318                 :             :      * it at this level also.  However, if the input relation is not
    4319                 :             :      * partitioned, partitionwise aggregate is impossible.
    4320                 :             :      */
    4321         [ +  + ]:       35892 :     if (extra->patype != PARTITIONWISE_AGGREGATE_NONE &&
    4322   [ +  +  +  -  :        2375 :         IS_PARTITIONED_REL(input_rel))
          +  +  +  -  +  
                      + ]
    4323                 :             :     {
    4324                 :             :         /*
    4325                 :             :          * If this is the topmost relation or if the parent relation is doing
    4326                 :             :          * full partitionwise aggregation, then we can do full partitionwise
    4327                 :             :          * aggregation provided that the GROUP BY clause contains all of the
    4328                 :             :          * partitioning columns at this level and the collation used by GROUP
    4329                 :             :          * BY matches the partitioning collation.  Otherwise, we can do at
    4330                 :             :          * most partial partitionwise aggregation.  But if partial aggregation
    4331                 :             :          * is not supported in general then we can't use it for partitionwise
    4332                 :             :          * aggregation either.
    4333                 :             :          *
    4334                 :             :          * Check parse->groupClause not processed_groupClause, because it's
    4335                 :             :          * okay if some of the partitioning columns were proved redundant.
    4336                 :             :          */
    4337   [ +  +  +  + ]:        1360 :         if (extra->patype == PARTITIONWISE_AGGREGATE_FULL &&
    4338                 :         640 :             group_by_has_partkey(input_rel, extra->targetList,
    4339                 :         640 :                                  root->parse->groupClause))
    4340                 :         404 :             patype = PARTITIONWISE_AGGREGATE_FULL;
    4341         [ +  + ]:         316 :         else if ((extra->flags & GROUPING_CAN_PARTIAL_AGG) != 0)
    4342                 :         281 :             patype = PARTITIONWISE_AGGREGATE_PARTIAL;
    4343                 :             :         else
    4344                 :          35 :             patype = PARTITIONWISE_AGGREGATE_NONE;
    4345                 :             :     }
    4346                 :             : 
    4347                 :             :     /*
    4348                 :             :      * Before generating paths for grouped_rel, we first generate any possible
    4349                 :             :      * partially grouped paths; that way, later code can easily consider both
    4350                 :             :      * parallel and non-parallel approaches to grouping.
    4351                 :             :      */
    4352         [ +  + ]:       35892 :     if ((extra->flags & GROUPING_CAN_PARTIAL_AGG) != 0)
    4353                 :             :     {
    4354                 :             :         bool        force_rel_creation;
    4355                 :             : 
    4356                 :             :         /*
    4357                 :             :          * If we're doing partitionwise aggregation at this level, force
    4358                 :             :          * creation of a partially_grouped_rel so we can add partitionwise
    4359                 :             :          * paths to it.
    4360                 :             :          */
    4361                 :       31896 :         force_rel_creation = (patype == PARTITIONWISE_AGGREGATE_PARTIAL);
    4362                 :             : 
    4363                 :             :         partially_grouped_rel =
    4364                 :       31896 :             create_partial_grouping_paths(root,
    4365                 :             :                                           grouped_rel,
    4366                 :             :                                           input_rel,
    4367                 :             :                                           gd,
    4368                 :             :                                           extra,
    4369                 :             :                                           force_rel_creation);
    4370                 :             :     }
    4371                 :             : 
    4372                 :             :     /* Set out parameter. */
    4373                 :       35892 :     *partially_grouped_rel_p = partially_grouped_rel;
    4374                 :             : 
    4375                 :             :     /* Apply partitionwise aggregation technique, if possible. */
    4376         [ +  + ]:       35892 :     if (patype != PARTITIONWISE_AGGREGATE_NONE)
    4377                 :         685 :         create_partitionwise_grouping_paths(root, input_rel, grouped_rel,
    4378                 :             :                                             partially_grouped_rel, agg_costs,
    4379                 :             :                                             gd, patype, extra);
    4380                 :             : 
    4381                 :             :     /* If we are doing partial aggregation only, return. */
    4382         [ +  + ]:       35892 :     if (extra->patype == PARTITIONWISE_AGGREGATE_PARTIAL)
    4383                 :             :     {
    4384                 :             :         Assert(partially_grouped_rel);
    4385                 :             : 
    4386         [ +  - ]:         713 :         if (partially_grouped_rel->pathlist)
    4387                 :         713 :             set_cheapest(partially_grouped_rel);
    4388                 :             : 
    4389                 :         713 :         return;
    4390                 :             :     }
    4391                 :             : 
    4392                 :             :     /* Gather any partially grouped partial paths. */
    4393   [ +  +  +  + ]:       35179 :     if (partially_grouped_rel && partially_grouped_rel->partial_pathlist)
    4394                 :        2322 :         gather_grouping_paths(root, partially_grouped_rel);
    4395                 :             : 
    4396                 :             :     /* Now choose the best path(s) for partially_grouped_rel. */
    4397   [ +  +  +  - ]:       35179 :     if (partially_grouped_rel && partially_grouped_rel->pathlist)
    4398                 :        2500 :         set_cheapest(partially_grouped_rel);
    4399                 :             : 
    4400                 :             :     /* Build final grouping paths */
    4401                 :       35179 :     add_paths_to_grouping_rel(root, input_rel, grouped_rel,
    4402                 :             :                               partially_grouped_rel, agg_costs, gd,
    4403                 :             :                               extra);
    4404                 :             : 
    4405                 :             :     /* Give a helpful error if we failed to find any implementation */
    4406         [ +  + ]:       35179 :     if (grouped_rel->pathlist == NIL)
    4407         [ +  - ]:           4 :         ereport(ERROR,
    4408                 :             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    4409                 :             :                  errmsg("could not implement GROUP BY"),
    4410                 :             :                  errdetail("Some of the datatypes only support hashing, while others only support sorting.")));
    4411                 :             : 
    4412                 :             :     /*
    4413                 :             :      * If there is an FDW that's responsible for all baserels of the query,
    4414                 :             :      * let it consider adding ForeignPaths.
    4415                 :             :      */
    4416         [ +  + ]:       35175 :     if (grouped_rel->fdwroutine &&
    4417         [ +  + ]:         172 :         grouped_rel->fdwroutine->GetForeignUpperPaths)
    4418                 :         171 :         grouped_rel->fdwroutine->GetForeignUpperPaths(root, UPPERREL_GROUP_AGG,
    4419                 :             :                                                       input_rel, grouped_rel,
    4420                 :             :                                                       extra);
    4421                 :             : 
    4422                 :             :     /* Let extensions possibly add some more paths */
    4423         [ -  + ]:       35175 :     if (create_upper_paths_hook)
    4424                 :           0 :         (*create_upper_paths_hook) (root, UPPERREL_GROUP_AGG,
    4425                 :             :                                     input_rel, grouped_rel,
    4426                 :             :                                     extra);
    4427                 :             : }
    4428                 :             : 
    4429                 :             : /*
    4430                 :             :  * For a given input path, consider the possible ways of doing grouping sets on
    4431                 :             :  * it, by combinations of hashing and sorting.  This can be called multiple
    4432                 :             :  * times, so it's important that it not scribble on input.  No result is
    4433                 :             :  * returned, but any generated paths are added to grouped_rel.
    4434                 :             :  */
    4435                 :             : static void
    4436                 :        1777 : consider_groupingsets_paths(PlannerInfo *root,
    4437                 :             :                             RelOptInfo *grouped_rel,
    4438                 :             :                             Path *path,
    4439                 :             :                             bool is_sorted,
    4440                 :             :                             bool can_hash,
    4441                 :             :                             grouping_sets_data *gd,
    4442                 :             :                             const AggClauseCosts *agg_costs,
    4443                 :             :                             double dNumGroups)
    4444                 :             : {
    4445                 :        1777 :     Query      *parse = root->parse;
    4446                 :        1777 :     Size        hash_mem_limit = get_hash_memory_limit();
    4447                 :             : 
    4448                 :             :     /*
    4449                 :             :      * If we're not being offered sorted input, then only consider plans that
    4450                 :             :      * can be done entirely by hashing.
    4451                 :             :      *
    4452                 :             :      * We can hash everything if it looks like it'll fit in hash_mem. But if
    4453                 :             :      * the input is actually sorted despite not being advertised as such, we
    4454                 :             :      * prefer to make use of that in order to use less memory.
    4455                 :             :      *
    4456                 :             :      * If none of the grouping sets are sortable, then ignore the hash_mem
    4457                 :             :      * limit and generate a path anyway, since otherwise we'll just fail.
    4458                 :             :      */
    4459         [ +  + ]:        1777 :     if (!is_sorted)
    4460                 :             :     {
    4461                 :         807 :         List       *new_rollups = NIL;
    4462                 :         807 :         RollupData *unhashed_rollup = NULL;
    4463                 :             :         List       *sets_data;
    4464                 :         807 :         List       *empty_sets_data = NIL;
    4465                 :         807 :         List       *empty_sets = NIL;
    4466                 :             :         ListCell   *lc;
    4467                 :         807 :         ListCell   *l_start = list_head(gd->rollups);
    4468                 :         807 :         AggStrategy strat = AGG_HASHED;
    4469                 :             :         double      hashsize;
    4470                 :         807 :         double      exclude_groups = 0.0;
    4471                 :             : 
    4472                 :             :         Assert(can_hash);
    4473                 :             : 
    4474                 :             :         /*
    4475                 :             :          * If the input is coincidentally sorted usefully (which can happen
    4476                 :             :          * even if is_sorted is false, since that only means that our caller
    4477                 :             :          * has set up the sorting for us), then save some hashtable space by
    4478                 :             :          * making use of that. But we need to watch out for degenerate cases:
    4479                 :             :          *
    4480                 :             :          * 1) If there are any empty grouping sets, then group_pathkeys might
    4481                 :             :          * be NIL if all non-empty grouping sets are unsortable. In this case,
    4482                 :             :          * there will be a rollup containing only empty groups, and the
    4483                 :             :          * pathkeys_contained_in test is vacuously true; this is ok.
    4484                 :             :          *
    4485                 :             :          * XXX: the above relies on the fact that group_pathkeys is generated
    4486                 :             :          * from the first rollup. If we add the ability to consider multiple
    4487                 :             :          * sort orders for grouping input, this assumption might fail.
    4488                 :             :          *
    4489                 :             :          * 2) If there are no empty sets and only unsortable sets, then the
    4490                 :             :          * rollups list will be empty (and thus l_start == NULL), and
    4491                 :             :          * group_pathkeys will be NIL; we must ensure that the vacuously-true
    4492                 :             :          * pathkeys_contained_in test doesn't cause us to crash.
    4493                 :             :          */
    4494   [ +  +  +  + ]:        1609 :         if (l_start != NULL &&
    4495                 :         802 :             pathkeys_contained_in(root->group_pathkeys, path->pathkeys))
    4496                 :             :         {
    4497                 :          40 :             unhashed_rollup = lfirst_node(RollupData, l_start);
    4498                 :          40 :             exclude_groups = unhashed_rollup->numGroups;
    4499                 :          40 :             l_start = lnext(gd->rollups, l_start);
    4500                 :             :         }
    4501                 :             : 
    4502                 :         807 :         hashsize = estimate_hashagg_tablesize(root,
    4503                 :             :                                               path,
    4504                 :             :                                               agg_costs,
    4505                 :             :                                               dNumGroups - exclude_groups);
    4506                 :             : 
    4507                 :             :         /*
    4508                 :             :          * gd->rollups is empty if we have only unsortable columns to work
    4509                 :             :          * with.  Override hash_mem in that case; otherwise, we'll rely on the
    4510                 :             :          * sorted-input case to generate usable mixed paths.
    4511                 :             :          */
    4512   [ +  +  +  - ]:         807 :         if (hashsize > hash_mem_limit && gd->rollups)
    4513                 :          15 :             return;             /* nope, won't fit */
    4514                 :             : 
    4515                 :             :         /*
    4516                 :             :          * We need to burst the existing rollups list into individual grouping
    4517                 :             :          * sets and recompute a groupClause for each set.
    4518                 :             :          */
    4519                 :         792 :         sets_data = list_copy(gd->unsortable_sets);
    4520                 :             : 
    4521   [ +  +  +  +  :        2013 :         for_each_cell(lc, gd->rollups, l_start)
                   +  + ]
    4522                 :             :         {
    4523                 :        1241 :             RollupData *rollup = lfirst_node(RollupData, lc);
    4524                 :             : 
    4525                 :             :             /*
    4526                 :             :              * If we find an unhashable rollup that's not been skipped by the
    4527                 :             :              * "actually sorted" check above, we can't cope; we'd need sorted
    4528                 :             :              * input (with a different sort order) but we can't get that here.
    4529                 :             :              * So bail out; we'll get a valid path from the is_sorted case
    4530                 :             :              * instead.
    4531                 :             :              *
    4532                 :             :              * The mere presence of empty grouping sets doesn't make a rollup
    4533                 :             :              * unhashable (see preprocess_grouping_sets), we handle those
    4534                 :             :              * specially below.
    4535                 :             :              */
    4536         [ +  + ]:        1241 :             if (!rollup->hashable)
    4537                 :          20 :                 return;
    4538                 :             : 
    4539                 :        1221 :             sets_data = list_concat(sets_data, rollup->gsets_data);
    4540                 :             :         }
    4541   [ +  -  +  +  :        3053 :         foreach(lc, sets_data)
                   +  + ]
    4542                 :             :         {
    4543                 :        2281 :             GroupingSetData *gs = lfirst_node(GroupingSetData, lc);
    4544                 :        2281 :             List       *gset = gs->set;
    4545                 :             :             RollupData *rollup;
    4546                 :             : 
    4547         [ +  + ]:        2281 :             if (gset == NIL)
    4548                 :             :             {
    4549                 :             :                 /* Empty grouping sets can't be hashed. */
    4550                 :         445 :                 empty_sets_data = lappend(empty_sets_data, gs);
    4551                 :         445 :                 empty_sets = lappend(empty_sets, NIL);
    4552                 :             :             }
    4553                 :             :             else
    4554                 :             :             {
    4555                 :        1836 :                 rollup = makeNode(RollupData);
    4556                 :             : 
    4557                 :        1836 :                 rollup->groupClause = preprocess_groupclause(root, gset);
    4558                 :        1836 :                 rollup->gsets_data = list_make1(gs);
    4559                 :        1836 :                 rollup->gsets = remap_to_groupclause_idx(rollup->groupClause,
    4560                 :             :                                                          rollup->gsets_data,
    4561                 :             :                                                          gd->tleref_to_colnum_map);
    4562                 :        1836 :                 rollup->numGroups = gs->numGroups;
    4563                 :        1836 :                 rollup->hashable = true;
    4564                 :        1836 :                 rollup->is_hashed = true;
    4565                 :        1836 :                 new_rollups = lappend(new_rollups, rollup);
    4566                 :             :             }
    4567                 :             :         }
    4568                 :             : 
    4569                 :             :         /*
    4570                 :             :          * If we didn't find anything nonempty to hash, then bail.  We'll
    4571                 :             :          * generate a path from the is_sorted case.
    4572                 :             :          */
    4573         [ -  + ]:         772 :         if (new_rollups == NIL)
    4574                 :           0 :             return;
    4575                 :             : 
    4576                 :             :         /*
    4577                 :             :          * If there were empty grouping sets they should have been in the
    4578                 :             :          * first rollup.
    4579                 :             :          */
    4580                 :             :         Assert(!unhashed_rollup || !empty_sets);
    4581                 :             : 
    4582         [ +  + ]:         772 :         if (unhashed_rollup)
    4583                 :             :         {
    4584                 :          40 :             new_rollups = lappend(new_rollups, unhashed_rollup);
    4585                 :          40 :             strat = AGG_MIXED;
    4586                 :             :         }
    4587         [ +  + ]:         732 :         else if (empty_sets)
    4588                 :             :         {
    4589                 :         405 :             RollupData *rollup = makeNode(RollupData);
    4590                 :             : 
    4591                 :         405 :             rollup->groupClause = NIL;
    4592                 :         405 :             rollup->gsets_data = empty_sets_data;
    4593                 :         405 :             rollup->gsets = empty_sets;
    4594                 :         405 :             rollup->numGroups = list_length(empty_sets);
    4595                 :         405 :             rollup->hashable = false;
    4596                 :         405 :             rollup->is_hashed = false;
    4597                 :         405 :             new_rollups = lappend(new_rollups, rollup);
    4598                 :         405 :             strat = AGG_MIXED;
    4599                 :             :         }
    4600                 :             : 
    4601                 :         772 :         add_path(grouped_rel, (Path *)
    4602                 :         772 :                  create_groupingsets_path(root,
    4603                 :             :                                           grouped_rel,
    4604                 :             :                                           path,
    4605                 :         772 :                                           (List *) parse->havingQual,
    4606                 :             :                                           strat,
    4607                 :             :                                           new_rollups,
    4608                 :             :                                           agg_costs));
    4609                 :         772 :         return;
    4610                 :             :     }
    4611                 :             : 
    4612                 :             :     /*
    4613                 :             :      * If we have sorted input but nothing we can do with it, bail.
    4614                 :             :      */
    4615         [ -  + ]:         970 :     if (gd->rollups == NIL)
    4616                 :           0 :         return;
    4617                 :             : 
    4618                 :             :     /*
    4619                 :             :      * Given sorted input, we try and make two paths: one sorted and one mixed
    4620                 :             :      * sort/hash. (We need to try both because hashagg might be disabled, or
    4621                 :             :      * some columns might not be sortable.)
    4622                 :             :      *
    4623                 :             :      * can_hash is passed in as false if some obstacle elsewhere (such as
    4624                 :             :      * ordered aggs) means that we shouldn't consider hashing at all.
    4625                 :             :      */
    4626   [ +  +  +  - ]:         970 :     if (can_hash && gd->any_hashable)
    4627                 :             :     {
    4628                 :         896 :         List       *rollups = NIL;
    4629                 :         896 :         List       *hash_sets = list_copy(gd->unsortable_sets);
    4630                 :         896 :         double      availspace = hash_mem_limit;
    4631                 :             :         ListCell   *lc;
    4632                 :             : 
    4633                 :             :         /*
    4634                 :             :          * Account first for space needed for groups we can't sort at all.
    4635                 :             :          */
    4636                 :         896 :         availspace -= estimate_hashagg_tablesize(root,
    4637                 :             :                                                  path,
    4638                 :             :                                                  agg_costs,
    4639                 :             :                                                  gd->dNumHashGroups);
    4640                 :             : 
    4641   [ +  -  +  + ]:         896 :         if (availspace > 0 && list_length(gd->rollups) > 1)
    4642                 :             :         {
    4643                 :             :             double      scale;
    4644                 :         501 :             int         num_rollups = list_length(gd->rollups);
    4645                 :             :             int         k_capacity;
    4646                 :         501 :             int        *k_weights = palloc(num_rollups * sizeof(int));
    4647                 :         501 :             Bitmapset  *hash_items = NULL;
    4648                 :             :             int         i;
    4649                 :             : 
    4650                 :             :             /*
    4651                 :             :              * We treat this as a knapsack problem: the knapsack capacity
    4652                 :             :              * represents hash_mem, the item weights are the estimated memory
    4653                 :             :              * usage of the hashtables needed to implement a single rollup,
    4654                 :             :              * and we really ought to use the cost saving as the item value;
    4655                 :             :              * however, currently the costs assigned to sort nodes don't
    4656                 :             :              * reflect the comparison costs well, and so we treat all items as
    4657                 :             :              * of equal value (each rollup we hash instead saves us one sort).
    4658                 :             :              *
    4659                 :             :              * To use the discrete knapsack, we need to scale the values to a
    4660                 :             :              * reasonably small bounded range.  We choose to allow a 5% error
    4661                 :             :              * margin; we have no more than 4096 rollups in the worst possible
    4662                 :             :              * case, which with a 5% error margin will require a bit over 42MB
    4663                 :             :              * of workspace. (Anyone wanting to plan queries that complex had
    4664                 :             :              * better have the memory for it.  In more reasonable cases, with
    4665                 :             :              * no more than a couple of dozen rollups, the memory usage will
    4666                 :             :              * be negligible.)
    4667                 :             :              *
    4668                 :             :              * k_capacity is naturally bounded, but we clamp the values for
    4669                 :             :              * scale and weight (below) to avoid overflows or underflows (or
    4670                 :             :              * uselessly trying to use a scale factor less than 1 byte).
    4671                 :             :              */
    4672         [ +  - ]:         501 :             scale = Max(availspace / (20.0 * num_rollups), 1.0);
    4673                 :         501 :             k_capacity = (int) floor(availspace / scale);
    4674                 :             : 
    4675                 :             :             /*
    4676                 :             :              * We leave the first rollup out of consideration since it's the
    4677                 :             :              * one that matches the input sort order.  We assign indexes "i"
    4678                 :             :              * to only those entries considered for hashing; the second loop,
    4679                 :             :              * below, must use the same condition.
    4680                 :             :              */
    4681                 :         501 :             i = 0;
    4682   [ +  -  +  +  :        1222 :             for_each_from(lc, gd->rollups, 1)
                   +  + ]
    4683                 :             :             {
    4684                 :         721 :                 RollupData *rollup = lfirst_node(RollupData, lc);
    4685                 :             : 
    4686         [ +  - ]:         721 :                 if (rollup->hashable)
    4687                 :             :                 {
    4688                 :         721 :                     double      sz = estimate_hashagg_tablesize(root,
    4689                 :             :                                                                 path,
    4690                 :             :                                                                 agg_costs,
    4691                 :             :                                                                 rollup->numGroups);
    4692                 :             : 
    4693                 :             :                     /*
    4694                 :             :                      * If sz is enormous, but hash_mem (and hence scale) is
    4695                 :             :                      * small, avoid integer overflow here.
    4696                 :             :                      */
    4697         [ +  + ]:         721 :                     k_weights[i] = (int) Min(floor(sz / scale),
    4698                 :             :                                              k_capacity + 1.0);
    4699                 :         721 :                     ++i;
    4700                 :             :                 }
    4701                 :             :             }
    4702                 :             : 
    4703                 :             :             /*
    4704                 :             :              * Apply knapsack algorithm; compute the set of items which
    4705                 :             :              * maximizes the value stored (in this case the number of sorts
    4706                 :             :              * saved) while keeping the total size (approximately) within
    4707                 :             :              * capacity.
    4708                 :             :              */
    4709         [ +  - ]:         501 :             if (i > 0)
    4710                 :         501 :                 hash_items = DiscreteKnapsack(k_capacity, i, k_weights, NULL);
    4711                 :             : 
    4712         [ +  - ]:         501 :             if (!bms_is_empty(hash_items))
    4713                 :             :             {
    4714                 :         501 :                 rollups = list_make1(linitial(gd->rollups));
    4715                 :             : 
    4716                 :         501 :                 i = 0;
    4717   [ +  -  +  +  :        1222 :                 for_each_from(lc, gd->rollups, 1)
                   +  + ]
    4718                 :             :                 {
    4719                 :         721 :                     RollupData *rollup = lfirst_node(RollupData, lc);
    4720                 :             : 
    4721         [ +  - ]:         721 :                     if (rollup->hashable)
    4722                 :             :                     {
    4723         [ +  + ]:         721 :                         if (bms_is_member(i, hash_items))
    4724                 :         691 :                             hash_sets = list_concat(hash_sets,
    4725                 :         691 :                                                     rollup->gsets_data);
    4726                 :             :                         else
    4727                 :          30 :                             rollups = lappend(rollups, rollup);
    4728                 :         721 :                         ++i;
    4729                 :             :                     }
    4730                 :             :                     else
    4731                 :           0 :                         rollups = lappend(rollups, rollup);
    4732                 :             :                 }
    4733                 :             :             }
    4734                 :             :         }
    4735                 :             : 
    4736   [ +  +  +  + ]:         896 :         if (!rollups && hash_sets)
    4737                 :          20 :             rollups = list_copy(gd->rollups);
    4738                 :             : 
    4739   [ +  +  +  +  :        1703 :         foreach(lc, hash_sets)
                   +  + ]
    4740                 :             :         {
    4741                 :         807 :             GroupingSetData *gs = lfirst_node(GroupingSetData, lc);
    4742                 :         807 :             RollupData *rollup = makeNode(RollupData);
    4743                 :             : 
    4744                 :             :             Assert(gs->set != NIL);
    4745                 :             : 
    4746                 :         807 :             rollup->groupClause = preprocess_groupclause(root, gs->set);
    4747                 :         807 :             rollup->gsets_data = list_make1(gs);
    4748                 :         807 :             rollup->gsets = remap_to_groupclause_idx(rollup->groupClause,
    4749                 :             :                                                      rollup->gsets_data,
    4750                 :             :                                                      gd->tleref_to_colnum_map);
    4751                 :         807 :             rollup->numGroups = gs->numGroups;
    4752                 :         807 :             rollup->hashable = true;
    4753                 :         807 :             rollup->is_hashed = true;
    4754                 :         807 :             rollups = lcons(rollup, rollups);
    4755                 :             :         }
    4756                 :             : 
    4757         [ +  + ]:         896 :         if (rollups)
    4758                 :             :         {
    4759                 :         521 :             add_path(grouped_rel, (Path *)
    4760                 :         521 :                      create_groupingsets_path(root,
    4761                 :             :                                               grouped_rel,
    4762                 :             :                                               path,
    4763                 :         521 :                                               (List *) parse->havingQual,
    4764                 :             :                                               AGG_MIXED,
    4765                 :             :                                               rollups,
    4766                 :             :                                               agg_costs));
    4767                 :             :         }
    4768                 :             :     }
    4769                 :             : 
    4770                 :             :     /*
    4771                 :             :      * Now try the simple sorted case.
    4772                 :             :      */
    4773         [ +  + ]:         970 :     if (!gd->unsortable_sets)
    4774                 :         946 :         add_path(grouped_rel, (Path *)
    4775                 :         946 :                  create_groupingsets_path(root,
    4776                 :             :                                           grouped_rel,
    4777                 :             :                                           path,
    4778                 :         946 :                                           (List *) parse->havingQual,
    4779                 :             :                                           AGG_SORTED,
    4780                 :             :                                           gd->rollups,
    4781                 :             :                                           agg_costs));
    4782                 :             : }
    4783                 :             : 
    4784                 :             : /*
    4785                 :             :  * create_window_paths
    4786                 :             :  *
    4787                 :             :  * Build a new upperrel containing Paths for window-function evaluation.
    4788                 :             :  *
    4789                 :             :  * input_rel: contains the source-data Paths
    4790                 :             :  * input_target: result of make_window_input_target
    4791                 :             :  * output_target: what the topmost WindowAggPath should return
    4792                 :             :  * wflists: result of find_window_functions
    4793                 :             :  * activeWindows: result of select_active_windows
    4794                 :             :  *
    4795                 :             :  * Note: all Paths in input_rel are expected to return input_target.
    4796                 :             :  */
    4797                 :             : static RelOptInfo *
    4798                 :        2326 : create_window_paths(PlannerInfo *root,
    4799                 :             :                     RelOptInfo *input_rel,
    4800                 :             :                     PathTarget *input_target,
    4801                 :             :                     PathTarget *output_target,
    4802                 :             :                     bool output_target_parallel_safe,
    4803                 :             :                     WindowFuncLists *wflists,
    4804                 :             :                     List *activeWindows)
    4805                 :             : {
    4806                 :             :     RelOptInfo *window_rel;
    4807                 :             :     ListCell   *lc;
    4808                 :             : 
    4809                 :             :     /* For now, do all work in the (WINDOW, NULL) upperrel */
    4810                 :        2326 :     window_rel = fetch_upper_rel(root, UPPERREL_WINDOW, NULL);
    4811                 :             : 
    4812                 :             :     /*
    4813                 :             :      * If the input relation is not parallel-safe, then the window relation
    4814                 :             :      * can't be parallel-safe, either.  Otherwise, we need to examine the
    4815                 :             :      * target list and active windows for non-parallel-safe constructs.
    4816                 :             :      */
    4817   [ +  +  -  +  :        2326 :     if (input_rel->consider_parallel && output_target_parallel_safe &&
                   -  - ]
    4818                 :           0 :         is_parallel_safe(root, (Node *) activeWindows))
    4819                 :           0 :         window_rel->consider_parallel = true;
    4820                 :             : 
    4821                 :             :     /*
    4822                 :             :      * If the input rel belongs to a single FDW, so does the window rel.
    4823                 :             :      */
    4824                 :        2326 :     window_rel->serverid = input_rel->serverid;
    4825                 :        2326 :     window_rel->userid = input_rel->userid;
    4826                 :        2326 :     window_rel->useridiscurrent = input_rel->useridiscurrent;
    4827                 :        2326 :     window_rel->fdwroutine = input_rel->fdwroutine;
    4828                 :             : 
    4829                 :             :     /*
    4830                 :             :      * Consider computing window functions starting from the existing
    4831                 :             :      * cheapest-total path (which will likely require a sort) as well as any
    4832                 :             :      * existing paths that satisfy or partially satisfy root->window_pathkeys.
    4833                 :             :      */
    4834   [ +  -  +  +  :        4903 :     foreach(lc, input_rel->pathlist)
                   +  + ]
    4835                 :             :     {
    4836                 :        2577 :         Path       *path = (Path *) lfirst(lc);
    4837                 :             :         int         presorted_keys;
    4838                 :             : 
    4839   [ +  +  +  + ]:        2828 :         if (path == input_rel->cheapest_total_path ||
    4840                 :         251 :             pathkeys_count_contained_in(root->window_pathkeys, path->pathkeys,
    4841                 :         115 :                                         &presorted_keys) ||
    4842         [ +  + ]:         115 :             presorted_keys > 0)
    4843                 :        2482 :             create_one_window_path(root,
    4844                 :             :                                    window_rel,
    4845                 :             :                                    path,
    4846                 :             :                                    input_target,
    4847                 :             :                                    output_target,
    4848                 :             :                                    wflists,
    4849                 :             :                                    activeWindows);
    4850                 :             :     }
    4851                 :             : 
    4852                 :             :     /*
    4853                 :             :      * If there is an FDW that's responsible for all baserels of the query,
    4854                 :             :      * let it consider adding ForeignPaths.
    4855                 :             :      */
    4856         [ +  + ]:        2326 :     if (window_rel->fdwroutine &&
    4857         [ +  - ]:           6 :         window_rel->fdwroutine->GetForeignUpperPaths)
    4858                 :           6 :         window_rel->fdwroutine->GetForeignUpperPaths(root, UPPERREL_WINDOW,
    4859                 :             :                                                      input_rel, window_rel,
    4860                 :             :                                                      NULL);
    4861                 :             : 
    4862                 :             :     /* Let extensions possibly add some more paths */
    4863         [ -  + ]:        2326 :     if (create_upper_paths_hook)
    4864                 :           0 :         (*create_upper_paths_hook) (root, UPPERREL_WINDOW,
    4865                 :             :                                     input_rel, window_rel, NULL);
    4866                 :             : 
    4867                 :             :     /* Now choose the best path(s) */
    4868                 :        2326 :     set_cheapest(window_rel);
    4869                 :             : 
    4870                 :        2326 :     return window_rel;
    4871                 :             : }
    4872                 :             : 
    4873                 :             : /*
    4874                 :             :  * Stack window-function implementation steps atop the given Path, and
    4875                 :             :  * add the result to window_rel.
    4876                 :             :  *
    4877                 :             :  * window_rel: upperrel to contain result
    4878                 :             :  * path: input Path to use (must return input_target)
    4879                 :             :  * input_target: result of make_window_input_target
    4880                 :             :  * output_target: what the topmost WindowAggPath should return
    4881                 :             :  * wflists: result of find_window_functions
    4882                 :             :  * activeWindows: result of select_active_windows
    4883                 :             :  */
    4884                 :             : static void
    4885                 :        2482 : create_one_window_path(PlannerInfo *root,
    4886                 :             :                        RelOptInfo *window_rel,
    4887                 :             :                        Path *path,
    4888                 :             :                        PathTarget *input_target,
    4889                 :             :                        PathTarget *output_target,
    4890                 :             :                        WindowFuncLists *wflists,
    4891                 :             :                        List *activeWindows)
    4892                 :             : {
    4893                 :             :     PathTarget *window_target;
    4894                 :             :     ListCell   *l;
    4895                 :        2482 :     List       *topqual = NIL;
    4896                 :             : 
    4897                 :             :     /*
    4898                 :             :      * Since each window clause could require a different sort order, we stack
    4899                 :             :      * up a WindowAgg node for each clause, with sort steps between them as
    4900                 :             :      * needed.  (We assume that select_active_windows chose a good order for
    4901                 :             :      * executing the clauses in.)
    4902                 :             :      *
    4903                 :             :      * input_target should contain all Vars and Aggs needed for the result.
    4904                 :             :      * (In some cases we wouldn't need to propagate all of these all the way
    4905                 :             :      * to the top, since they might only be needed as inputs to WindowFuncs.
    4906                 :             :      * It's probably not worth trying to optimize that though.)  It must also
    4907                 :             :      * contain all window partitioning and sorting expressions, to ensure
    4908                 :             :      * they're computed only once at the bottom of the stack (that's critical
    4909                 :             :      * for volatile functions).  As we climb up the stack, we'll add outputs
    4910                 :             :      * for the WindowFuncs computed at each level.
    4911                 :             :      */
    4912                 :        2482 :     window_target = input_target;
    4913                 :             : 
    4914   [ +  -  +  +  :        5129 :     foreach(l, activeWindows)
                   +  + ]
    4915                 :             :     {
    4916                 :        2647 :         WindowClause *wc = lfirst_node(WindowClause, l);
    4917                 :             :         List       *window_pathkeys;
    4918                 :        2647 :         List       *runcondition = NIL;
    4919                 :             :         int         presorted_keys;
    4920                 :             :         bool        is_sorted;
    4921                 :             :         bool        topwindow;
    4922                 :             :         ListCell   *lc2;
    4923                 :             : 
    4924                 :        2647 :         window_pathkeys = make_pathkeys_for_window(root,
    4925                 :             :                                                    wc,
    4926                 :             :                                                    root->processed_tlist);
    4927                 :             : 
    4928                 :        2647 :         is_sorted = pathkeys_count_contained_in(window_pathkeys,
    4929                 :             :                                                 path->pathkeys,
    4930                 :             :                                                 &presorted_keys);
    4931                 :             : 
    4932                 :             :         /* Sort if necessary */
    4933         [ +  + ]:        2647 :         if (!is_sorted)
    4934                 :             :         {
    4935                 :             :             /*
    4936                 :             :              * No presorted keys or incremental sort disabled, just perform a
    4937                 :             :              * complete sort.
    4938                 :             :              */
    4939   [ +  +  -  + ]:        1924 :             if (presorted_keys == 0 || !enable_incremental_sort)
    4940                 :        1874 :                 path = (Path *) create_sort_path(root, window_rel,
    4941                 :             :                                                  path,
    4942                 :             :                                                  window_pathkeys,
    4943                 :             :                                                  -1.0);
    4944                 :             :             else
    4945                 :             :             {
    4946                 :             :                 /*
    4947                 :             :                  * Since we have presorted keys and incremental sort is
    4948                 :             :                  * enabled, just use incremental sort.
    4949                 :             :                  */
    4950                 :          50 :                 path = (Path *) create_incremental_sort_path(root,
    4951                 :             :                                                              window_rel,
    4952                 :             :                                                              path,
    4953                 :             :                                                              window_pathkeys,
    4954                 :             :                                                              presorted_keys,
    4955                 :             :                                                              -1.0);
    4956                 :             :             }
    4957                 :             :         }
    4958                 :             : 
    4959         [ +  + ]:        2647 :         if (lnext(activeWindows, l))
    4960                 :             :         {
    4961                 :             :             /*
    4962                 :             :              * Add the current WindowFuncs to the output target for this
    4963                 :             :              * intermediate WindowAggPath.  We must copy window_target to
    4964                 :             :              * avoid changing the previous path's target.
    4965                 :             :              *
    4966                 :             :              * Note: a WindowFunc adds nothing to the target's eval costs; but
    4967                 :             :              * we do need to account for the increase in tlist width.
    4968                 :             :              */
    4969                 :         165 :             int64       tuple_width = window_target->width;
    4970                 :             : 
    4971                 :         165 :             window_target = copy_pathtarget(window_target);
    4972   [ +  -  +  +  :         390 :             foreach(lc2, wflists->windowFuncs[wc->winref])
                   +  + ]
    4973                 :             :             {
    4974                 :         225 :                 WindowFunc *wfunc = lfirst_node(WindowFunc, lc2);
    4975                 :             : 
    4976                 :         225 :                 add_column_to_pathtarget(window_target, (Expr *) wfunc, 0);
    4977                 :         225 :                 tuple_width += get_typavgwidth(wfunc->wintype, -1);
    4978                 :             :             }
    4979                 :         165 :             window_target->width = clamp_width_est(tuple_width);
    4980                 :             :         }
    4981                 :             :         else
    4982                 :             :         {
    4983                 :             :             /* Install the goal target in the topmost WindowAgg */
    4984                 :        2482 :             window_target = output_target;
    4985                 :             :         }
    4986                 :             : 
    4987                 :             :         /* mark the final item in the list as the top-level window */
    4988                 :        2647 :         topwindow = foreach_current_index(l) == list_length(activeWindows) - 1;
    4989                 :             : 
    4990                 :             :         /*
    4991                 :             :          * Collect the WindowFuncRunConditions from each WindowFunc and
    4992                 :             :          * convert them into OpExprs
    4993                 :             :          */
    4994   [ +  -  +  +  :        6027 :         foreach(lc2, wflists->windowFuncs[wc->winref])
                   +  + ]
    4995                 :             :         {
    4996                 :             :             ListCell   *lc3;
    4997                 :        3380 :             WindowFunc *wfunc = lfirst_node(WindowFunc, lc2);
    4998                 :             : 
    4999   [ +  +  +  +  :        3550 :             foreach(lc3, wfunc->runCondition)
                   +  + ]
    5000                 :             :             {
    5001                 :         170 :                 WindowFuncRunCondition *wfuncrc =
    5002                 :             :                     lfirst_node(WindowFuncRunCondition, lc3);
    5003                 :             :                 Expr       *opexpr;
    5004                 :             :                 Expr       *leftop;
    5005                 :             :                 Expr       *rightop;
    5006                 :             : 
    5007         [ +  + ]:         170 :                 if (wfuncrc->wfunc_left)
    5008                 :             :                 {
    5009                 :         155 :                     leftop = (Expr *) copyObject(wfunc);
    5010                 :         155 :                     rightop = copyObject(wfuncrc->arg);
    5011                 :             :                 }
    5012                 :             :                 else
    5013                 :             :                 {
    5014                 :          15 :                     leftop = copyObject(wfuncrc->arg);
    5015                 :          15 :                     rightop = (Expr *) copyObject(wfunc);
    5016                 :             :                 }
    5017                 :             : 
    5018                 :         170 :                 opexpr = make_opclause(wfuncrc->opno,
    5019                 :             :                                        BOOLOID,
    5020                 :             :                                        false,
    5021                 :             :                                        leftop,
    5022                 :             :                                        rightop,
    5023                 :             :                                        InvalidOid,
    5024                 :             :                                        wfuncrc->inputcollid);
    5025                 :             : 
    5026                 :         170 :                 runcondition = lappend(runcondition, opexpr);
    5027                 :             : 
    5028         [ +  + ]:         170 :                 if (!topwindow)
    5029                 :          20 :                     topqual = lappend(topqual, opexpr);
    5030                 :             :             }
    5031                 :             :         }
    5032                 :             : 
    5033                 :             :         path = (Path *)
    5034         [ +  + ]:        2647 :             create_windowagg_path(root, window_rel, path, window_target,
    5035                 :        2647 :                                   wflists->windowFuncs[wc->winref],
    5036                 :             :                                   runcondition, wc,
    5037                 :             :                                   topwindow ? topqual : NIL, topwindow);
    5038                 :             :     }
    5039                 :             : 
    5040                 :        2482 :     add_path(window_rel, path);
    5041                 :        2482 : }
    5042                 :             : 
    5043                 :             : /*
    5044                 :             :  * create_distinct_paths
    5045                 :             :  *
    5046                 :             :  * Build a new upperrel containing Paths for SELECT DISTINCT evaluation.
    5047                 :             :  *
    5048                 :             :  * input_rel: contains the source-data Paths
    5049                 :             :  * target: the pathtarget for the result Paths to compute
    5050                 :             :  *
    5051                 :             :  * Note: input paths should already compute the desired pathtarget, since
    5052                 :             :  * Sort/Unique won't project anything.
    5053                 :             :  */
    5054                 :             : static RelOptInfo *
    5055                 :        2017 : create_distinct_paths(PlannerInfo *root, RelOptInfo *input_rel,
    5056                 :             :                       PathTarget *target)
    5057                 :             : {
    5058                 :             :     RelOptInfo *distinct_rel;
    5059                 :             : 
    5060                 :             :     /* For now, do all work in the (DISTINCT, NULL) upperrel */
    5061                 :        2017 :     distinct_rel = fetch_upper_rel(root, UPPERREL_DISTINCT, NULL);
    5062                 :             : 
    5063                 :             :     /*
    5064                 :             :      * We don't compute anything at this level, so distinct_rel will be
    5065                 :             :      * parallel-safe if the input rel is parallel-safe.  In particular, if
    5066                 :             :      * there is a DISTINCT ON (...) clause, any path for the input_rel will
    5067                 :             :      * output those expressions, and will not be parallel-safe unless those
    5068                 :             :      * expressions are parallel-safe.
    5069                 :             :      */
    5070                 :        2017 :     distinct_rel->consider_parallel = input_rel->consider_parallel;
    5071                 :             : 
    5072                 :             :     /*
    5073                 :             :      * If the input rel belongs to a single FDW, so does the distinct_rel.
    5074                 :             :      */
    5075                 :        2017 :     distinct_rel->serverid = input_rel->serverid;
    5076                 :        2017 :     distinct_rel->userid = input_rel->userid;
    5077                 :        2017 :     distinct_rel->useridiscurrent = input_rel->useridiscurrent;
    5078                 :        2017 :     distinct_rel->fdwroutine = input_rel->fdwroutine;
    5079                 :             : 
    5080                 :             :     /* build distinct paths based on input_rel's pathlist */
    5081                 :        2017 :     create_final_distinct_paths(root, input_rel, distinct_rel);
    5082                 :             : 
    5083                 :             :     /* now build distinct paths based on input_rel's partial_pathlist */
    5084                 :        2017 :     create_partial_distinct_paths(root, input_rel, distinct_rel, target);
    5085                 :             : 
    5086                 :             :     /* Give a helpful error if we failed to create any paths */
    5087         [ -  + ]:        2017 :     if (distinct_rel->pathlist == NIL)
    5088         [ #  # ]:           0 :         ereport(ERROR,
    5089                 :             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    5090                 :             :                  errmsg("could not implement DISTINCT"),
    5091                 :             :                  errdetail("Some of the datatypes only support hashing, while others only support sorting.")));
    5092                 :             : 
    5093                 :             :     /*
    5094                 :             :      * If there is an FDW that's responsible for all baserels of the query,
    5095                 :             :      * let it consider adding ForeignPaths.
    5096                 :             :      */
    5097         [ +  + ]:        2017 :     if (distinct_rel->fdwroutine &&
    5098         [ +  - ]:           8 :         distinct_rel->fdwroutine->GetForeignUpperPaths)
    5099                 :           8 :         distinct_rel->fdwroutine->GetForeignUpperPaths(root,
    5100                 :             :                                                        UPPERREL_DISTINCT,
    5101                 :             :                                                        input_rel,
    5102                 :             :                                                        distinct_rel,
    5103                 :             :                                                        NULL);
    5104                 :             : 
    5105                 :             :     /* Let extensions possibly add some more paths */
    5106         [ -  + ]:        2017 :     if (create_upper_paths_hook)
    5107                 :           0 :         (*create_upper_paths_hook) (root, UPPERREL_DISTINCT, input_rel,
    5108                 :             :                                     distinct_rel, NULL);
    5109                 :             : 
    5110                 :             :     /* Now choose the best path(s) */
    5111                 :        2017 :     set_cheapest(distinct_rel);
    5112                 :             : 
    5113                 :        2017 :     return distinct_rel;
    5114                 :             : }
    5115                 :             : 
    5116                 :             : /*
    5117                 :             :  * create_partial_distinct_paths
    5118                 :             :  *
    5119                 :             :  * Process 'input_rel' partial paths and add unique/aggregate paths to the
    5120                 :             :  * UPPERREL_PARTIAL_DISTINCT rel.  For paths created, add Gather/GatherMerge
    5121                 :             :  * paths on top and add a final unique/aggregate path to remove any duplicate
    5122                 :             :  * produced from combining rows from parallel workers.
    5123                 :             :  */
    5124                 :             : static void
    5125                 :        2017 : create_partial_distinct_paths(PlannerInfo *root, RelOptInfo *input_rel,
    5126                 :             :                               RelOptInfo *final_distinct_rel,
    5127                 :             :                               PathTarget *target)
    5128                 :             : {
    5129                 :             :     RelOptInfo *partial_distinct_rel;
    5130                 :             :     Query      *parse;
    5131                 :             :     List       *distinctExprs;
    5132                 :             :     double      numDistinctRows;
    5133                 :             :     Path       *cheapest_partial_path;
    5134                 :             :     ListCell   *lc;
    5135                 :             : 
    5136                 :             :     /* nothing to do when there are no partial paths in the input rel */
    5137   [ +  +  +  + ]:        2017 :     if (!input_rel->consider_parallel || input_rel->partial_pathlist == NIL)
    5138                 :        1927 :         return;
    5139                 :             : 
    5140                 :          90 :     parse = root->parse;
    5141                 :             : 
    5142                 :             :     /* can't do parallel DISTINCT ON */
    5143         [ -  + ]:          90 :     if (parse->hasDistinctOn)
    5144                 :           0 :         return;
    5145                 :             : 
    5146                 :          90 :     partial_distinct_rel = fetch_upper_rel(root, UPPERREL_PARTIAL_DISTINCT,
    5147                 :             :                                            NULL);
    5148                 :          90 :     partial_distinct_rel->reltarget = target;
    5149                 :          90 :     partial_distinct_rel->consider_parallel = input_rel->consider_parallel;
    5150                 :             : 
    5151                 :             :     /*
    5152                 :             :      * If input_rel belongs to a single FDW, so does the partial_distinct_rel.
    5153                 :             :      */
    5154                 :          90 :     partial_distinct_rel->serverid = input_rel->serverid;
    5155                 :          90 :     partial_distinct_rel->userid = input_rel->userid;
    5156                 :          90 :     partial_distinct_rel->useridiscurrent = input_rel->useridiscurrent;
    5157                 :          90 :     partial_distinct_rel->fdwroutine = input_rel->fdwroutine;
    5158                 :             : 
    5159                 :          90 :     cheapest_partial_path = linitial(input_rel->partial_pathlist);
    5160                 :             : 
    5161                 :          90 :     distinctExprs = get_sortgrouplist_exprs(root->processed_distinctClause,
    5162                 :             :                                             parse->targetList);
    5163                 :             : 
    5164                 :             :     /* estimate how many distinct rows we'll get from each worker */
    5165                 :          90 :     numDistinctRows = estimate_num_groups(root, distinctExprs,
    5166                 :             :                                           cheapest_partial_path->rows,
    5167                 :             :                                           NULL, NULL);
    5168                 :             : 
    5169                 :             :     /*
    5170                 :             :      * Try sorting the cheapest path and incrementally sorting any paths with
    5171                 :             :      * presorted keys and put a unique paths atop of those.  We'll also
    5172                 :             :      * attempt to reorder the required pathkeys to match the input path's
    5173                 :             :      * pathkeys as much as possible, in hopes of avoiding a possible need to
    5174                 :             :      * re-sort.
    5175                 :             :      */
    5176         [ +  - ]:          90 :     if (grouping_is_sortable(root->processed_distinctClause))
    5177                 :             :     {
    5178   [ +  -  +  +  :         193 :         foreach(lc, input_rel->partial_pathlist)
                   +  + ]
    5179                 :             :         {
    5180                 :         103 :             Path       *input_path = (Path *) lfirst(lc);
    5181                 :             :             Path       *sorted_path;
    5182                 :         103 :             List       *useful_pathkeys_list = NIL;
    5183                 :             : 
    5184                 :             :             useful_pathkeys_list =
    5185                 :         103 :                 get_useful_pathkeys_for_distinct(root,
    5186                 :             :                                                  root->distinct_pathkeys,
    5187                 :             :                                                  input_path->pathkeys);
    5188                 :             :             Assert(list_length(useful_pathkeys_list) > 0);
    5189                 :             : 
    5190   [ +  -  +  +  :         319 :             foreach_node(List, useful_pathkeys, useful_pathkeys_list)
                   +  + ]
    5191                 :             :             {
    5192                 :         113 :                 sorted_path = make_ordered_path(root,
    5193                 :             :                                                 partial_distinct_rel,
    5194                 :             :                                                 input_path,
    5195                 :             :                                                 cheapest_partial_path,
    5196                 :             :                                                 useful_pathkeys,
    5197                 :             :                                                 -1.0);
    5198                 :             : 
    5199         [ +  + ]:         113 :                 if (sorted_path == NULL)
    5200                 :           8 :                     continue;
    5201                 :             : 
    5202                 :             :                 /*
    5203                 :             :                  * An empty distinct_pathkeys means all tuples have the same
    5204                 :             :                  * value for the DISTINCT clause.  See
    5205                 :             :                  * create_final_distinct_paths()
    5206                 :             :                  */
    5207         [ +  + ]:         105 :                 if (root->distinct_pathkeys == NIL)
    5208                 :             :                 {
    5209                 :             :                     Node       *limitCount;
    5210                 :             : 
    5211                 :           5 :                     limitCount = (Node *) makeConst(INT8OID, -1, InvalidOid,
    5212                 :             :                                                     sizeof(int64),
    5213                 :             :                                                     Int64GetDatum(1), false,
    5214                 :             :                                                     true);
    5215                 :             : 
    5216                 :             :                     /*
    5217                 :             :                      * Apply a LimitPath onto the partial path to restrict the
    5218                 :             :                      * tuples from each worker to 1.
    5219                 :             :                      * create_final_distinct_paths will need to apply an
    5220                 :             :                      * additional LimitPath to restrict this to a single row
    5221                 :             :                      * after the Gather node.  If the query already has a
    5222                 :             :                      * LIMIT clause, then we could end up with three Limit
    5223                 :             :                      * nodes in the final plan.  Consolidating the top two of
    5224                 :             :                      * these could be done, but does not seem worth troubling
    5225                 :             :                      * over.
    5226                 :             :                      */
    5227                 :           5 :                     add_partial_path(partial_distinct_rel, (Path *)
    5228                 :           5 :                                      create_limit_path(root, partial_distinct_rel,
    5229                 :             :                                                        sorted_path,
    5230                 :             :                                                        NULL,
    5231                 :             :                                                        limitCount,
    5232                 :             :                                                        LIMIT_OPTION_COUNT,
    5233                 :             :                                                        0, 1));
    5234                 :             :                 }
    5235                 :             :                 else
    5236                 :             :                 {
    5237                 :         100 :                     add_partial_path(partial_distinct_rel, (Path *)
    5238                 :         100 :                                      create_unique_path(root, partial_distinct_rel,
    5239                 :             :                                                         sorted_path,
    5240                 :         100 :                                                         list_length(root->distinct_pathkeys),
    5241                 :             :                                                         numDistinctRows));
    5242                 :             :                 }
    5243                 :             :             }
    5244                 :             :         }
    5245                 :             :     }
    5246                 :             : 
    5247                 :             :     /*
    5248                 :             :      * Now try hash aggregate paths, if enabled and hashing is possible. Since
    5249                 :             :      * we're not on the hook to ensure we do our best to create at least one
    5250                 :             :      * path here, we treat enable_hashagg as a hard off-switch rather than the
    5251                 :             :      * slightly softer variant in create_final_distinct_paths.
    5252                 :             :      */
    5253   [ +  +  +  - ]:          90 :     if (enable_hashagg && grouping_is_hashable(root->processed_distinctClause))
    5254                 :             :     {
    5255                 :          65 :         add_partial_path(partial_distinct_rel, (Path *)
    5256                 :          65 :                          create_agg_path(root,
    5257                 :             :                                          partial_distinct_rel,
    5258                 :             :                                          cheapest_partial_path,
    5259                 :             :                                          cheapest_partial_path->pathtarget,
    5260                 :             :                                          AGG_HASHED,
    5261                 :             :                                          AGGSPLIT_SIMPLE,
    5262                 :             :                                          root->processed_distinctClause,
    5263                 :             :                                          NIL,
    5264                 :             :                                          NULL,
    5265                 :             :                                          numDistinctRows));
    5266                 :             :     }
    5267                 :             : 
    5268                 :             :     /*
    5269                 :             :      * If there is an FDW that's responsible for all baserels of the query,
    5270                 :             :      * let it consider adding ForeignPaths.
    5271                 :             :      */
    5272         [ -  + ]:          90 :     if (partial_distinct_rel->fdwroutine &&
    5273         [ #  # ]:           0 :         partial_distinct_rel->fdwroutine->GetForeignUpperPaths)
    5274                 :           0 :         partial_distinct_rel->fdwroutine->GetForeignUpperPaths(root,
    5275                 :             :                                                                UPPERREL_PARTIAL_DISTINCT,
    5276                 :             :                                                                input_rel,
    5277                 :             :                                                                partial_distinct_rel,
    5278                 :             :                                                                NULL);
    5279                 :             : 
    5280                 :             :     /* Let extensions possibly add some more partial paths */
    5281         [ -  + ]:          90 :     if (create_upper_paths_hook)
    5282                 :           0 :         (*create_upper_paths_hook) (root, UPPERREL_PARTIAL_DISTINCT,
    5283                 :             :                                     input_rel, partial_distinct_rel, NULL);
    5284                 :             : 
    5285         [ +  - ]:          90 :     if (partial_distinct_rel->partial_pathlist != NIL)
    5286                 :             :     {
    5287                 :          90 :         generate_useful_gather_paths(root, partial_distinct_rel, true);
    5288                 :          90 :         set_cheapest(partial_distinct_rel);
    5289                 :             : 
    5290                 :             :         /*
    5291                 :             :          * Finally, create paths to distinctify the final result.  This step
    5292                 :             :          * is needed to remove any duplicates due to combining rows from
    5293                 :             :          * parallel workers.
    5294                 :             :          */
    5295                 :          90 :         create_final_distinct_paths(root, partial_distinct_rel,
    5296                 :             :                                     final_distinct_rel);
    5297                 :             :     }
    5298                 :             : }
    5299                 :             : 
    5300                 :             : /*
    5301                 :             :  * create_final_distinct_paths
    5302                 :             :  *      Create distinct paths in 'distinct_rel' based on 'input_rel' pathlist
    5303                 :             :  *
    5304                 :             :  * input_rel: contains the source-data paths
    5305                 :             :  * distinct_rel: destination relation for storing created paths
    5306                 :             :  */
    5307                 :             : static RelOptInfo *
    5308                 :        2107 : create_final_distinct_paths(PlannerInfo *root, RelOptInfo *input_rel,
    5309                 :             :                             RelOptInfo *distinct_rel)
    5310                 :             : {
    5311                 :        2107 :     Query      *parse = root->parse;
    5312                 :        2107 :     Path       *cheapest_input_path = input_rel->cheapest_total_path;
    5313                 :             :     double      numDistinctRows;
    5314                 :             :     bool        allow_hash;
    5315                 :             : 
    5316                 :             :     /* Estimate number of distinct rows there will be */
    5317   [ +  +  +  -  :        2107 :     if (parse->groupClause || parse->groupingSets || parse->hasAggs ||
                   +  + ]
    5318         [ -  + ]:        2048 :         root->hasHavingQual)
    5319                 :             :     {
    5320                 :             :         /*
    5321                 :             :          * If there was grouping or aggregation, use the number of input rows
    5322                 :             :          * as the estimated number of DISTINCT rows (ie, assume the input is
    5323                 :             :          * already mostly unique).
    5324                 :             :          */
    5325                 :          59 :         numDistinctRows = cheapest_input_path->rows;
    5326                 :             :     }
    5327                 :             :     else
    5328                 :             :     {
    5329                 :             :         /*
    5330                 :             :          * Otherwise, the UNIQUE filter has effects comparable to GROUP BY.
    5331                 :             :          */
    5332                 :             :         List       *distinctExprs;
    5333                 :             : 
    5334                 :        2048 :         distinctExprs = get_sortgrouplist_exprs(root->processed_distinctClause,
    5335                 :             :                                                 parse->targetList);
    5336                 :        2048 :         numDistinctRows = estimate_num_groups(root, distinctExprs,
    5337                 :             :                                               cheapest_input_path->rows,
    5338                 :             :                                               NULL, NULL);
    5339                 :             :     }
    5340                 :             : 
    5341                 :             :     /*
    5342                 :             :      * Consider sort-based implementations of DISTINCT, if possible.
    5343                 :             :      */
    5344         [ +  + ]:        2107 :     if (grouping_is_sortable(root->processed_distinctClause))
    5345                 :             :     {
    5346                 :             :         /*
    5347                 :             :          * Firstly, if we have any adequately-presorted paths, just stick a
    5348                 :             :          * Unique node on those.  We also, consider doing an explicit sort of
    5349                 :             :          * the cheapest input path and Unique'ing that.  If any paths have
    5350                 :             :          * presorted keys then we'll create an incremental sort atop of those
    5351                 :             :          * before adding a unique node on the top.  We'll also attempt to
    5352                 :             :          * reorder the required pathkeys to match the input path's pathkeys as
    5353                 :             :          * much as possible, in hopes of avoiding a possible need to re-sort.
    5354                 :             :          *
    5355                 :             :          * When we have DISTINCT ON, we must sort by the more rigorous of
    5356                 :             :          * DISTINCT and ORDER BY, else it won't have the desired behavior.
    5357                 :             :          * Also, if we do have to do an explicit sort, we might as well use
    5358                 :             :          * the more rigorous ordering to avoid a second sort later.  (Note
    5359                 :             :          * that the parser will have ensured that one clause is a prefix of
    5360                 :             :          * the other.)
    5361                 :             :          */
    5362                 :             :         List       *needed_pathkeys;
    5363                 :             :         ListCell   *lc;
    5364         [ +  + ]:        2102 :         double      limittuples = root->distinct_pathkeys == NIL ? 1.0 : -1.0;
    5365                 :             : 
    5366   [ +  +  +  + ]:        2329 :         if (parse->hasDistinctOn &&
    5367                 :         227 :             list_length(root->distinct_pathkeys) <
    5368                 :         227 :             list_length(root->sort_pathkeys))
    5369                 :          93 :             needed_pathkeys = root->sort_pathkeys;
    5370                 :             :         else
    5371                 :        2009 :             needed_pathkeys = root->distinct_pathkeys;
    5372                 :             : 
    5373   [ +  -  +  +  :        5529 :         foreach(lc, input_rel->pathlist)
                   +  + ]
    5374                 :             :         {
    5375                 :        3427 :             Path       *input_path = (Path *) lfirst(lc);
    5376                 :             :             Path       *sorted_path;
    5377                 :        3427 :             List       *useful_pathkeys_list = NIL;
    5378                 :             : 
    5379                 :             :             useful_pathkeys_list =
    5380                 :        3427 :                 get_useful_pathkeys_for_distinct(root,
    5381                 :             :                                                  needed_pathkeys,
    5382                 :             :                                                  input_path->pathkeys);
    5383                 :             :             Assert(list_length(useful_pathkeys_list) > 0);
    5384                 :             : 
    5385   [ +  -  +  +  :       10796 :             foreach_node(List, useful_pathkeys, useful_pathkeys_list)
                   +  + ]
    5386                 :             :             {
    5387                 :        3942 :                 sorted_path = make_ordered_path(root,
    5388                 :             :                                                 distinct_rel,
    5389                 :             :                                                 input_path,
    5390                 :             :                                                 cheapest_input_path,
    5391                 :             :                                                 useful_pathkeys,
    5392                 :             :                                                 limittuples);
    5393                 :             : 
    5394         [ +  + ]:        3942 :                 if (sorted_path == NULL)
    5395                 :         546 :                     continue;
    5396                 :             : 
    5397                 :             :                 /*
    5398                 :             :                  * distinct_pathkeys may have become empty if all of the
    5399                 :             :                  * pathkeys were determined to be redundant.  If all of the
    5400                 :             :                  * pathkeys are redundant then each DISTINCT target must only
    5401                 :             :                  * allow a single value, therefore all resulting tuples must
    5402                 :             :                  * be identical (or at least indistinguishable by an equality
    5403                 :             :                  * check).  We can uniquify these tuples simply by just taking
    5404                 :             :                  * the first tuple.  All we do here is add a path to do "LIMIT
    5405                 :             :                  * 1" atop of 'sorted_path'.  When doing a DISTINCT ON we may
    5406                 :             :                  * still have a non-NIL sort_pathkeys list, so we must still
    5407                 :             :                  * only do this with paths which are correctly sorted by
    5408                 :             :                  * sort_pathkeys.
    5409                 :             :                  */
    5410         [ +  + ]:        3396 :                 if (root->distinct_pathkeys == NIL)
    5411                 :             :                 {
    5412                 :             :                     Node       *limitCount;
    5413                 :             : 
    5414                 :         116 :                     limitCount = (Node *) makeConst(INT8OID, -1, InvalidOid,
    5415                 :             :                                                     sizeof(int64),
    5416                 :             :                                                     Int64GetDatum(1), false,
    5417                 :             :                                                     true);
    5418                 :             : 
    5419                 :             :                     /*
    5420                 :             :                      * If the query already has a LIMIT clause, then we could
    5421                 :             :                      * end up with a duplicate LimitPath in the final plan.
    5422                 :             :                      * That does not seem worth troubling over too much.
    5423                 :             :                      */
    5424                 :         116 :                     add_path(distinct_rel, (Path *)
    5425                 :         116 :                              create_limit_path(root, distinct_rel, sorted_path,
    5426                 :             :                                                NULL, limitCount,
    5427                 :             :                                                LIMIT_OPTION_COUNT, 0, 1));
    5428                 :             :                 }
    5429                 :             :                 else
    5430                 :             :                 {
    5431                 :        3280 :                     add_path(distinct_rel, (Path *)
    5432                 :        3280 :                              create_unique_path(root, distinct_rel,
    5433                 :             :                                                 sorted_path,
    5434                 :        3280 :                                                 list_length(root->distinct_pathkeys),
    5435                 :             :                                                 numDistinctRows));
    5436                 :             :                 }
    5437                 :             :             }
    5438                 :             :         }
    5439                 :             :     }
    5440                 :             : 
    5441                 :             :     /*
    5442                 :             :      * Consider hash-based implementations of DISTINCT, if possible.
    5443                 :             :      *
    5444                 :             :      * If we were not able to make any other types of path, we *must* hash or
    5445                 :             :      * die trying.  If we do have other choices, there are two things that
    5446                 :             :      * should prevent selection of hashing: if the query uses DISTINCT ON
    5447                 :             :      * (because it won't really have the expected behavior if we hash), or if
    5448                 :             :      * enable_hashagg is off.
    5449                 :             :      *
    5450                 :             :      * Note: grouping_is_hashable() is much more expensive to check than the
    5451                 :             :      * other gating conditions, so we want to do it last.
    5452                 :             :      */
    5453         [ +  + ]:        2107 :     if (distinct_rel->pathlist == NIL)
    5454                 :           5 :         allow_hash = true;      /* we have no alternatives */
    5455   [ +  +  +  + ]:        2102 :     else if (parse->hasDistinctOn || !enable_hashagg)
    5456                 :         352 :         allow_hash = false;     /* policy-based decision not to hash */
    5457                 :             :     else
    5458                 :        1750 :         allow_hash = true;      /* default */
    5459                 :             : 
    5460   [ +  +  +  - ]:        2107 :     if (allow_hash && grouping_is_hashable(root->processed_distinctClause))
    5461                 :             :     {
    5462                 :             :         /* Generate hashed aggregate path --- no sort needed */
    5463                 :        1755 :         add_path(distinct_rel, (Path *)
    5464                 :        1755 :                  create_agg_path(root,
    5465                 :             :                                  distinct_rel,
    5466                 :             :                                  cheapest_input_path,
    5467                 :             :                                  cheapest_input_path->pathtarget,
    5468                 :             :                                  AGG_HASHED,
    5469                 :             :                                  AGGSPLIT_SIMPLE,
    5470                 :             :                                  root->processed_distinctClause,
    5471                 :             :                                  NIL,
    5472                 :             :                                  NULL,
    5473                 :             :                                  numDistinctRows));
    5474                 :             :     }
    5475                 :             : 
    5476                 :        2107 :     return distinct_rel;
    5477                 :             : }
    5478                 :             : 
    5479                 :             : /*
    5480                 :             :  * get_useful_pathkeys_for_distinct
    5481                 :             :  *    Get useful orderings of pathkeys for distinctClause by reordering
    5482                 :             :  *    'needed_pathkeys' to match the given 'path_pathkeys' as much as possible.
    5483                 :             :  *
    5484                 :             :  * This returns a list of pathkeys that can be useful for DISTINCT or DISTINCT
    5485                 :             :  * ON clause.  For convenience, it always includes the given 'needed_pathkeys'.
    5486                 :             :  */
    5487                 :             : static List *
    5488                 :        3530 : get_useful_pathkeys_for_distinct(PlannerInfo *root, List *needed_pathkeys,
    5489                 :             :                                  List *path_pathkeys)
    5490                 :             : {
    5491                 :        3530 :     List       *useful_pathkeys_list = NIL;
    5492                 :        3530 :     List       *useful_pathkeys = NIL;
    5493                 :             : 
    5494                 :             :     /* always include the given 'needed_pathkeys' */
    5495                 :        3530 :     useful_pathkeys_list = lappend(useful_pathkeys_list,
    5496                 :             :                                    needed_pathkeys);
    5497                 :             : 
    5498         [ -  + ]:        3530 :     if (!enable_distinct_reordering)
    5499                 :           0 :         return useful_pathkeys_list;
    5500                 :             : 
    5501                 :             :     /*
    5502                 :             :      * Scan the given 'path_pathkeys' and construct a list of PathKey nodes
    5503                 :             :      * that match 'needed_pathkeys', but only up to the longest matching
    5504                 :             :      * prefix.
    5505                 :             :      *
    5506                 :             :      * When we have DISTINCT ON, we must ensure that the resulting pathkey
    5507                 :             :      * list matches initial distinctClause pathkeys; otherwise, it won't have
    5508                 :             :      * the desired behavior.
    5509                 :             :      */
    5510   [ +  +  +  +  :        8779 :     foreach_node(PathKey, pathkey, path_pathkeys)
                   +  + ]
    5511                 :             :     {
    5512                 :             :         /*
    5513                 :             :          * The PathKey nodes are canonical, so they can be checked for
    5514                 :             :          * equality by simple pointer comparison.
    5515                 :             :          */
    5516         [ +  + ]:        1741 :         if (!list_member_ptr(needed_pathkeys, pathkey))
    5517                 :           7 :             break;
    5518         [ +  + ]:        1734 :         if (root->parse->hasDistinctOn &&
    5519         [ +  + ]:         139 :             !list_member_ptr(root->distinct_pathkeys, pathkey))
    5520                 :          15 :             break;
    5521                 :             : 
    5522                 :        1719 :         useful_pathkeys = lappend(useful_pathkeys, pathkey);
    5523                 :             :     }
    5524                 :             : 
    5525                 :             :     /* If no match at all, no point in reordering needed_pathkeys */
    5526         [ +  + ]:        3530 :     if (useful_pathkeys == NIL)
    5527                 :        2059 :         return useful_pathkeys_list;
    5528                 :             : 
    5529                 :             :     /*
    5530                 :             :      * If not full match, the resulting pathkey list is not useful without
    5531                 :             :      * incremental sort.
    5532                 :             :      */
    5533         [ +  + ]:        1471 :     if (list_length(useful_pathkeys) < list_length(needed_pathkeys) &&
    5534         [ +  + ]:         939 :         !enable_incremental_sort)
    5535                 :          48 :         return useful_pathkeys_list;
    5536                 :             : 
    5537                 :             :     /* Append the remaining PathKey nodes in needed_pathkeys */
    5538                 :        1423 :     useful_pathkeys = list_concat_unique_ptr(useful_pathkeys,
    5539                 :             :                                              needed_pathkeys);
    5540                 :             : 
    5541                 :             :     /*
    5542                 :             :      * If the resulting pathkey list is the same as the 'needed_pathkeys',
    5543                 :             :      * just drop it.
    5544                 :             :      */
    5545         [ +  + ]:        1423 :     if (compare_pathkeys(needed_pathkeys,
    5546                 :             :                          useful_pathkeys) == PATHKEYS_EQUAL)
    5547                 :         898 :         return useful_pathkeys_list;
    5548                 :             : 
    5549                 :         525 :     useful_pathkeys_list = lappend(useful_pathkeys_list,
    5550                 :             :                                    useful_pathkeys);
    5551                 :             : 
    5552                 :         525 :     return useful_pathkeys_list;
    5553                 :             : }
    5554                 :             : 
    5555                 :             : /*
    5556                 :             :  * create_ordered_paths
    5557                 :             :  *
    5558                 :             :  * Build a new upperrel containing Paths for ORDER BY evaluation.
    5559                 :             :  *
    5560                 :             :  * All paths in the result must satisfy the ORDER BY ordering.
    5561                 :             :  * The only new paths we need consider are an explicit full sort
    5562                 :             :  * and incremental sort on the cheapest-total existing path.
    5563                 :             :  *
    5564                 :             :  * input_rel: contains the source-data Paths
    5565                 :             :  * target: the output tlist the result Paths must emit
    5566                 :             :  * limit_tuples: estimated bound on the number of output tuples,
    5567                 :             :  *      or -1 if no LIMIT or couldn't estimate
    5568                 :             :  *
    5569                 :             :  * XXX This only looks at sort_pathkeys. I wonder if it needs to look at the
    5570                 :             :  * other pathkeys (grouping, ...) like generate_useful_gather_paths.
    5571                 :             :  */
    5572                 :             : static RelOptInfo *
    5573                 :       61265 : create_ordered_paths(PlannerInfo *root,
    5574                 :             :                      RelOptInfo *input_rel,
    5575                 :             :                      PathTarget *target,
    5576                 :             :                      bool target_parallel_safe,
    5577                 :             :                      double limit_tuples)
    5578                 :             : {
    5579                 :       61265 :     Path       *cheapest_input_path = input_rel->cheapest_total_path;
    5580                 :             :     RelOptInfo *ordered_rel;
    5581                 :             :     ListCell   *lc;
    5582                 :             : 
    5583                 :             :     /* For now, do all work in the (ORDERED, NULL) upperrel */
    5584                 :       61265 :     ordered_rel = fetch_upper_rel(root, UPPERREL_ORDERED, NULL);
    5585                 :             : 
    5586                 :             :     /*
    5587                 :             :      * If the input relation is not parallel-safe, then the ordered relation
    5588                 :             :      * can't be parallel-safe, either.  Otherwise, it's parallel-safe if the
    5589                 :             :      * target list is parallel-safe.
    5590                 :             :      */
    5591   [ +  +  +  + ]:       61265 :     if (input_rel->consider_parallel && target_parallel_safe)
    5592                 :       43024 :         ordered_rel->consider_parallel = true;
    5593                 :             : 
    5594                 :             :     /* Assume that the same path generation strategies are allowed. */
    5595                 :       61265 :     ordered_rel->pgs_mask = input_rel->pgs_mask;
    5596                 :             : 
    5597                 :             :     /*
    5598                 :             :      * If the input rel belongs to a single FDW, so does the ordered_rel.
    5599                 :             :      */
    5600                 :       61265 :     ordered_rel->serverid = input_rel->serverid;
    5601                 :       61265 :     ordered_rel->userid = input_rel->userid;
    5602                 :       61265 :     ordered_rel->useridiscurrent = input_rel->useridiscurrent;
    5603                 :       61265 :     ordered_rel->fdwroutine = input_rel->fdwroutine;
    5604                 :             : 
    5605   [ +  -  +  +  :      155854 :     foreach(lc, input_rel->pathlist)
                   +  + ]
    5606                 :             :     {
    5607                 :       94589 :         Path       *input_path = (Path *) lfirst(lc);
    5608                 :             :         Path       *sorted_path;
    5609                 :             :         bool        is_sorted;
    5610                 :             :         int         presorted_keys;
    5611                 :             : 
    5612                 :       94589 :         is_sorted = pathkeys_count_contained_in(root->sort_pathkeys,
    5613                 :             :                                                 input_path->pathkeys, &presorted_keys);
    5614                 :             : 
    5615         [ +  + ]:       94589 :         if (is_sorted)
    5616                 :       36616 :             sorted_path = input_path;
    5617                 :             :         else
    5618                 :             :         {
    5619                 :             :             /*
    5620                 :             :              * Try at least sorting the cheapest path and also try
    5621                 :             :              * incrementally sorting any path which is partially sorted
    5622                 :             :              * already (no need to deal with paths which have presorted keys
    5623                 :             :              * when incremental sort is disabled unless it's the cheapest
    5624                 :             :              * input path).
    5625                 :             :              */
    5626         [ +  + ]:       57973 :             if (input_path != cheapest_input_path &&
    5627   [ +  +  +  + ]:        4415 :                 (presorted_keys == 0 || !enable_incremental_sort))
    5628                 :        1669 :                 continue;
    5629                 :             : 
    5630                 :             :             /*
    5631                 :             :              * We've no need to consider both a sort and incremental sort.
    5632                 :             :              * We'll just do a sort if there are no presorted keys and an
    5633                 :             :              * incremental sort when there are presorted keys.
    5634                 :             :              */
    5635   [ +  +  +  + ]:       56304 :             if (presorted_keys == 0 || !enable_incremental_sort)
    5636                 :       52870 :                 sorted_path = (Path *) create_sort_path(root,
    5637                 :             :                                                         ordered_rel,
    5638                 :             :                                                         input_path,
    5639                 :             :                                                         root->sort_pathkeys,
    5640                 :             :                                                         limit_tuples);
    5641                 :             :             else
    5642                 :        3434 :                 sorted_path = (Path *) create_incremental_sort_path(root,
    5643                 :             :                                                                     ordered_rel,
    5644                 :             :                                                                     input_path,
    5645                 :             :                                                                     root->sort_pathkeys,
    5646                 :             :                                                                     presorted_keys,
    5647                 :             :                                                                     limit_tuples);
    5648                 :             :         }
    5649                 :             : 
    5650                 :             :         /*
    5651                 :             :          * If the pathtarget of the result path has different expressions from
    5652                 :             :          * the target to be applied, a projection step is needed.
    5653                 :             :          */
    5654         [ +  + ]:       92920 :         if (!equal(sorted_path->pathtarget->exprs, target->exprs))
    5655                 :         303 :             sorted_path = apply_projection_to_path(root, ordered_rel,
    5656                 :             :                                                    sorted_path, target);
    5657                 :             : 
    5658                 :       92920 :         add_path(ordered_rel, sorted_path);
    5659                 :             :     }
    5660                 :             : 
    5661                 :             :     /*
    5662                 :             :      * generate_gather_paths() will have already generated a simple Gather
    5663                 :             :      * path for the best parallel path, if any, and the loop above will have
    5664                 :             :      * considered sorting it.  Similarly, generate_gather_paths() will also
    5665                 :             :      * have generated order-preserving Gather Merge plans which can be used
    5666                 :             :      * without sorting if they happen to match the sort_pathkeys, and the loop
    5667                 :             :      * above will have handled those as well.  However, there's one more
    5668                 :             :      * possibility: it may make sense to sort the cheapest partial path or
    5669                 :             :      * incrementally sort any partial path that is partially sorted according
    5670                 :             :      * to the required output order and then use Gather Merge.
    5671                 :             :      */
    5672   [ +  +  +  + ]:       61265 :     if (ordered_rel->consider_parallel && root->sort_pathkeys != NIL &&
    5673         [ +  + ]:       42904 :         input_rel->partial_pathlist != NIL)
    5674                 :             :     {
    5675                 :             :         Path       *cheapest_partial_path;
    5676                 :             : 
    5677                 :        2378 :         cheapest_partial_path = linitial(input_rel->partial_pathlist);
    5678                 :             : 
    5679   [ +  -  +  +  :        5311 :         foreach(lc, input_rel->partial_pathlist)
                   +  + ]
    5680                 :             :         {
    5681                 :        2933 :             Path       *input_path = (Path *) lfirst(lc);
    5682                 :             :             Path       *sorted_path;
    5683                 :             :             bool        is_sorted;
    5684                 :             :             int         presorted_keys;
    5685                 :             :             double      total_groups;
    5686                 :             : 
    5687                 :        2933 :             is_sorted = pathkeys_count_contained_in(root->sort_pathkeys,
    5688                 :             :                                                     input_path->pathkeys,
    5689                 :             :                                                     &presorted_keys);
    5690                 :             : 
    5691         [ +  + ]:        2933 :             if (is_sorted)
    5692                 :         476 :                 continue;
    5693                 :             : 
    5694                 :             :             /*
    5695                 :             :              * Try at least sorting the cheapest path and also try
    5696                 :             :              * incrementally sorting any path which is partially sorted
    5697                 :             :              * already (no need to deal with paths which have presorted keys
    5698                 :             :              * when incremental sort is disabled unless it's the cheapest
    5699                 :             :              * partial path).
    5700                 :             :              */
    5701         [ +  + ]:        2457 :             if (input_path != cheapest_partial_path &&
    5702   [ +  -  -  + ]:         101 :                 (presorted_keys == 0 || !enable_incremental_sort))
    5703                 :           0 :                 continue;
    5704                 :             : 
    5705                 :             :             /*
    5706                 :             :              * We've no need to consider both a sort and incremental sort.
    5707                 :             :              * We'll just do a sort if there are no presorted keys and an
    5708                 :             :              * incremental sort when there are presorted keys.
    5709                 :             :              */
    5710   [ +  +  +  + ]:        2457 :             if (presorted_keys == 0 || !enable_incremental_sort)
    5711                 :        2341 :                 sorted_path = (Path *) create_sort_path(root,
    5712                 :             :                                                         ordered_rel,
    5713                 :             :                                                         input_path,
    5714                 :             :                                                         root->sort_pathkeys,
    5715                 :             :                                                         limit_tuples);
    5716                 :             :             else
    5717                 :         116 :                 sorted_path = (Path *) create_incremental_sort_path(root,
    5718                 :             :                                                                     ordered_rel,
    5719                 :             :                                                                     input_path,
    5720                 :             :                                                                     root->sort_pathkeys,
    5721                 :             :                                                                     presorted_keys,
    5722                 :             :                                                                     limit_tuples);
    5723                 :        2457 :             total_groups = compute_gather_rows(sorted_path);
    5724                 :             :             sorted_path = (Path *)
    5725                 :        2457 :                 create_gather_merge_path(root, ordered_rel,
    5726                 :             :                                          sorted_path,
    5727                 :             :                                          sorted_path->pathtarget,
    5728                 :             :                                          root->sort_pathkeys, NULL,
    5729                 :             :                                          &total_groups);
    5730                 :             : 
    5731                 :             :             /*
    5732                 :             :              * If the pathtarget of the result path has different expressions
    5733                 :             :              * from the target to be applied, a projection step is needed.
    5734                 :             :              */
    5735         [ +  + ]:        2457 :             if (!equal(sorted_path->pathtarget->exprs, target->exprs))
    5736                 :           5 :                 sorted_path = apply_projection_to_path(root, ordered_rel,
    5737                 :             :                                                        sorted_path, target);
    5738                 :             : 
    5739                 :        2457 :             add_path(ordered_rel, sorted_path);
    5740                 :             :         }
    5741                 :             :     }
    5742                 :             : 
    5743                 :             :     /*
    5744                 :             :      * If there is an FDW that's responsible for all baserels of the query,
    5745                 :             :      * let it consider adding ForeignPaths.
    5746                 :             :      */
    5747         [ +  + ]:       61265 :     if (ordered_rel->fdwroutine &&
    5748         [ +  + ]:         197 :         ordered_rel->fdwroutine->GetForeignUpperPaths)
    5749                 :         189 :         ordered_rel->fdwroutine->GetForeignUpperPaths(root, UPPERREL_ORDERED,
    5750                 :             :                                                       input_rel, ordered_rel,
    5751                 :             :                                                       NULL);
    5752                 :             : 
    5753                 :             :     /* Let extensions possibly add some more paths */
    5754         [ -  + ]:       61265 :     if (create_upper_paths_hook)
    5755                 :           0 :         (*create_upper_paths_hook) (root, UPPERREL_ORDERED,
    5756                 :             :                                     input_rel, ordered_rel, NULL);
    5757                 :             : 
    5758                 :             :     /*
    5759                 :             :      * No need to bother with set_cheapest here; grouping_planner does not
    5760                 :             :      * need us to do it.
    5761                 :             :      */
    5762                 :             :     Assert(ordered_rel->pathlist != NIL);
    5763                 :             : 
    5764                 :       61265 :     return ordered_rel;
    5765                 :             : }
    5766                 :             : 
    5767                 :             : 
    5768                 :             : /*
    5769                 :             :  * make_group_input_target
    5770                 :             :  *    Generate appropriate PathTarget for initial input to grouping nodes.
    5771                 :             :  *
    5772                 :             :  * If there is grouping or aggregation, the scan/join subplan cannot emit
    5773                 :             :  * the query's final targetlist; for example, it certainly can't emit any
    5774                 :             :  * aggregate function calls.  This routine generates the correct target
    5775                 :             :  * for the scan/join subplan.
    5776                 :             :  *
    5777                 :             :  * The query target list passed from the parser already contains entries
    5778                 :             :  * for all ORDER BY and GROUP BY expressions, but it will not have entries
    5779                 :             :  * for variables used only in HAVING clauses; so we need to add those
    5780                 :             :  * variables to the subplan target list.  Also, we flatten all expressions
    5781                 :             :  * except GROUP BY items into their component variables; other expressions
    5782                 :             :  * will be computed by the upper plan nodes rather than by the subplan.
    5783                 :             :  * For example, given a query like
    5784                 :             :  *      SELECT a+b,SUM(c+d) FROM table GROUP BY a+b;
    5785                 :             :  * we want to pass this targetlist to the subplan:
    5786                 :             :  *      a+b,c,d
    5787                 :             :  * where the a+b target will be used by the Sort/Group steps, and the
    5788                 :             :  * other targets will be used for computing the final results.
    5789                 :             :  *
    5790                 :             :  * 'final_target' is the query's final target list (in PathTarget form)
    5791                 :             :  *
    5792                 :             :  * The result is the PathTarget to be computed by the Paths returned from
    5793                 :             :  * query_planner().
    5794                 :             :  */
    5795                 :             : static PathTarget *
    5796                 :       34142 : make_group_input_target(PlannerInfo *root, PathTarget *final_target)
    5797                 :             : {
    5798                 :       34142 :     Query      *parse = root->parse;
    5799                 :             :     PathTarget *input_target;
    5800                 :             :     List       *non_group_cols;
    5801                 :             :     List       *non_group_vars;
    5802                 :             :     int         i;
    5803                 :             :     ListCell   *lc;
    5804                 :             : 
    5805                 :             :     /*
    5806                 :             :      * We must build a target containing all grouping columns, plus any other
    5807                 :             :      * Vars mentioned in the query's targetlist and HAVING qual.
    5808                 :             :      */
    5809                 :       34142 :     input_target = create_empty_pathtarget();
    5810                 :       34142 :     non_group_cols = NIL;
    5811                 :             : 
    5812                 :       34142 :     i = 0;
    5813   [ +  -  +  +  :       86062 :     foreach(lc, final_target->exprs)
                   +  + ]
    5814                 :             :     {
    5815                 :       51920 :         Expr       *expr = (Expr *) lfirst(lc);
    5816         [ +  - ]:       51920 :         Index       sgref = get_pathtarget_sortgroupref(final_target, i);
    5817                 :             : 
    5818   [ +  +  +  +  :       60140 :         if (sgref && root->processed_groupClause &&
                   +  + ]
    5819                 :        8220 :             get_sortgroupref_clause_noerr(sgref,
    5820                 :             :                                           root->processed_groupClause) != NULL)
    5821                 :             :         {
    5822                 :             :             /*
    5823                 :             :              * It's a grouping column, so add it to the input target as-is.
    5824                 :             :              *
    5825                 :             :              * Note that the target is logically below the grouping step.  So
    5826                 :             :              * with grouping sets we need to remove the RT index of the
    5827                 :             :              * grouping step if there is any from the target expression.
    5828                 :             :              */
    5829   [ +  -  +  + ]:        6699 :             if (parse->hasGroupRTE && parse->groupingSets != NIL)
    5830                 :             :             {
    5831                 :             :                 Assert(root->group_rtindex > 0);
    5832                 :             :                 expr = (Expr *)
    5833                 :        1803 :                     remove_nulling_relids((Node *) expr,
    5834                 :        1803 :                                           bms_make_singleton(root->group_rtindex),
    5835                 :             :                                           NULL);
    5836                 :             :             }
    5837                 :        6699 :             add_column_to_pathtarget(input_target, expr, sgref);
    5838                 :             :         }
    5839                 :             :         else
    5840                 :             :         {
    5841                 :             :             /*
    5842                 :             :              * Non-grouping column, so just remember the expression for later
    5843                 :             :              * call to pull_var_clause.
    5844                 :             :              */
    5845                 :       45221 :             non_group_cols = lappend(non_group_cols, expr);
    5846                 :             :         }
    5847                 :             : 
    5848                 :       51920 :         i++;
    5849                 :             :     }
    5850                 :             : 
    5851                 :             :     /*
    5852                 :             :      * If there's a HAVING clause, we'll need the Vars it uses, too.
    5853                 :             :      */
    5854         [ +  + ]:       34142 :     if (parse->havingQual)
    5855                 :         882 :         non_group_cols = lappend(non_group_cols, parse->havingQual);
    5856                 :             : 
    5857                 :             :     /*
    5858                 :             :      * Pull out all the Vars mentioned in non-group cols (plus HAVING), and
    5859                 :             :      * add them to the input target if not already present.  (A Var used
    5860                 :             :      * directly as a GROUP BY item will be present already.)  Note this
    5861                 :             :      * includes Vars used in resjunk items, so we are covering the needs of
    5862                 :             :      * ORDER BY and window specifications.  Vars used within Aggrefs and
    5863                 :             :      * WindowFuncs will be pulled out here, too.
    5864                 :             :      *
    5865                 :             :      * Note that the target is logically below the grouping step.  So with
    5866                 :             :      * grouping sets we need to remove the RT index of the grouping step if
    5867                 :             :      * there is any from the non-group Vars.
    5868                 :             :      */
    5869                 :       34142 :     non_group_vars = pull_var_clause((Node *) non_group_cols,
    5870                 :             :                                      PVC_RECURSE_AGGREGATES |
    5871                 :             :                                      PVC_RECURSE_WINDOWFUNCS |
    5872                 :             :                                      PVC_INCLUDE_PLACEHOLDERS);
    5873   [ +  +  +  + ]:       34142 :     if (parse->hasGroupRTE && parse->groupingSets != NIL)
    5874                 :             :     {
    5875                 :             :         Assert(root->group_rtindex > 0);
    5876                 :             :         non_group_vars = (List *)
    5877                 :         836 :             remove_nulling_relids((Node *) non_group_vars,
    5878                 :         836 :                                   bms_make_singleton(root->group_rtindex),
    5879                 :             :                                   NULL);
    5880                 :             :     }
    5881                 :       34142 :     add_new_columns_to_pathtarget(input_target, non_group_vars);
    5882                 :             : 
    5883                 :             :     /* clean up cruft */
    5884                 :       34142 :     list_free(non_group_vars);
    5885                 :       34142 :     list_free(non_group_cols);
    5886                 :             : 
    5887                 :             :     /* XXX this causes some redundant cost calculation ... */
    5888                 :       34142 :     return set_pathtarget_cost_width(root, input_target);
    5889                 :             : }
    5890                 :             : 
    5891                 :             : /*
    5892                 :             :  * make_partial_grouping_target
    5893                 :             :  *    Generate appropriate PathTarget for output of partial aggregate
    5894                 :             :  *    (or partial grouping, if there are no aggregates) nodes.
    5895                 :             :  *
    5896                 :             :  * A partial aggregation node needs to emit all the same aggregates that
    5897                 :             :  * a regular aggregation node would, plus any aggregates used in HAVING;
    5898                 :             :  * except that the Aggref nodes should be marked as partial aggregates.
    5899                 :             :  *
    5900                 :             :  * In addition, we'd better emit any Vars and PlaceHolderVars that are
    5901                 :             :  * used outside of Aggrefs in the aggregation tlist and HAVING.  (Presumably,
    5902                 :             :  * these would be Vars that are grouped by or used in grouping expressions.)
    5903                 :             :  *
    5904                 :             :  * grouping_target is the tlist to be emitted by the topmost aggregation step.
    5905                 :             :  * havingQual represents the HAVING clause.
    5906                 :             :  */
    5907                 :             : static PathTarget *
    5908                 :        3213 : make_partial_grouping_target(PlannerInfo *root,
    5909                 :             :                              PathTarget *grouping_target,
    5910                 :             :                              Node *havingQual)
    5911                 :             : {
    5912                 :             :     PathTarget *partial_target;
    5913                 :             :     List       *non_group_cols;
    5914                 :             :     List       *non_group_exprs;
    5915                 :             :     int         i;
    5916                 :             :     ListCell   *lc;
    5917                 :             : 
    5918                 :        3213 :     partial_target = create_empty_pathtarget();
    5919                 :        3213 :     non_group_cols = NIL;
    5920                 :             : 
    5921                 :        3213 :     i = 0;
    5922   [ +  -  +  +  :       10587 :     foreach(lc, grouping_target->exprs)
                   +  + ]
    5923                 :             :     {
    5924                 :        7374 :         Expr       *expr = (Expr *) lfirst(lc);
    5925         [ +  - ]:        7374 :         Index       sgref = get_pathtarget_sortgroupref(grouping_target, i);
    5926                 :             : 
    5927   [ +  +  +  +  :       11316 :         if (sgref && root->processed_groupClause &&
                   +  + ]
    5928                 :        3942 :             get_sortgroupref_clause_noerr(sgref,
    5929                 :             :                                           root->processed_groupClause) != NULL)
    5930                 :             :         {
    5931                 :             :             /*
    5932                 :             :              * It's a grouping column, so add it to the partial_target as-is.
    5933                 :             :              * (This allows the upper agg step to repeat the grouping calcs.)
    5934                 :             :              */
    5935                 :        2340 :             add_column_to_pathtarget(partial_target, expr, sgref);
    5936                 :             :         }
    5937                 :             :         else
    5938                 :             :         {
    5939                 :             :             /*
    5940                 :             :              * Non-grouping column, so just remember the expression for later
    5941                 :             :              * call to pull_var_clause.
    5942                 :             :              */
    5943                 :        5034 :             non_group_cols = lappend(non_group_cols, expr);
    5944                 :             :         }
    5945                 :             : 
    5946                 :        7374 :         i++;
    5947                 :             :     }
    5948                 :             : 
    5949                 :             :     /*
    5950                 :             :      * If there's a HAVING clause, we'll need the Vars/Aggrefs it uses, too.
    5951                 :             :      */
    5952         [ +  + ]:        3213 :     if (havingQual)
    5953                 :         729 :         non_group_cols = lappend(non_group_cols, havingQual);
    5954                 :             : 
    5955                 :             :     /*
    5956                 :             :      * Pull out all the Vars, PlaceHolderVars, and Aggrefs mentioned in
    5957                 :             :      * non-group cols (plus HAVING), and add them to the partial_target if not
    5958                 :             :      * already present.  (An expression used directly as a GROUP BY item will
    5959                 :             :      * be present already.)  Note this includes Vars used in resjunk items, so
    5960                 :             :      * we are covering the needs of ORDER BY and window specifications.
    5961                 :             :      */
    5962                 :        3213 :     non_group_exprs = pull_var_clause((Node *) non_group_cols,
    5963                 :             :                                       PVC_INCLUDE_AGGREGATES |
    5964                 :             :                                       PVC_RECURSE_WINDOWFUNCS |
    5965                 :             :                                       PVC_INCLUDE_PLACEHOLDERS);
    5966                 :             : 
    5967                 :        3213 :     add_new_columns_to_pathtarget(partial_target, non_group_exprs);
    5968                 :             : 
    5969                 :             :     /*
    5970                 :             :      * Adjust Aggrefs to put them in partial mode.  At this point all Aggrefs
    5971                 :             :      * are at the top level of the target list, so we can just scan the list
    5972                 :             :      * rather than recursing through the expression trees.
    5973                 :             :      */
    5974   [ +  -  +  +  :       11101 :     foreach(lc, partial_target->exprs)
                   +  + ]
    5975                 :             :     {
    5976                 :        7888 :         Aggref     *aggref = (Aggref *) lfirst(lc);
    5977                 :             : 
    5978         [ +  + ]:        7888 :         if (IsA(aggref, Aggref))
    5979                 :             :         {
    5980                 :             :             Aggref     *newaggref;
    5981                 :             : 
    5982                 :             :             /*
    5983                 :             :              * We shouldn't need to copy the substructure of the Aggref node,
    5984                 :             :              * but flat-copy the node itself to avoid damaging other trees.
    5985                 :             :              */
    5986                 :        5523 :             newaggref = makeNode(Aggref);
    5987                 :        5523 :             memcpy(newaggref, aggref, sizeof(Aggref));
    5988                 :             : 
    5989                 :             :             /* For now, assume serialization is required */
    5990                 :        5523 :             mark_partial_aggref(newaggref, AGGSPLIT_INITIAL_SERIAL);
    5991                 :             : 
    5992                 :        5523 :             lfirst(lc) = newaggref;
    5993                 :             :         }
    5994                 :             :     }
    5995                 :             : 
    5996                 :             :     /* clean up cruft */
    5997                 :        3213 :     list_free(non_group_exprs);
    5998                 :        3213 :     list_free(non_group_cols);
    5999                 :             : 
    6000                 :             :     /* XXX this causes some redundant cost calculation ... */
    6001                 :        3213 :     return set_pathtarget_cost_width(root, partial_target);
    6002                 :             : }
    6003                 :             : 
    6004                 :             : /*
    6005                 :             :  * mark_partial_aggref
    6006                 :             :  *    Adjust an Aggref to make it represent a partial-aggregation step.
    6007                 :             :  *
    6008                 :             :  * The Aggref node is modified in-place; caller must do any copying required.
    6009                 :             :  */
    6010                 :             : void
    6011                 :       15386 : mark_partial_aggref(Aggref *agg, AggSplit aggsplit)
    6012                 :             : {
    6013                 :             :     /* aggtranstype should be computed by this point */
    6014                 :             :     Assert(OidIsValid(agg->aggtranstype));
    6015                 :             :     /* ... but aggsplit should still be as the parser left it */
    6016                 :             :     Assert(agg->aggsplit == AGGSPLIT_SIMPLE);
    6017                 :             : 
    6018                 :             :     /* Mark the Aggref with the intended partial-aggregation mode */
    6019                 :       15386 :     agg->aggsplit = aggsplit;
    6020                 :             : 
    6021                 :             :     /*
    6022                 :             :      * Adjust result type if needed.  Normally, a partial aggregate returns
    6023                 :             :      * the aggregate's transition type; but if that's INTERNAL and we're
    6024                 :             :      * serializing, it returns BYTEA instead.
    6025                 :             :      */
    6026         [ +  + ]:       15386 :     if (DO_AGGSPLIT_SKIPFINAL(aggsplit))
    6027                 :             :     {
    6028   [ +  +  +  - ]:       13474 :         if (agg->aggtranstype == INTERNALOID && DO_AGGSPLIT_SERIALIZE(aggsplit))
    6029                 :         261 :             agg->aggtype = BYTEAOID;
    6030                 :             :         else
    6031                 :       13213 :             agg->aggtype = agg->aggtranstype;
    6032                 :             :     }
    6033                 :       15386 : }
    6034                 :             : 
    6035                 :             : /*
    6036                 :             :  * postprocess_setop_tlist
    6037                 :             :  *    Fix up targetlist returned by plan_set_operations().
    6038                 :             :  *
    6039                 :             :  * We need to transpose sort key info from the orig_tlist into new_tlist.
    6040                 :             :  * NOTE: this would not be good enough if we supported resjunk sort keys
    6041                 :             :  * for results of set operations --- then, we'd need to project a whole
    6042                 :             :  * new tlist to evaluate the resjunk columns.  For now, just ereport if we
    6043                 :             :  * find any resjunk columns in orig_tlist.
    6044                 :             :  */
    6045                 :             : static List *
    6046                 :        4947 : postprocess_setop_tlist(List *new_tlist, List *orig_tlist)
    6047                 :             : {
    6048                 :             :     ListCell   *l;
    6049                 :        4947 :     ListCell   *orig_tlist_item = list_head(orig_tlist);
    6050                 :             : 
    6051   [ +  +  +  +  :       18907 :     foreach(l, new_tlist)
                   +  + ]
    6052                 :             :     {
    6053                 :       13960 :         TargetEntry *new_tle = lfirst_node(TargetEntry, l);
    6054                 :             :         TargetEntry *orig_tle;
    6055                 :             : 
    6056                 :             :         /* ignore resjunk columns in setop result */
    6057         [ -  + ]:       13960 :         if (new_tle->resjunk)
    6058                 :           0 :             continue;
    6059                 :             : 
    6060                 :             :         Assert(orig_tlist_item != NULL);
    6061                 :       13960 :         orig_tle = lfirst_node(TargetEntry, orig_tlist_item);
    6062                 :       13960 :         orig_tlist_item = lnext(orig_tlist, orig_tlist_item);
    6063         [ -  + ]:       13960 :         if (orig_tle->resjunk)   /* should not happen */
    6064         [ #  # ]:           0 :             elog(ERROR, "resjunk output columns are not implemented");
    6065                 :             :         Assert(new_tle->resno == orig_tle->resno);
    6066                 :       13960 :         new_tle->ressortgroupref = orig_tle->ressortgroupref;
    6067                 :             :     }
    6068         [ -  + ]:        4947 :     if (orig_tlist_item != NULL)
    6069         [ #  # ]:           0 :         elog(ERROR, "resjunk output columns are not implemented");
    6070                 :        4947 :     return new_tlist;
    6071                 :             : }
    6072                 :             : 
    6073                 :             : /*
    6074                 :             :  * optimize_window_clauses
    6075                 :             :  *      Call each WindowFunc's prosupport function to see if we're able to
    6076                 :             :  *      make any adjustments to any of the WindowClause's so that the executor
    6077                 :             :  *      can execute the window functions in a more optimal way.
    6078                 :             :  *
    6079                 :             :  * Currently we only allow adjustments to the WindowClause's frameOptions.  We
    6080                 :             :  * may allow more things to be done here in the future.
    6081                 :             :  */
    6082                 :             : static void
    6083                 :        2326 : optimize_window_clauses(PlannerInfo *root, WindowFuncLists *wflists)
    6084                 :             : {
    6085                 :        2326 :     List       *windowClause = root->parse->windowClause;
    6086                 :             :     ListCell   *lc;
    6087                 :             : 
    6088   [ +  -  +  +  :        4867 :     foreach(lc, windowClause)
                   +  + ]
    6089                 :             :     {
    6090                 :        2541 :         WindowClause *wc = lfirst_node(WindowClause, lc);
    6091                 :             :         ListCell   *lc2;
    6092                 :        2541 :         int         optimizedFrameOptions = 0;
    6093                 :             : 
    6094                 :             :         Assert(wc->winref <= wflists->maxWinRef);
    6095                 :             : 
    6096                 :             :         /* skip any WindowClauses that have no WindowFuncs */
    6097         [ +  + ]:        2541 :         if (wflists->windowFuncs[wc->winref] == NIL)
    6098                 :          20 :             continue;
    6099                 :             : 
    6100   [ +  -  +  +  :        3083 :         foreach(lc2, wflists->windowFuncs[wc->winref])
                   +  + ]
    6101                 :             :         {
    6102                 :             :             SupportRequestOptimizeWindowClause req;
    6103                 :             :             SupportRequestOptimizeWindowClause *res;
    6104                 :        2556 :             WindowFunc *wfunc = lfirst_node(WindowFunc, lc2);
    6105                 :             :             Oid         prosupport;
    6106                 :             : 
    6107                 :        2556 :             prosupport = get_func_support(wfunc->winfnoid);
    6108                 :             : 
    6109                 :             :             /* Check if there's a support function for 'wfunc' */
    6110         [ +  + ]:        2556 :             if (!OidIsValid(prosupport))
    6111                 :        1994 :                 break;          /* can't optimize this WindowClause */
    6112                 :             : 
    6113                 :         829 :             req.type = T_SupportRequestOptimizeWindowClause;
    6114                 :         829 :             req.window_clause = wc;
    6115                 :         829 :             req.window_func = wfunc;
    6116                 :         829 :             req.frameOptions = wc->frameOptions;
    6117                 :             : 
    6118                 :             :             /* call the support function */
    6119                 :             :             res = (SupportRequestOptimizeWindowClause *)
    6120                 :         829 :                 DatumGetPointer(OidFunctionCall1(prosupport,
    6121                 :             :                                                  PointerGetDatum(&req)));
    6122                 :             : 
    6123                 :             :             /*
    6124                 :             :              * Skip to next WindowClause if the support function does not
    6125                 :             :              * support this request type.
    6126                 :             :              */
    6127         [ +  + ]:         829 :             if (res == NULL)
    6128                 :         267 :                 break;
    6129                 :             : 
    6130                 :             :             /*
    6131                 :             :              * Save these frameOptions for the first WindowFunc for this
    6132                 :             :              * WindowClause.
    6133                 :             :              */
    6134         [ +  + ]:         562 :             if (foreach_current_index(lc2) == 0)
    6135                 :         542 :                 optimizedFrameOptions = res->frameOptions;
    6136                 :             : 
    6137                 :             :             /*
    6138                 :             :              * On subsequent WindowFuncs, if the frameOptions are not the same
    6139                 :             :              * then we're unable to optimize the frameOptions for this
    6140                 :             :              * WindowClause.
    6141                 :             :              */
    6142         [ -  + ]:          20 :             else if (optimizedFrameOptions != res->frameOptions)
    6143                 :           0 :                 break;          /* skip to the next WindowClause, if any */
    6144                 :             :         }
    6145                 :             : 
    6146                 :             :         /* adjust the frameOptions if all WindowFunc's agree that it's ok */
    6147   [ +  +  +  - ]:        2521 :         if (lc2 == NULL && wc->frameOptions != optimizedFrameOptions)
    6148                 :             :         {
    6149                 :             :             ListCell   *lc3;
    6150                 :             : 
    6151                 :             :             /* apply the new frame options */
    6152                 :         527 :             wc->frameOptions = optimizedFrameOptions;
    6153                 :             : 
    6154                 :             :             /*
    6155                 :             :              * We now check to see if changing the frameOptions has caused
    6156                 :             :              * this WindowClause to be a duplicate of some other WindowClause.
    6157                 :             :              * This can only happen if we have multiple WindowClauses, so
    6158                 :             :              * don't bother if there's only 1.
    6159                 :             :              */
    6160         [ +  + ]:         527 :             if (list_length(windowClause) == 1)
    6161                 :         442 :                 continue;
    6162                 :             : 
    6163                 :             :             /*
    6164                 :             :              * Do the duplicate check and reuse the existing WindowClause if
    6165                 :             :              * we find a duplicate.
    6166                 :             :              */
    6167   [ +  -  +  +  :         220 :             foreach(lc3, windowClause)
                   +  + ]
    6168                 :             :             {
    6169                 :         165 :                 WindowClause *existing_wc = lfirst_node(WindowClause, lc3);
    6170                 :             : 
    6171                 :             :                 /* skip over the WindowClause we're currently editing */
    6172         [ +  + ]:         165 :                 if (existing_wc == wc)
    6173                 :          55 :                     continue;
    6174                 :             : 
    6175                 :             :                 /*
    6176                 :             :                  * Perform the same duplicate check that is done in
    6177                 :             :                  * transformWindowFuncCall.
    6178                 :             :                  */
    6179   [ +  -  +  + ]:         220 :                 if (equal(wc->partitionClause, existing_wc->partitionClause) &&
    6180                 :         110 :                     equal(wc->orderClause, existing_wc->orderClause) &&
    6181   [ +  +  +  - ]:         100 :                     wc->frameOptions == existing_wc->frameOptions &&
    6182         [ +  - ]:          60 :                     equal(wc->startOffset, existing_wc->startOffset) &&
    6183                 :          30 :                     equal(wc->endOffset, existing_wc->endOffset))
    6184                 :             :                 {
    6185                 :             :                     ListCell   *lc4;
    6186                 :             : 
    6187                 :             :                     /*
    6188                 :             :                      * Now move each WindowFunc in 'wc' into 'existing_wc'.
    6189                 :             :                      * This required adjusting each WindowFunc's winref and
    6190                 :             :                      * moving the WindowFuncs in 'wc' to the list of
    6191                 :             :                      * WindowFuncs in 'existing_wc'.
    6192                 :             :                      */
    6193   [ +  -  +  +  :          65 :                     foreach(lc4, wflists->windowFuncs[wc->winref])
                   +  + ]
    6194                 :             :                     {
    6195                 :          35 :                         WindowFunc *wfunc = lfirst_node(WindowFunc, lc4);
    6196                 :             : 
    6197                 :          35 :                         wfunc->winref = existing_wc->winref;
    6198                 :             :                     }
    6199                 :             : 
    6200                 :             :                     /* move list items */
    6201                 :          60 :                     wflists->windowFuncs[existing_wc->winref] = list_concat(wflists->windowFuncs[existing_wc->winref],
    6202                 :          30 :                                                                             wflists->windowFuncs[wc->winref]);
    6203                 :          30 :                     wflists->windowFuncs[wc->winref] = NIL;
    6204                 :             : 
    6205                 :             :                     /*
    6206                 :             :                      * transformWindowFuncCall() should have made sure there
    6207                 :             :                      * are no other duplicates, so we needn't bother looking
    6208                 :             :                      * any further.
    6209                 :             :                      */
    6210                 :          30 :                     break;
    6211                 :             :                 }
    6212                 :             :             }
    6213                 :             :         }
    6214                 :             :     }
    6215                 :        2326 : }
    6216                 :             : 
    6217                 :             : /*
    6218                 :             :  * select_active_windows
    6219                 :             :  *      Create a list of the "active" window clauses (ie, those referenced
    6220                 :             :  *      by non-deleted WindowFuncs) in the order they are to be executed.
    6221                 :             :  */
    6222                 :             : static List *
    6223                 :        2326 : select_active_windows(PlannerInfo *root, WindowFuncLists *wflists)
    6224                 :             : {
    6225                 :        2326 :     List       *windowClause = root->parse->windowClause;
    6226                 :        2326 :     List       *result = NIL;
    6227                 :             :     ListCell   *lc;
    6228                 :        2326 :     int         nActive = 0;
    6229                 :        2326 :     WindowClauseSortData *actives = palloc_array(WindowClauseSortData,
    6230                 :             :                                                  list_length(windowClause));
    6231                 :             : 
    6232                 :             :     /* First, construct an array of the active windows */
    6233   [ +  -  +  +  :        4867 :     foreach(lc, windowClause)
                   +  + ]
    6234                 :             :     {
    6235                 :        2541 :         WindowClause *wc = lfirst_node(WindowClause, lc);
    6236                 :             : 
    6237                 :             :         /* It's only active if wflists shows some related WindowFuncs */
    6238                 :             :         Assert(wc->winref <= wflists->maxWinRef);
    6239         [ +  + ]:        2541 :         if (wflists->windowFuncs[wc->winref] == NIL)
    6240                 :          50 :             continue;
    6241                 :             : 
    6242                 :        2491 :         actives[nActive].wc = wc;   /* original clause */
    6243                 :             : 
    6244                 :             :         /*
    6245                 :             :          * For sorting, we want the list of partition keys followed by the
    6246                 :             :          * list of sort keys. But pathkeys construction will remove duplicates
    6247                 :             :          * between the two, so we can as well (even though we can't detect all
    6248                 :             :          * of the duplicates, since some may come from ECs - that might mean
    6249                 :             :          * we miss optimization chances here). We must, however, ensure that
    6250                 :             :          * the order of entries is preserved with respect to the ones we do
    6251                 :             :          * keep.
    6252                 :             :          *
    6253                 :             :          * partitionClause and orderClause had their own duplicates removed in
    6254                 :             :          * parse analysis, so we're only concerned here with removing
    6255                 :             :          * orderClause entries that also appear in partitionClause.
    6256                 :             :          */
    6257                 :        4982 :         actives[nActive].uniqueOrder =
    6258                 :        2491 :             list_concat_unique(list_copy(wc->partitionClause),
    6259                 :        2491 :                                wc->orderClause);
    6260                 :        2491 :         nActive++;
    6261                 :             :     }
    6262                 :             : 
    6263                 :             :     /*
    6264                 :             :      * Sort active windows by their partitioning/ordering clauses, ignoring
    6265                 :             :      * any framing clauses, so that the windows that need the same sorting are
    6266                 :             :      * adjacent in the list. When we come to generate paths, this will avoid
    6267                 :             :      * inserting additional Sort nodes.
    6268                 :             :      *
    6269                 :             :      * This is how we implement a specific requirement from the SQL standard,
    6270                 :             :      * which says that when two or more windows are order-equivalent (i.e.
    6271                 :             :      * have matching partition and order clauses, even if their names or
    6272                 :             :      * framing clauses differ), then all peer rows must be presented in the
    6273                 :             :      * same order in all of them. If we allowed multiple sort nodes for such
    6274                 :             :      * cases, we'd risk having the peer rows end up in different orders in
    6275                 :             :      * equivalent windows due to sort instability. (See General Rule 4 of
    6276                 :             :      * <window clause> in SQL2008 - SQL2016.)
    6277                 :             :      *
    6278                 :             :      * Additionally, if the entire list of clauses of one window is a prefix
    6279                 :             :      * of another, put first the window with stronger sorting requirements.
    6280                 :             :      * This way we will first sort for stronger window, and won't have to sort
    6281                 :             :      * again for the weaker one.
    6282                 :             :      */
    6283                 :        2326 :     qsort(actives, nActive, sizeof(WindowClauseSortData), common_prefix_cmp);
    6284                 :             : 
    6285                 :             :     /* build ordered list of the original WindowClause nodes */
    6286         [ +  + ]:        4817 :     for (int i = 0; i < nActive; i++)
    6287                 :        2491 :         result = lappend(result, actives[i].wc);
    6288                 :             : 
    6289                 :        2326 :     pfree(actives);
    6290                 :             : 
    6291                 :        2326 :     return result;
    6292                 :             : }
    6293                 :             : 
    6294                 :             : /*
    6295                 :             :  * name_active_windows
    6296                 :             :  *    Ensure all active windows have unique names.
    6297                 :             :  *
    6298                 :             :  * The parser will have checked that user-assigned window names are unique
    6299                 :             :  * within the Query.  Here we assign made-up names to any unnamed
    6300                 :             :  * WindowClauses for the benefit of EXPLAIN.  (We don't want to do this
    6301                 :             :  * at parse time, because it'd mess up decompilation of views.)
    6302                 :             :  *
    6303                 :             :  * activeWindows: result of select_active_windows
    6304                 :             :  */
    6305                 :             : static void
    6306                 :        2326 : name_active_windows(List *activeWindows)
    6307                 :             : {
    6308                 :        2326 :     int         next_n = 1;
    6309                 :             :     char        newname[16];
    6310                 :             :     ListCell   *lc;
    6311                 :             : 
    6312   [ +  -  +  +  :        4817 :     foreach(lc, activeWindows)
                   +  + ]
    6313                 :             :     {
    6314                 :        2491 :         WindowClause *wc = lfirst_node(WindowClause, lc);
    6315                 :             : 
    6316                 :             :         /* Nothing to do if it has a name already. */
    6317         [ +  + ]:        2491 :         if (wc->name)
    6318                 :         480 :             continue;
    6319                 :             : 
    6320                 :             :         /* Select a name not currently present in the list. */
    6321                 :             :         for (;;)
    6322                 :           5 :         {
    6323                 :             :             ListCell   *lc2;
    6324                 :             : 
    6325                 :        2016 :             snprintf(newname, sizeof(newname), "w%d", next_n++);
    6326   [ +  -  +  +  :        4342 :             foreach(lc2, activeWindows)
                   +  + ]
    6327                 :             :             {
    6328                 :        2331 :                 WindowClause *wc2 = lfirst_node(WindowClause, lc2);
    6329                 :             : 
    6330   [ +  +  +  + ]:        2331 :                 if (wc2->name && strcmp(wc2->name, newname) == 0)
    6331                 :           5 :                     break;      /* matched */
    6332                 :             :             }
    6333         [ +  + ]:        2016 :             if (lc2 == NULL)
    6334                 :        2011 :                 break;          /* reached the end with no match */
    6335                 :             :         }
    6336                 :        2011 :         wc->name = pstrdup(newname);
    6337                 :             :     }
    6338                 :        2326 : }
    6339                 :             : 
    6340                 :             : /*
    6341                 :             :  * common_prefix_cmp
    6342                 :             :  *    QSort comparison function for WindowClauseSortData
    6343                 :             :  *
    6344                 :             :  * Sort the windows by the required sorting clauses. First, compare the sort
    6345                 :             :  * clauses themselves. Second, if one window's clauses are a prefix of another
    6346                 :             :  * one's clauses, put the window with more sort clauses first.
    6347                 :             :  *
    6348                 :             :  * We purposefully sort by the highest tleSortGroupRef first.  Since
    6349                 :             :  * tleSortGroupRefs are assigned for the query's DISTINCT and ORDER BY first
    6350                 :             :  * and because here we sort the lowest tleSortGroupRefs last, if a
    6351                 :             :  * WindowClause is sharing a tleSortGroupRef with the query's DISTINCT or
    6352                 :             :  * ORDER BY clause, this makes it more likely that the final WindowAgg will
    6353                 :             :  * provide presorted input for the query's DISTINCT or ORDER BY clause, thus
    6354                 :             :  * reducing the total number of sorts required for the query.
    6355                 :             :  */
    6356                 :             : static int
    6357                 :         180 : common_prefix_cmp(const void *a, const void *b)
    6358                 :             : {
    6359                 :         180 :     const WindowClauseSortData *wcsa = a;
    6360                 :         180 :     const WindowClauseSortData *wcsb = b;
    6361                 :             :     ListCell   *item_a;
    6362                 :             :     ListCell   *item_b;
    6363                 :             : 
    6364   [ +  +  +  +  :         315 :     forboth(item_a, wcsa->uniqueOrder, item_b, wcsb->uniqueOrder)
          +  +  +  +  +  
             +  +  +  +  
                      + ]
    6365                 :             :     {
    6366                 :         230 :         SortGroupClause *sca = lfirst_node(SortGroupClause, item_a);
    6367                 :         230 :         SortGroupClause *scb = lfirst_node(SortGroupClause, item_b);
    6368                 :             : 
    6369         [ +  + ]:         230 :         if (sca->tleSortGroupRef > scb->tleSortGroupRef)
    6370                 :          95 :             return -1;
    6371         [ +  + ]:         220 :         else if (sca->tleSortGroupRef < scb->tleSortGroupRef)
    6372                 :          55 :             return 1;
    6373         [ +  + ]:         165 :         else if (sca->sortop > scb->sortop)
    6374                 :          10 :             return -1;
    6375         [ +  + ]:         155 :         else if (sca->sortop < scb->sortop)
    6376                 :          20 :             return 1;
    6377   [ -  +  -  - ]:         135 :         else if (sca->nulls_first && !scb->nulls_first)
    6378                 :           0 :             return -1;
    6379   [ +  -  -  + ]:         135 :         else if (!sca->nulls_first && scb->nulls_first)
    6380                 :           0 :             return 1;
    6381                 :             :         /* no need to compare eqop, since it is fully determined by sortop */
    6382                 :             :     }
    6383                 :             : 
    6384         [ +  + ]:          85 :     if (list_length(wcsa->uniqueOrder) > list_length(wcsb->uniqueOrder))
    6385                 :           5 :         return -1;
    6386         [ +  + ]:          80 :     else if (list_length(wcsa->uniqueOrder) < list_length(wcsb->uniqueOrder))
    6387                 :          25 :         return 1;
    6388                 :             : 
    6389                 :          55 :     return 0;
    6390                 :             : }
    6391                 :             : 
    6392                 :             : /*
    6393                 :             :  * make_window_input_target
    6394                 :             :  *    Generate appropriate PathTarget for initial input to WindowAgg nodes.
    6395                 :             :  *
    6396                 :             :  * When the query has window functions, this function computes the desired
    6397                 :             :  * target to be computed by the node just below the first WindowAgg.
    6398                 :             :  * This tlist must contain all values needed to evaluate the window functions,
    6399                 :             :  * compute the final target list, and perform any required final sort step.
    6400                 :             :  * If multiple WindowAggs are needed, each intermediate one adds its window
    6401                 :             :  * function results onto this base tlist; only the topmost WindowAgg computes
    6402                 :             :  * the actual desired target list.
    6403                 :             :  *
    6404                 :             :  * This function is much like make_group_input_target, though not quite enough
    6405                 :             :  * like it to share code.  As in that function, we flatten most expressions
    6406                 :             :  * into their component variables.  But we do not want to flatten window
    6407                 :             :  * PARTITION BY/ORDER BY clauses, since that might result in multiple
    6408                 :             :  * evaluations of them, which would be bad (possibly even resulting in
    6409                 :             :  * inconsistent answers, if they contain volatile functions).
    6410                 :             :  * Also, we must not flatten GROUP BY clauses that were left unflattened by
    6411                 :             :  * make_group_input_target, because we may no longer have access to the
    6412                 :             :  * individual Vars in them.
    6413                 :             :  *
    6414                 :             :  * Another key difference from make_group_input_target is that we don't
    6415                 :             :  * flatten Aggref expressions, since those are to be computed below the
    6416                 :             :  * window functions and just referenced like Vars above that.
    6417                 :             :  *
    6418                 :             :  * 'final_target' is the query's final target list (in PathTarget form)
    6419                 :             :  * 'activeWindows' is the list of active windows previously identified by
    6420                 :             :  *          select_active_windows.
    6421                 :             :  *
    6422                 :             :  * The result is the PathTarget to be computed by the plan node immediately
    6423                 :             :  * below the first WindowAgg node.
    6424                 :             :  */
    6425                 :             : static PathTarget *
    6426                 :        2326 : make_window_input_target(PlannerInfo *root,
    6427                 :             :                          PathTarget *final_target,
    6428                 :             :                          List *activeWindows)
    6429                 :             : {
    6430                 :             :     PathTarget *input_target;
    6431                 :             :     Bitmapset  *sgrefs;
    6432                 :             :     List       *flattenable_cols;
    6433                 :             :     List       *flattenable_vars;
    6434                 :             :     int         i;
    6435                 :             :     ListCell   *lc;
    6436                 :             : 
    6437                 :             :     Assert(root->parse->hasWindowFuncs);
    6438                 :             : 
    6439                 :             :     /*
    6440                 :             :      * Collect the sortgroupref numbers of window PARTITION/ORDER BY clauses
    6441                 :             :      * into a bitmapset for convenient reference below.
    6442                 :             :      */
    6443                 :        2326 :     sgrefs = NULL;
    6444   [ +  -  +  +  :        4817 :     foreach(lc, activeWindows)
                   +  + ]
    6445                 :             :     {
    6446                 :        2491 :         WindowClause *wc = lfirst_node(WindowClause, lc);
    6447                 :             :         ListCell   *lc2;
    6448                 :             : 
    6449   [ +  +  +  +  :        3128 :         foreach(lc2, wc->partitionClause)
                   +  + ]
    6450                 :             :         {
    6451                 :         637 :             SortGroupClause *sortcl = lfirst_node(SortGroupClause, lc2);
    6452                 :             : 
    6453                 :         637 :             sgrefs = bms_add_member(sgrefs, sortcl->tleSortGroupRef);
    6454                 :             :         }
    6455   [ +  +  +  +  :        4480 :         foreach(lc2, wc->orderClause)
                   +  + ]
    6456                 :             :         {
    6457                 :        1989 :             SortGroupClause *sortcl = lfirst_node(SortGroupClause, lc2);
    6458                 :             : 
    6459                 :        1989 :             sgrefs = bms_add_member(sgrefs, sortcl->tleSortGroupRef);
    6460                 :             :         }
    6461                 :             :     }
    6462                 :             : 
    6463                 :             :     /* Add in sortgroupref numbers of GROUP BY clauses, too */
    6464   [ +  +  +  +  :        2482 :     foreach(lc, root->processed_groupClause)
                   +  + ]
    6465                 :             :     {
    6466                 :         156 :         SortGroupClause *grpcl = lfirst_node(SortGroupClause, lc);
    6467                 :             : 
    6468                 :         156 :         sgrefs = bms_add_member(sgrefs, grpcl->tleSortGroupRef);
    6469                 :             :     }
    6470                 :             : 
    6471                 :             :     /*
    6472                 :             :      * Construct a target containing all the non-flattenable targetlist items,
    6473                 :             :      * and save aside the others for a moment.
    6474                 :             :      */
    6475                 :        2326 :     input_target = create_empty_pathtarget();
    6476                 :        2326 :     flattenable_cols = NIL;
    6477                 :             : 
    6478                 :        2326 :     i = 0;
    6479   [ +  -  +  +  :        9787 :     foreach(lc, final_target->exprs)
                   +  + ]
    6480                 :             :     {
    6481                 :        7461 :         Expr       *expr = (Expr *) lfirst(lc);
    6482         [ +  - ]:        7461 :         Index       sgref = get_pathtarget_sortgroupref(final_target, i);
    6483                 :             : 
    6484                 :             :         /*
    6485                 :             :          * Don't want to deconstruct window clauses or GROUP BY items.  (Note
    6486                 :             :          * that such items can't contain window functions, so it's okay to
    6487                 :             :          * compute them below the WindowAgg nodes.)
    6488                 :             :          */
    6489   [ +  +  +  + ]:        7461 :         if (sgref != 0 && bms_is_member(sgref, sgrefs))
    6490                 :             :         {
    6491                 :             :             /*
    6492                 :             :              * Don't want to deconstruct this value, so add it to the input
    6493                 :             :              * target as-is.
    6494                 :             :              */
    6495                 :        2483 :             add_column_to_pathtarget(input_target, expr, sgref);
    6496                 :             :         }
    6497                 :             :         else
    6498                 :             :         {
    6499                 :             :             /*
    6500                 :             :              * Column is to be flattened, so just remember the expression for
    6501                 :             :              * later call to pull_var_clause.
    6502                 :             :              */
    6503                 :        4978 :             flattenable_cols = lappend(flattenable_cols, expr);
    6504                 :             :         }
    6505                 :             : 
    6506                 :        7461 :         i++;
    6507                 :             :     }
    6508                 :             : 
    6509                 :             :     /*
    6510                 :             :      * Pull out all the Vars and Aggrefs mentioned in flattenable columns, and
    6511                 :             :      * add them to the input target if not already present.  (Some might be
    6512                 :             :      * there already because they're used directly as window/group clauses.)
    6513                 :             :      *
    6514                 :             :      * Note: it's essential to use PVC_INCLUDE_AGGREGATES here, so that any
    6515                 :             :      * Aggrefs are placed in the Agg node's tlist and not left to be computed
    6516                 :             :      * at higher levels.  On the other hand, we should recurse into
    6517                 :             :      * WindowFuncs to make sure their input expressions are available.
    6518                 :             :      */
    6519                 :        2326 :     flattenable_vars = pull_var_clause((Node *) flattenable_cols,
    6520                 :             :                                        PVC_INCLUDE_AGGREGATES |
    6521                 :             :                                        PVC_RECURSE_WINDOWFUNCS |
    6522                 :             :                                        PVC_INCLUDE_PLACEHOLDERS);
    6523                 :        2326 :     add_new_columns_to_pathtarget(input_target, flattenable_vars);
    6524                 :             : 
    6525                 :             :     /* clean up cruft */
    6526                 :        2326 :     list_free(flattenable_vars);
    6527                 :        2326 :     list_free(flattenable_cols);
    6528                 :             : 
    6529                 :             :     /* XXX this causes some redundant cost calculation ... */
    6530                 :        2326 :     return set_pathtarget_cost_width(root, input_target);
    6531                 :             : }
    6532                 :             : 
    6533                 :             : /*
    6534                 :             :  * make_pathkeys_for_window
    6535                 :             :  *      Create a pathkeys list describing the required input ordering
    6536                 :             :  *      for the given WindowClause.
    6537                 :             :  *
    6538                 :             :  * Modifies wc's partitionClause to remove any clauses which are deemed
    6539                 :             :  * redundant by the pathkey logic.
    6540                 :             :  *
    6541                 :             :  * The required ordering is first the PARTITION keys, then the ORDER keys.
    6542                 :             :  * In the future we might try to implement windowing using hashing, in which
    6543                 :             :  * case the ordering could be relaxed, but for now we always sort.
    6544                 :             :  */
    6545                 :             : static List *
    6546                 :        4973 : make_pathkeys_for_window(PlannerInfo *root, WindowClause *wc,
    6547                 :             :                          List *tlist)
    6548                 :             : {
    6549                 :        4973 :     List       *window_pathkeys = NIL;
    6550                 :             : 
    6551                 :             :     /* Throw error if can't sort */
    6552         [ -  + ]:        4973 :     if (!grouping_is_sortable(wc->partitionClause))
    6553         [ #  # ]:           0 :         ereport(ERROR,
    6554                 :             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    6555                 :             :                  errmsg("could not implement window PARTITION BY"),
    6556                 :             :                  errdetail("Window partitioning columns must be of sortable datatypes.")));
    6557         [ -  + ]:        4973 :     if (!grouping_is_sortable(wc->orderClause))
    6558         [ #  # ]:           0 :         ereport(ERROR,
    6559                 :             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    6560                 :             :                  errmsg("could not implement window ORDER BY"),
    6561                 :             :                  errdetail("Window ordering columns must be of sortable datatypes.")));
    6562                 :             : 
    6563                 :             :     /*
    6564                 :             :      * First fetch the pathkeys for the PARTITION BY clause.  We can safely
    6565                 :             :      * remove any clauses from the wc->partitionClause for redundant pathkeys.
    6566                 :             :      */
    6567         [ +  + ]:        4973 :     if (wc->partitionClause != NIL)
    6568                 :             :     {
    6569                 :             :         bool        sortable;
    6570                 :             : 
    6571                 :        1115 :         window_pathkeys = make_pathkeys_for_sortclauses_extended(root,
    6572                 :             :                                                                  &wc->partitionClause,
    6573                 :             :                                                                  tlist,
    6574                 :             :                                                                  true,
    6575                 :             :                                                                  false,
    6576                 :             :                                                                  &sortable,
    6577                 :             :                                                                  false);
    6578                 :             : 
    6579                 :             :         Assert(sortable);
    6580                 :             :     }
    6581                 :             : 
    6582                 :             :     /*
    6583                 :             :      * In principle, we could also consider removing redundant ORDER BY items
    6584                 :             :      * too as doing so does not alter the result of peer row checks done by
    6585                 :             :      * the executor.  However, we must *not* remove the ordering column for
    6586                 :             :      * RANGE OFFSET cases, as the executor needs that for in_range tests even
    6587                 :             :      * if it's known to be equal to some partitioning column.
    6588                 :             :      */
    6589         [ +  + ]:        4973 :     if (wc->orderClause != NIL)
    6590                 :             :     {
    6591                 :             :         List       *orderby_pathkeys;
    6592                 :             : 
    6593                 :        3876 :         orderby_pathkeys = make_pathkeys_for_sortclauses(root,
    6594                 :             :                                                          wc->orderClause,
    6595                 :             :                                                          tlist);
    6596                 :             : 
    6597                 :             :         /* Okay, make the combined pathkeys */
    6598         [ +  + ]:        3876 :         if (window_pathkeys != NIL)
    6599                 :         763 :             window_pathkeys = append_pathkeys(window_pathkeys, orderby_pathkeys);
    6600                 :             :         else
    6601                 :        3113 :             window_pathkeys = orderby_pathkeys;
    6602                 :             :     }
    6603                 :             : 
    6604                 :        4973 :     return window_pathkeys;
    6605                 :             : }
    6606                 :             : 
    6607                 :             : /*
    6608                 :             :  * make_sort_input_target
    6609                 :             :  *    Generate appropriate PathTarget for initial input to Sort step.
    6610                 :             :  *
    6611                 :             :  * If the query has ORDER BY, this function chooses the target to be computed
    6612                 :             :  * by the node just below the Sort (and DISTINCT, if any, since Unique can't
    6613                 :             :  * project) steps.  This might or might not be identical to the query's final
    6614                 :             :  * output target.
    6615                 :             :  *
    6616                 :             :  * The main argument for keeping the sort-input tlist the same as the final
    6617                 :             :  * is that we avoid a separate projection node (which will be needed if
    6618                 :             :  * they're different, because Sort can't project).  However, there are also
    6619                 :             :  * advantages to postponing tlist evaluation till after the Sort: it ensures
    6620                 :             :  * a consistent order of evaluation for any volatile functions in the tlist,
    6621                 :             :  * and if there's also a LIMIT, we can stop the query without ever computing
    6622                 :             :  * tlist functions for later rows, which is beneficial for both volatile and
    6623                 :             :  * expensive functions.
    6624                 :             :  *
    6625                 :             :  * Our current policy is to postpone volatile expressions till after the sort
    6626                 :             :  * unconditionally (assuming that that's possible, ie they are in plain tlist
    6627                 :             :  * columns and not ORDER BY/GROUP BY/DISTINCT columns).  We also prefer to
    6628                 :             :  * postpone set-returning expressions, because running them beforehand would
    6629                 :             :  * bloat the sort dataset, and because it might cause unexpected output order
    6630                 :             :  * if the sort isn't stable.  However there's a constraint on that: all SRFs
    6631                 :             :  * in the tlist should be evaluated at the same plan step, so that they can
    6632                 :             :  * run in sync in nodeProjectSet.  So if any SRFs are in sort columns, we
    6633                 :             :  * mustn't postpone any SRFs.  (Note that in principle that policy should
    6634                 :             :  * probably get applied to the group/window input targetlists too, but we
    6635                 :             :  * have not done that historically.)  Lastly, expensive expressions are
    6636                 :             :  * postponed if there is a LIMIT, or if root->tuple_fraction shows that
    6637                 :             :  * partial evaluation of the query is possible (if neither is true, we expect
    6638                 :             :  * to have to evaluate the expressions for every row anyway), or if there are
    6639                 :             :  * any volatile or set-returning expressions (since once we've put in a
    6640                 :             :  * projection at all, it won't cost any more to postpone more stuff).
    6641                 :             :  *
    6642                 :             :  * Another issue that could potentially be considered here is that
    6643                 :             :  * evaluating tlist expressions could result in data that's either wider
    6644                 :             :  * or narrower than the input Vars, thus changing the volume of data that
    6645                 :             :  * has to go through the Sort.  However, we usually have only a very bad
    6646                 :             :  * idea of the output width of any expression more complex than a Var,
    6647                 :             :  * so for now it seems too risky to try to optimize on that basis.
    6648                 :             :  *
    6649                 :             :  * Note that if we do produce a modified sort-input target, and then the
    6650                 :             :  * query ends up not using an explicit Sort, no particular harm is done:
    6651                 :             :  * we'll initially use the modified target for the preceding path nodes,
    6652                 :             :  * but then change them to the final target with apply_projection_to_path.
    6653                 :             :  * Moreover, in such a case the guarantees about evaluation order of
    6654                 :             :  * volatile functions still hold, since the rows are sorted already.
    6655                 :             :  *
    6656                 :             :  * This function has some things in common with make_group_input_target and
    6657                 :             :  * make_window_input_target, though the detailed rules for what to do are
    6658                 :             :  * different.  We never flatten/postpone any grouping or ordering columns;
    6659                 :             :  * those are needed before the sort.  If we do flatten a particular
    6660                 :             :  * expression, we leave Aggref and WindowFunc nodes alone, since those were
    6661                 :             :  * computed earlier.
    6662                 :             :  *
    6663                 :             :  * 'final_target' is the query's final target list (in PathTarget form)
    6664                 :             :  * 'have_postponed_srfs' is an output argument, see below
    6665                 :             :  *
    6666                 :             :  * The result is the PathTarget to be computed by the plan node immediately
    6667                 :             :  * below the Sort step (and the Distinct step, if any).  This will be
    6668                 :             :  * exactly final_target if we decide a projection step wouldn't be helpful.
    6669                 :             :  *
    6670                 :             :  * In addition, *have_postponed_srfs is set to true if we choose to postpone
    6671                 :             :  * any set-returning functions to after the Sort.
    6672                 :             :  */
    6673                 :             : static PathTarget *
    6674                 :       58046 : make_sort_input_target(PlannerInfo *root,
    6675                 :             :                        PathTarget *final_target,
    6676                 :             :                        bool *have_postponed_srfs)
    6677                 :             : {
    6678                 :       58046 :     Query      *parse = root->parse;
    6679                 :             :     PathTarget *input_target;
    6680                 :             :     int         ncols;
    6681                 :             :     bool       *col_is_srf;
    6682                 :             :     bool       *postpone_col;
    6683                 :             :     bool        have_srf;
    6684                 :             :     bool        have_volatile;
    6685                 :             :     bool        have_expensive;
    6686                 :             :     bool        have_srf_sortcols;
    6687                 :             :     bool        postpone_srfs;
    6688                 :             :     List       *postponable_cols;
    6689                 :             :     List       *postponable_vars;
    6690                 :             :     int         i;
    6691                 :             :     ListCell   *lc;
    6692                 :             : 
    6693                 :             :     /* Shouldn't get here unless query has ORDER BY */
    6694                 :             :     Assert(parse->sortClause);
    6695                 :             : 
    6696                 :       58046 :     *have_postponed_srfs = false;   /* default result */
    6697                 :             : 
    6698                 :             :     /* Inspect tlist and collect per-column information */
    6699                 :       58046 :     ncols = list_length(final_target->exprs);
    6700                 :       58046 :     col_is_srf = (bool *) palloc0(ncols * sizeof(bool));
    6701                 :       58046 :     postpone_col = (bool *) palloc0(ncols * sizeof(bool));
    6702                 :       58046 :     have_srf = have_volatile = have_expensive = have_srf_sortcols = false;
    6703                 :             : 
    6704                 :       58046 :     i = 0;
    6705   [ +  -  +  +  :      331099 :     foreach(lc, final_target->exprs)
                   +  + ]
    6706                 :             :     {
    6707                 :      273053 :         Expr       *expr = (Expr *) lfirst(lc);
    6708                 :             : 
    6709                 :             :         /*
    6710                 :             :          * If the column has a sortgroupref, assume it has to be evaluated
    6711                 :             :          * before sorting.  Generally such columns would be ORDER BY, GROUP
    6712                 :             :          * BY, etc targets.  One exception is columns that were removed from
    6713                 :             :          * GROUP BY by remove_useless_groupby_columns() ... but those would
    6714                 :             :          * only be Vars anyway.  There don't seem to be any cases where it
    6715                 :             :          * would be worth the trouble to double-check.
    6716                 :             :          */
    6717   [ +  -  +  + ]:      273053 :         if (get_pathtarget_sortgroupref(final_target, i) == 0)
    6718                 :             :         {
    6719                 :             :             /*
    6720                 :             :              * Check for SRF or volatile functions.  Check the SRF case first
    6721                 :             :              * because we must know whether we have any postponed SRFs.
    6722                 :             :              */
    6723   [ +  +  +  + ]:      191346 :             if (parse->hasTargetSRFs &&
    6724                 :         180 :                 expression_returns_set((Node *) expr))
    6725                 :             :             {
    6726                 :             :                 /* We'll decide below whether these are postponable */
    6727                 :          80 :                 col_is_srf[i] = true;
    6728                 :          80 :                 have_srf = true;
    6729                 :             :             }
    6730         [ +  + ]:      191086 :             else if (contain_volatile_functions((Node *) expr))
    6731                 :             :             {
    6732                 :             :                 /* Unconditionally postpone */
    6733                 :         195 :                 postpone_col[i] = true;
    6734                 :         195 :                 have_volatile = true;
    6735                 :             :             }
    6736                 :             :             else
    6737                 :             :             {
    6738                 :             :                 /*
    6739                 :             :                  * Else check the cost.  XXX it's annoying to have to do this
    6740                 :             :                  * when set_pathtarget_cost_width() just did it.  Refactor to
    6741                 :             :                  * allow sharing the work?
    6742                 :             :                  */
    6743                 :             :                 QualCost    cost;
    6744                 :             : 
    6745                 :      190891 :                 cost_qual_eval_node(&cost, (Node *) expr, root);
    6746                 :             : 
    6747                 :             :                 /*
    6748                 :             :                  * We arbitrarily define "expensive" as "more than 10X
    6749                 :             :                  * cpu_operator_cost".  Note this will take in any PL function
    6750                 :             :                  * with default cost.
    6751                 :             :                  */
    6752         [ +  + ]:      190891 :                 if (cost.per_tuple > 10 * cpu_operator_cost)
    6753                 :             :                 {
    6754                 :       14000 :                     postpone_col[i] = true;
    6755                 :       14000 :                     have_expensive = true;
    6756                 :             :                 }
    6757                 :             :             }
    6758                 :             :         }
    6759                 :             :         else
    6760                 :             :         {
    6761                 :             :             /* For sortgroupref cols, just check if any contain SRFs */
    6762         [ +  + ]:       81887 :             if (!have_srf_sortcols &&
    6763   [ +  +  +  + ]:       82144 :                 parse->hasTargetSRFs &&
    6764                 :         277 :                 expression_returns_set((Node *) expr))
    6765                 :         122 :                 have_srf_sortcols = true;
    6766                 :             :         }
    6767                 :             : 
    6768                 :      273053 :         i++;
    6769                 :             :     }
    6770                 :             : 
    6771                 :             :     /*
    6772                 :             :      * We can postpone SRFs if we have some but none are in sortgroupref cols.
    6773                 :             :      */
    6774   [ +  +  +  + ]:       58046 :     postpone_srfs = (have_srf && !have_srf_sortcols);
    6775                 :             : 
    6776                 :             :     /*
    6777                 :             :      * If we don't need a post-sort projection, just return final_target.
    6778                 :             :      */
    6779   [ +  +  +  + ]:       58046 :     if (!(postpone_srfs || have_volatile ||
    6780         [ +  + ]:       57803 :           (have_expensive &&
    6781   [ +  +  +  - ]:        8426 :            (parse->limitCount || root->tuple_fraction > 0))))
    6782                 :       57773 :         return final_target;
    6783                 :             : 
    6784                 :             :     /*
    6785                 :             :      * Report whether the post-sort projection will contain set-returning
    6786                 :             :      * functions.  This is important because it affects whether the Sort can
    6787                 :             :      * rely on the query's LIMIT (if any) to bound the number of rows it needs
    6788                 :             :      * to return.
    6789                 :             :      */
    6790                 :         273 :     *have_postponed_srfs = postpone_srfs;
    6791                 :             : 
    6792                 :             :     /*
    6793                 :             :      * Construct the sort-input target, taking all non-postponable columns and
    6794                 :             :      * then adding Vars, PlaceHolderVars, Aggrefs, and WindowFuncs found in
    6795                 :             :      * the postponable ones.
    6796                 :             :      */
    6797                 :         273 :     input_target = create_empty_pathtarget();
    6798                 :         273 :     postponable_cols = NIL;
    6799                 :             : 
    6800                 :         273 :     i = 0;
    6801   [ +  -  +  +  :        1895 :     foreach(lc, final_target->exprs)
                   +  + ]
    6802                 :             :     {
    6803                 :        1622 :         Expr       *expr = (Expr *) lfirst(lc);
    6804                 :             : 
    6805   [ +  +  +  +  :        1622 :         if (postpone_col[i] || (postpone_srfs && col_is_srf[i]))
                   +  + ]
    6806                 :         325 :             postponable_cols = lappend(postponable_cols, expr);
    6807                 :             :         else
    6808                 :        1297 :             add_column_to_pathtarget(input_target, expr,
    6809         [ +  - ]:        1297 :                                      get_pathtarget_sortgroupref(final_target, i));
    6810                 :             : 
    6811                 :        1622 :         i++;
    6812                 :             :     }
    6813                 :             : 
    6814                 :             :     /*
    6815                 :             :      * Pull out all the Vars, Aggrefs, and WindowFuncs mentioned in
    6816                 :             :      * postponable columns, and add them to the sort-input target if not
    6817                 :             :      * already present.  (Some might be there already.)  We mustn't
    6818                 :             :      * deconstruct Aggrefs or WindowFuncs here, since the projection node
    6819                 :             :      * would be unable to recompute them.
    6820                 :             :      */
    6821                 :         273 :     postponable_vars = pull_var_clause((Node *) postponable_cols,
    6822                 :             :                                        PVC_INCLUDE_AGGREGATES |
    6823                 :             :                                        PVC_INCLUDE_WINDOWFUNCS |
    6824                 :             :                                        PVC_INCLUDE_PLACEHOLDERS);
    6825                 :         273 :     add_new_columns_to_pathtarget(input_target, postponable_vars);
    6826                 :             : 
    6827                 :             :     /* clean up cruft */
    6828                 :         273 :     list_free(postponable_vars);
    6829                 :         273 :     list_free(postponable_cols);
    6830                 :             : 
    6831                 :             :     /* XXX this represents even more redundant cost calculation ... */
    6832                 :         273 :     return set_pathtarget_cost_width(root, input_target);
    6833                 :             : }
    6834                 :             : 
    6835                 :             : /*
    6836                 :             :  * get_cheapest_fractional_path
    6837                 :             :  *    Find the cheapest path for retrieving a specified fraction of all
    6838                 :             :  *    the tuples expected to be returned by the given relation.
    6839                 :             :  *
    6840                 :             :  * Do not consider parameterized paths.  If the caller needs a path for upper
    6841                 :             :  * rel, it can't have parameterized paths.  If the caller needs an append
    6842                 :             :  * subpath, it could become limited by the treatment of similar
    6843                 :             :  * parameterization of all the subpaths.
    6844                 :             :  *
    6845                 :             :  * We interpret tuple_fraction the same way as grouping_planner.
    6846                 :             :  *
    6847                 :             :  * We assume set_cheapest() has been run on the given rel.
    6848                 :             :  */
    6849                 :             : Path *
    6850                 :      363067 : get_cheapest_fractional_path(RelOptInfo *rel, double tuple_fraction)
    6851                 :             : {
    6852                 :      363067 :     Path       *best_path = rel->cheapest_total_path;
    6853                 :             :     ListCell   *l;
    6854                 :             : 
    6855                 :             :     /* If all tuples will be retrieved, just return the cheapest-total path */
    6856         [ +  + ]:      363067 :     if (tuple_fraction <= 0.0)
    6857                 :      356102 :         return best_path;
    6858                 :             : 
    6859                 :             :     /* Convert absolute # of tuples to a fraction; no need to clamp to 0..1 */
    6860   [ +  +  +  + ]:        6965 :     if (tuple_fraction >= 1.0 && best_path->rows > 0)
    6861                 :        2948 :         tuple_fraction /= best_path->rows;
    6862                 :             : 
    6863   [ +  -  +  +  :       17704 :     foreach(l, rel->pathlist)
                   +  + ]
    6864                 :             :     {
    6865                 :       10739 :         Path       *path = (Path *) lfirst(l);
    6866                 :             : 
    6867         [ +  + ]:       10739 :         if (path->param_info)
    6868                 :         166 :             continue;
    6869                 :             : 
    6870   [ +  +  +  + ]:       14181 :         if (path == rel->cheapest_total_path ||
    6871                 :        3608 :             compare_fractional_path_costs(best_path, path, tuple_fraction) <= 0)
    6872                 :       10251 :             continue;
    6873                 :             : 
    6874                 :         322 :         best_path = path;
    6875                 :             :     }
    6876                 :             : 
    6877                 :        6965 :     return best_path;
    6878                 :             : }
    6879                 :             : 
    6880                 :             : /*
    6881                 :             :  * adjust_paths_for_srfs
    6882                 :             :  *      Fix up the Paths of the given upperrel to handle tSRFs properly.
    6883                 :             :  *
    6884                 :             :  * The executor can only handle set-returning functions that appear at the
    6885                 :             :  * top level of the targetlist of a ProjectSet plan node.  If we have any SRFs
    6886                 :             :  * that are not at top level, we need to split up the evaluation into multiple
    6887                 :             :  * plan levels in which each level satisfies this constraint.  This function
    6888                 :             :  * modifies each Path of an upperrel that (might) compute any SRFs in its
    6889                 :             :  * output tlist to insert appropriate projection steps.
    6890                 :             :  *
    6891                 :             :  * The given targets and targets_contain_srfs lists are from
    6892                 :             :  * split_pathtarget_at_srfs().  We assume the existing Paths emit the first
    6893                 :             :  * target in targets.
    6894                 :             :  */
    6895                 :             : static void
    6896                 :       10708 : adjust_paths_for_srfs(PlannerInfo *root, RelOptInfo *rel,
    6897                 :             :                       List *targets, List *targets_contain_srfs)
    6898                 :             : {
    6899                 :             :     ListCell   *lc;
    6900                 :             : 
    6901                 :             :     Assert(list_length(targets) == list_length(targets_contain_srfs));
    6902                 :             :     Assert(!linitial_int(targets_contain_srfs));
    6903                 :             : 
    6904                 :             :     /* If no SRFs appear at this plan level, nothing to do */
    6905         [ +  + ]:       10708 :     if (list_length(targets) == 1)
    6906                 :         481 :         return;
    6907                 :             : 
    6908                 :             :     /*
    6909                 :             :      * Stack SRF-evaluation nodes atop each path for the rel.
    6910                 :             :      *
    6911                 :             :      * In principle we should re-run set_cheapest() here to identify the
    6912                 :             :      * cheapest path, but it seems unlikely that adding the same tlist eval
    6913                 :             :      * costs to all the paths would change that, so we don't bother. Instead,
    6914                 :             :      * just assume that the cheapest-startup and cheapest-total paths remain
    6915                 :             :      * so.  (There should be no parameterized paths anymore, so we needn't
    6916                 :             :      * worry about updating cheapest_parameterized_paths.)
    6917                 :             :      */
    6918   [ +  -  +  +  :       20484 :     foreach(lc, rel->pathlist)
                   +  + ]
    6919                 :             :     {
    6920                 :       10257 :         Path       *subpath = (Path *) lfirst(lc);
    6921                 :       10257 :         Path       *newpath = subpath;
    6922                 :             :         ListCell   *lc1,
    6923                 :             :                    *lc2;
    6924                 :             : 
    6925                 :             :         Assert(subpath->param_info == NULL);
    6926   [ +  -  +  +  :       31556 :         forboth(lc1, targets, lc2, targets_contain_srfs)
          +  -  +  +  +  
             +  +  -  +  
                      + ]
    6927                 :             :         {
    6928                 :       21299 :             PathTarget *thistarget = lfirst_node(PathTarget, lc1);
    6929                 :       21299 :             bool        contains_srfs = (bool) lfirst_int(lc2);
    6930                 :             : 
    6931                 :             :             /* If this level doesn't contain SRFs, do regular projection */
    6932         [ +  + ]:       21299 :             if (contains_srfs)
    6933                 :       10307 :                 newpath = (Path *) create_set_projection_path(root,
    6934                 :             :                                                               rel,
    6935                 :             :                                                               newpath,
    6936                 :             :                                                               thistarget);
    6937                 :             :             else
    6938                 :       10992 :                 newpath = (Path *) apply_projection_to_path(root,
    6939                 :             :                                                             rel,
    6940                 :             :                                                             newpath,
    6941                 :             :                                                             thistarget);
    6942                 :             :         }
    6943                 :       10257 :         lfirst(lc) = newpath;
    6944         [ +  + ]:       10257 :         if (subpath == rel->cheapest_startup_path)
    6945                 :         239 :             rel->cheapest_startup_path = newpath;
    6946         [ +  + ]:       10257 :         if (subpath == rel->cheapest_total_path)
    6947                 :         239 :             rel->cheapest_total_path = newpath;
    6948                 :             :     }
    6949                 :             : 
    6950                 :             :     /* Likewise for partial paths, if any */
    6951   [ +  +  +  +  :       10242 :     foreach(lc, rel->partial_pathlist)
                   +  + ]
    6952                 :             :     {
    6953                 :          15 :         Path       *subpath = (Path *) lfirst(lc);
    6954                 :          15 :         Path       *newpath = subpath;
    6955                 :             :         ListCell   *lc1,
    6956                 :             :                    *lc2;
    6957                 :             : 
    6958                 :             :         Assert(subpath->param_info == NULL);
    6959   [ +  -  +  +  :          60 :         forboth(lc1, targets, lc2, targets_contain_srfs)
          +  -  +  +  +  
             +  +  -  +  
                      + ]
    6960                 :             :         {
    6961                 :          45 :             PathTarget *thistarget = lfirst_node(PathTarget, lc1);
    6962                 :          45 :             bool        contains_srfs = (bool) lfirst_int(lc2);
    6963                 :             : 
    6964                 :             :             /* If this level doesn't contain SRFs, do regular projection */
    6965         [ +  + ]:          45 :             if (contains_srfs)
    6966                 :          15 :                 newpath = (Path *) create_set_projection_path(root,
    6967                 :             :                                                               rel,
    6968                 :             :                                                               newpath,
    6969                 :             :                                                               thistarget);
    6970                 :             :             else
    6971                 :             :             {
    6972                 :             :                 /* avoid apply_projection_to_path, in case of multiple refs */
    6973                 :          30 :                 newpath = (Path *) create_projection_path(root,
    6974                 :             :                                                           rel,
    6975                 :             :                                                           newpath,
    6976                 :             :                                                           thistarget);
    6977                 :             :             }
    6978                 :             :         }
    6979                 :          15 :         lfirst(lc) = newpath;
    6980                 :             :     }
    6981                 :             : }
    6982                 :             : 
    6983                 :             : /*
    6984                 :             :  * expression_planner
    6985                 :             :  *      Perform planner's transformations on a standalone expression.
    6986                 :             :  *
    6987                 :             :  * Various utility commands need to evaluate expressions that are not part
    6988                 :             :  * of a plannable query.  They can do so using the executor's regular
    6989                 :             :  * expression-execution machinery, but first the expression has to be fed
    6990                 :             :  * through here to transform it from parser output to something executable.
    6991                 :             :  *
    6992                 :             :  * Currently, we disallow sublinks in standalone expressions, so there's no
    6993                 :             :  * real "planning" involved here.  (That might not always be true though.)
    6994                 :             :  * What we must do is run eval_const_expressions to ensure that any function
    6995                 :             :  * calls are converted to positional notation and function default arguments
    6996                 :             :  * get inserted.  The fact that constant subexpressions get simplified is a
    6997                 :             :  * side-effect that is useful when the expression will get evaluated more than
    6998                 :             :  * once.  Also, we must fix operator function IDs.
    6999                 :             :  *
    7000                 :             :  * This does not return any information about dependencies of the expression.
    7001                 :             :  * Hence callers should use the results only for the duration of the current
    7002                 :             :  * query.  Callers that would like to cache the results for longer should use
    7003                 :             :  * expression_planner_with_deps, probably via the plancache.
    7004                 :             :  *
    7005                 :             :  * Note: this must not make any damaging changes to the passed-in expression
    7006                 :             :  * tree.  (It would actually be okay to apply fix_opfuncids to it, but since
    7007                 :             :  * we first do an expression_tree_mutator-based walk, what is returned will
    7008                 :             :  * be a new node tree.)  The result is constructed in the current memory
    7009                 :             :  * context; beware that this can leak a lot of additional stuff there, too.
    7010                 :             :  */
    7011                 :             : Expr *
    7012                 :      138723 : expression_planner(Expr *expr)
    7013                 :             : {
    7014                 :             :     Node       *result;
    7015                 :             : 
    7016                 :             :     /*
    7017                 :             :      * Convert named-argument function calls, insert default arguments and
    7018                 :             :      * simplify constant subexprs
    7019                 :             :      */
    7020                 :      138723 :     result = eval_const_expressions(NULL, (Node *) expr);
    7021                 :             : 
    7022                 :             :     /* Fill in opfuncid values if missing */
    7023                 :      138711 :     fix_opfuncids(result);
    7024                 :             : 
    7025                 :      138711 :     return (Expr *) result;
    7026                 :             : }
    7027                 :             : 
    7028                 :             : /*
    7029                 :             :  * expression_planner_with_deps
    7030                 :             :  *      Perform planner's transformations on a standalone expression,
    7031                 :             :  *      returning expression dependency information along with the result.
    7032                 :             :  *
    7033                 :             :  * This is identical to expression_planner() except that it also returns
    7034                 :             :  * information about possible dependencies of the expression, ie identities of
    7035                 :             :  * objects whose definitions affect the result.  As in a PlannedStmt, these
    7036                 :             :  * are expressed as a list of relation Oids and a list of PlanInvalItems.
    7037                 :             :  */
    7038                 :             : Expr *
    7039                 :         261 : expression_planner_with_deps(Expr *expr,
    7040                 :             :                              List **relationOids,
    7041                 :             :                              List **invalItems)
    7042                 :             : {
    7043                 :             :     Node       *result;
    7044                 :             :     PlannerGlobal glob;
    7045                 :             :     PlannerInfo root;
    7046                 :             : 
    7047                 :             :     /* Make up dummy planner state so we can use setrefs machinery */
    7048   [ +  -  +  -  :        7569 :     MemSet(&glob, 0, sizeof(glob));
          +  -  +  -  +  
                      + ]
    7049                 :         261 :     glob.type = T_PlannerGlobal;
    7050                 :         261 :     glob.relationOids = NIL;
    7051                 :         261 :     glob.invalItems = NIL;
    7052                 :             : 
    7053   [ +  -  +  -  :       24534 :     MemSet(&root, 0, sizeof(root));
          +  -  +  -  +  
                      + ]
    7054                 :         261 :     root.type = T_PlannerInfo;
    7055                 :         261 :     root.glob = &glob;
    7056                 :             : 
    7057                 :             :     /*
    7058                 :             :      * Convert named-argument function calls, insert default arguments and
    7059                 :             :      * simplify constant subexprs.  Collect identities of inlined functions
    7060                 :             :      * and elided domains, too.
    7061                 :             :      */
    7062                 :         261 :     result = eval_const_expressions(&root, (Node *) expr);
    7063                 :             : 
    7064                 :             :     /* Fill in opfuncid values if missing */
    7065                 :         261 :     fix_opfuncids(result);
    7066                 :             : 
    7067                 :             :     /*
    7068                 :             :      * Now walk the finished expression to find anything else we ought to
    7069                 :             :      * record as an expression dependency.
    7070                 :             :      */
    7071                 :         261 :     (void) extract_query_dependencies_walker(result, &root);
    7072                 :             : 
    7073                 :         261 :     *relationOids = glob.relationOids;
    7074                 :         261 :     *invalItems = glob.invalItems;
    7075                 :             : 
    7076                 :         261 :     return (Expr *) result;
    7077                 :             : }
    7078                 :             : 
    7079                 :             : 
    7080                 :             : /*
    7081                 :             :  * plan_cluster_use_sort
    7082                 :             :  *      Use the planner to decide how CLUSTER should implement sorting
    7083                 :             :  *
    7084                 :             :  * tableOid is the OID of a table to be clustered on its index indexOid
    7085                 :             :  * (which is already known to be a btree index).  Decide whether it's
    7086                 :             :  * cheaper to do an indexscan or a seqscan-plus-sort to execute the CLUSTER.
    7087                 :             :  * Return true to use sorting, false to use an indexscan.
    7088                 :             :  *
    7089                 :             :  * Note: caller had better already hold some type of lock on the table.
    7090                 :             :  */
    7091                 :             : bool
    7092                 :         144 : plan_cluster_use_sort(Oid tableOid, Oid indexOid)
    7093                 :             : {
    7094                 :             :     PlannerInfo *root;
    7095                 :             :     Query      *query;
    7096                 :             :     PlannerGlobal *glob;
    7097                 :             :     RangeTblEntry *rte;
    7098                 :             :     RelOptInfo *rel;
    7099                 :             :     IndexOptInfo *indexInfo;
    7100                 :             :     QualCost    indexExprCost;
    7101                 :             :     Cost        comparisonCost;
    7102                 :             :     Path       *seqScanPath;
    7103                 :             :     Path        seqScanAndSortPath;
    7104                 :             :     IndexPath  *indexScanPath;
    7105                 :             :     ListCell   *lc;
    7106                 :             : 
    7107                 :             :     /* We can short-circuit the cost comparison if indexscans are disabled */
    7108         [ +  + ]:         144 :     if (!enable_indexscan)
    7109                 :          20 :         return true;            /* use sort */
    7110                 :             : 
    7111                 :             :     /* Set up mostly-dummy planner state */
    7112                 :         124 :     query = makeNode(Query);
    7113                 :         124 :     query->commandType = CMD_SELECT;
    7114                 :             : 
    7115                 :         124 :     glob = makeNode(PlannerGlobal);
    7116                 :             : 
    7117                 :         124 :     root = makeNode(PlannerInfo);
    7118                 :         124 :     root->parse = query;
    7119                 :         124 :     root->glob = glob;
    7120                 :         124 :     root->query_level = 1;
    7121                 :         124 :     root->planner_cxt = CurrentMemoryContext;
    7122                 :         124 :     root->wt_param_id = -1;
    7123                 :         124 :     root->join_domains = list_make1(makeNode(JoinDomain));
    7124                 :             : 
    7125                 :             :     /* Build a minimal RTE for the rel */
    7126                 :         124 :     rte = makeNode(RangeTblEntry);
    7127                 :         124 :     rte->rtekind = RTE_RELATION;
    7128                 :         124 :     rte->relid = tableOid;
    7129                 :         124 :     rte->relkind = RELKIND_RELATION; /* Don't be too picky. */
    7130                 :         124 :     rte->rellockmode = AccessShareLock;
    7131                 :         124 :     rte->lateral = false;
    7132                 :         124 :     rte->inh = false;
    7133                 :         124 :     rte->inFromCl = true;
    7134                 :         124 :     query->rtable = list_make1(rte);
    7135                 :         124 :     addRTEPermissionInfo(&query->rteperminfos, rte);
    7136                 :             : 
    7137                 :             :     /* Set up RTE/RelOptInfo arrays */
    7138                 :         124 :     setup_simple_rel_arrays(root);
    7139                 :             : 
    7140                 :             :     /* Build RelOptInfo */
    7141                 :         124 :     rel = build_simple_rel(root, 1, NULL);
    7142                 :             : 
    7143                 :             :     /* Locate IndexOptInfo for the target index */
    7144                 :         124 :     indexInfo = NULL;
    7145   [ +  -  +  -  :         154 :     foreach(lc, rel->indexlist)
                   +  - ]
    7146                 :             :     {
    7147                 :         154 :         indexInfo = lfirst_node(IndexOptInfo, lc);
    7148         [ +  + ]:         154 :         if (indexInfo->indexoid == indexOid)
    7149                 :         124 :             break;
    7150                 :             :     }
    7151                 :             : 
    7152                 :             :     /*
    7153                 :             :      * It's possible that get_relation_info did not generate an IndexOptInfo
    7154                 :             :      * for the desired index; this could happen if it's not yet reached its
    7155                 :             :      * indcheckxmin usability horizon, or if it's a system index and we're
    7156                 :             :      * ignoring system indexes.  In such cases we should tell CLUSTER to not
    7157                 :             :      * trust the index contents but use seqscan-and-sort.
    7158                 :             :      */
    7159         [ -  + ]:         124 :     if (lc == NULL)             /* not in the list? */
    7160                 :           0 :         return true;            /* use sort */
    7161                 :             : 
    7162                 :             :     /*
    7163                 :             :      * Rather than doing all the pushups that would be needed to use
    7164                 :             :      * set_baserel_size_estimates, just do a quick hack for rows and width.
    7165                 :             :      */
    7166                 :         124 :     rel->rows = rel->tuples;
    7167                 :         124 :     rel->reltarget->width = get_relation_data_width(tableOid, NULL);
    7168                 :             : 
    7169                 :         124 :     root->total_table_pages = rel->pages;
    7170                 :             : 
    7171                 :             :     /*
    7172                 :             :      * Determine eval cost of the index expressions, if any.  We need to
    7173                 :             :      * charge twice that amount for each tuple comparison that happens during
    7174                 :             :      * the sort, since tuplesort.c will have to re-evaluate the index
    7175                 :             :      * expressions each time.  (XXX that's pretty inefficient...)
    7176                 :             :      */
    7177                 :         124 :     cost_qual_eval(&indexExprCost, indexInfo->indexprs, root);
    7178                 :         124 :     comparisonCost = 2.0 * (indexExprCost.startup + indexExprCost.per_tuple);
    7179                 :             : 
    7180                 :             :     /* Estimate the cost of seq scan + sort */
    7181                 :         124 :     seqScanPath = create_seqscan_path(root, rel, NULL, 0);
    7182                 :         124 :     cost_sort(&seqScanAndSortPath, root, NIL,
    7183                 :             :               seqScanPath->disabled_nodes,
    7184                 :         124 :               seqScanPath->total_cost, rel->tuples, rel->reltarget->width,
    7185                 :             :               comparisonCost, maintenance_work_mem, -1.0);
    7186                 :             : 
    7187                 :             :     /* Estimate the cost of index scan */
    7188                 :         124 :     indexScanPath = create_index_path(root, indexInfo,
    7189                 :             :                                       NIL, NIL, NIL, NIL,
    7190                 :             :                                       ForwardScanDirection, false,
    7191                 :             :                                       NULL, 1.0, false);
    7192                 :             : 
    7193                 :         124 :     return (seqScanAndSortPath.total_cost < indexScanPath->path.total_cost);
    7194                 :             : }
    7195                 :             : 
    7196                 :             : /*
    7197                 :             :  * plan_create_index_workers
    7198                 :             :  *      Use the planner to decide how many parallel worker processes
    7199                 :             :  *      CREATE INDEX should request for use
    7200                 :             :  *
    7201                 :             :  * tableOid is the table on which the index is to be built.  indexOid is the
    7202                 :             :  * OID of an index to be created or reindexed (which must be an index with
    7203                 :             :  * support for parallel builds - currently btree, GIN, or BRIN).
    7204                 :             :  *
    7205                 :             :  * Return value is the number of parallel worker processes to request.  It
    7206                 :             :  * may be unsafe to proceed if this is 0.  Note that this does not include the
    7207                 :             :  * leader participating as a worker (value is always a number of parallel
    7208                 :             :  * worker processes).
    7209                 :             :  *
    7210                 :             :  * Note: caller had better already hold some type of lock on the table and
    7211                 :             :  * index.
    7212                 :             :  */
    7213                 :             : int
    7214                 :       23610 : plan_create_index_workers(Oid tableOid, Oid indexOid)
    7215                 :             : {
    7216                 :             :     PlannerInfo *root;
    7217                 :             :     Query      *query;
    7218                 :             :     PlannerGlobal *glob;
    7219                 :             :     RangeTblEntry *rte;
    7220                 :             :     Relation    heap;
    7221                 :             :     Relation    index;
    7222                 :             :     RelOptInfo *rel;
    7223                 :             :     int         parallel_workers;
    7224                 :             :     BlockNumber heap_blocks;
    7225                 :             :     double      reltuples;
    7226                 :             :     double      allvisfrac;
    7227                 :             : 
    7228                 :             :     /*
    7229                 :             :      * We don't allow performing parallel operation in standalone backend or
    7230                 :             :      * when parallelism is disabled.
    7231                 :             :      */
    7232   [ +  +  +  + ]:       23610 :     if (!IsUnderPostmaster || max_parallel_maintenance_workers == 0)
    7233                 :         301 :         return 0;
    7234                 :             : 
    7235                 :             :     /* Set up largely-dummy planner state */
    7236                 :       23309 :     query = makeNode(Query);
    7237                 :       23309 :     query->commandType = CMD_SELECT;
    7238                 :             : 
    7239                 :       23309 :     glob = makeNode(PlannerGlobal);
    7240                 :             : 
    7241                 :       23309 :     root = makeNode(PlannerInfo);
    7242                 :       23309 :     root->parse = query;
    7243                 :       23309 :     root->glob = glob;
    7244                 :       23309 :     root->query_level = 1;
    7245                 :       23309 :     root->planner_cxt = CurrentMemoryContext;
    7246                 :       23309 :     root->wt_param_id = -1;
    7247                 :       23309 :     root->join_domains = list_make1(makeNode(JoinDomain));
    7248                 :             : 
    7249                 :             :     /*
    7250                 :             :      * Build a minimal RTE.
    7251                 :             :      *
    7252                 :             :      * Mark the RTE with inh = true.  This is a kludge to prevent
    7253                 :             :      * get_relation_info() from fetching index info, which is necessary
    7254                 :             :      * because it does not expect that any IndexOptInfo is currently
    7255                 :             :      * undergoing REINDEX.
    7256                 :             :      */
    7257                 :       23309 :     rte = makeNode(RangeTblEntry);
    7258                 :       23309 :     rte->rtekind = RTE_RELATION;
    7259                 :       23309 :     rte->relid = tableOid;
    7260                 :       23309 :     rte->relkind = RELKIND_RELATION; /* Don't be too picky. */
    7261                 :       23309 :     rte->rellockmode = AccessShareLock;
    7262                 :       23309 :     rte->lateral = false;
    7263                 :       23309 :     rte->inh = true;
    7264                 :       23309 :     rte->inFromCl = true;
    7265                 :       23309 :     query->rtable = list_make1(rte);
    7266                 :       23309 :     addRTEPermissionInfo(&query->rteperminfos, rte);
    7267                 :             : 
    7268                 :             :     /* Set up RTE/RelOptInfo arrays */
    7269                 :       23309 :     setup_simple_rel_arrays(root);
    7270                 :             : 
    7271                 :             :     /* Build RelOptInfo */
    7272                 :       23309 :     rel = build_simple_rel(root, 1, NULL);
    7273                 :             : 
    7274                 :             :     /* Rels are assumed already locked by the caller */
    7275                 :       23309 :     heap = table_open(tableOid, NoLock);
    7276                 :       23309 :     index = index_open(indexOid, NoLock);
    7277                 :             : 
    7278                 :             :     /*
    7279                 :             :      * Determine if it's safe to proceed.
    7280                 :             :      *
    7281                 :             :      * Currently, parallel workers can't access the leader's temporary tables.
    7282                 :             :      * Furthermore, any index predicate or index expressions must be parallel
    7283                 :             :      * safe.
    7284                 :             :      */
    7285         [ +  + ]:       23309 :     if (heap->rd_rel->relpersistence == RELPERSISTENCE_TEMP ||
    7286         [ +  + ]:       21890 :         !is_parallel_safe(root, (Node *) RelationGetIndexExpressions(index)) ||
    7287         [ -  + ]:       21800 :         !is_parallel_safe(root, (Node *) RelationGetIndexPredicate(index)))
    7288                 :             :     {
    7289                 :        1509 :         parallel_workers = 0;
    7290                 :        1509 :         goto done;
    7291                 :             :     }
    7292                 :             : 
    7293                 :             :     /*
    7294                 :             :      * If parallel_workers storage parameter is set for the table, accept that
    7295                 :             :      * as the number of parallel worker processes to launch (though still cap
    7296                 :             :      * at max_parallel_maintenance_workers).  Note that we deliberately do not
    7297                 :             :      * consider any other factor when parallel_workers is set. (e.g., memory
    7298                 :             :      * use by workers.)
    7299                 :             :      */
    7300         [ +  + ]:       21800 :     if (rel->rel_parallel_workers != -1)
    7301                 :             :     {
    7302                 :          59 :         parallel_workers = Min(rel->rel_parallel_workers,
    7303                 :             :                                max_parallel_maintenance_workers);
    7304                 :          59 :         goto done;
    7305                 :             :     }
    7306                 :             : 
    7307                 :             :     /*
    7308                 :             :      * Estimate heap relation size ourselves, since rel->pages cannot be
    7309                 :             :      * trusted (heap RTE was marked as inheritance parent)
    7310                 :             :      */
    7311                 :       21741 :     estimate_rel_size(heap, NULL, &heap_blocks, &reltuples, &allvisfrac);
    7312                 :             : 
    7313                 :             :     /*
    7314                 :             :      * Determine number of workers to scan the heap relation using generic
    7315                 :             :      * model
    7316                 :             :      */
    7317                 :       21741 :     parallel_workers = compute_parallel_worker(rel, heap_blocks, -1,
    7318                 :             :                                                max_parallel_maintenance_workers);
    7319                 :             : 
    7320                 :             :     /*
    7321                 :             :      * Cap workers based on available maintenance_work_mem as needed.
    7322                 :             :      *
    7323                 :             :      * Note that each tuplesort participant receives an even share of the
    7324                 :             :      * total maintenance_work_mem budget.  Aim to leave participants
    7325                 :             :      * (including the leader as a participant) with no less than 32MB of
    7326                 :             :      * memory.  This leaves cases where maintenance_work_mem is set to 64MB
    7327                 :             :      * immediately past the threshold of being capable of launching a single
    7328                 :             :      * parallel worker to sort.
    7329                 :             :      */
    7330         [ +  + ]:       21850 :     while (parallel_workers > 0 &&
    7331         [ +  + ]:         219 :            maintenance_work_mem / (parallel_workers + 1) < 32 * 1024)
    7332                 :         109 :         parallel_workers--;
    7333                 :             : 
    7334                 :       21741 : done:
    7335                 :       23309 :     index_close(index, NoLock);
    7336                 :       23309 :     table_close(heap, NoLock);
    7337                 :             : 
    7338                 :       23309 :     return parallel_workers;
    7339                 :             : }
    7340                 :             : 
    7341                 :             : /*
    7342                 :             :  * add_paths_to_grouping_rel
    7343                 :             :  *
    7344                 :             :  * Add non-partial paths to grouping relation.
    7345                 :             :  */
    7346                 :             : static void
    7347                 :       35179 : add_paths_to_grouping_rel(PlannerInfo *root, RelOptInfo *input_rel,
    7348                 :             :                           RelOptInfo *grouped_rel,
    7349                 :             :                           RelOptInfo *partially_grouped_rel,
    7350                 :             :                           const AggClauseCosts *agg_costs,
    7351                 :             :                           grouping_sets_data *gd,
    7352                 :             :                           GroupPathExtraData *extra)
    7353                 :             : {
    7354                 :       35179 :     Query      *parse = root->parse;
    7355                 :       35179 :     Path       *cheapest_path = input_rel->cheapest_total_path;
    7356                 :       35179 :     Path       *cheapest_partially_grouped_path = NULL;
    7357                 :             :     ListCell   *lc;
    7358                 :       35179 :     bool        can_hash = (extra->flags & GROUPING_CAN_USE_HASH) != 0;
    7359                 :       35179 :     bool        can_sort = (extra->flags & GROUPING_CAN_USE_SORT) != 0;
    7360                 :       35179 :     List       *havingQual = (List *) extra->havingQual;
    7361                 :       35179 :     AggClauseCosts *agg_final_costs = &extra->agg_final_costs;
    7362                 :       35179 :     double      dNumGroups = 0;
    7363                 :       35179 :     double      dNumFinalGroups = 0;
    7364                 :             : 
    7365                 :             :     /*
    7366                 :             :      * Estimate number of groups for non-split aggregation.
    7367                 :             :      */
    7368                 :       35179 :     dNumGroups = get_number_of_groups(root,
    7369                 :             :                                       cheapest_path->rows,
    7370                 :             :                                       gd,
    7371                 :             :                                       extra->targetList);
    7372                 :             : 
    7373   [ +  +  +  - ]:       35179 :     if (partially_grouped_rel && partially_grouped_rel->pathlist)
    7374                 :             :     {
    7375                 :        2500 :         cheapest_partially_grouped_path =
    7376                 :             :             partially_grouped_rel->cheapest_total_path;
    7377                 :             : 
    7378                 :             :         /*
    7379                 :             :          * Estimate number of groups for final phase of partial aggregation.
    7380                 :             :          */
    7381                 :             :         dNumFinalGroups =
    7382                 :        2500 :             get_number_of_groups(root,
    7383                 :             :                                  cheapest_partially_grouped_path->rows,
    7384                 :             :                                  gd,
    7385                 :             :                                  extra->targetList);
    7386                 :             :     }
    7387                 :             : 
    7388         [ +  + ]:       35179 :     if (can_sort)
    7389                 :             :     {
    7390                 :             :         /*
    7391                 :             :          * Use any available suitably-sorted path as input, and also consider
    7392                 :             :          * sorting the cheapest-total path and incremental sort on any paths
    7393                 :             :          * with presorted keys.
    7394                 :             :          */
    7395   [ +  -  +  +  :       72954 :         foreach(lc, input_rel->pathlist)
                   +  + ]
    7396                 :             :         {
    7397                 :             :             ListCell   *lc2;
    7398                 :       37780 :             Path       *path = (Path *) lfirst(lc);
    7399                 :       37780 :             Path       *path_save = path;
    7400                 :       37780 :             List       *pathkey_orderings = NIL;
    7401                 :             : 
    7402                 :             :             /* generate alternative group orderings that might be useful */
    7403                 :       37780 :             pathkey_orderings = get_useful_group_keys_orderings(root, path);
    7404                 :             : 
    7405                 :             :             Assert(list_length(pathkey_orderings) > 0);
    7406                 :             : 
    7407   [ +  -  +  +  :       75692 :             foreach(lc2, pathkey_orderings)
                   +  + ]
    7408                 :             :             {
    7409                 :       37912 :                 GroupByOrdering *info = (GroupByOrdering *) lfirst(lc2);
    7410                 :             : 
    7411                 :             :                 /* restore the path (we replace it in the loop) */
    7412                 :       37912 :                 path = path_save;
    7413                 :             : 
    7414                 :       37912 :                 path = make_ordered_path(root,
    7415                 :             :                                          grouped_rel,
    7416                 :             :                                          path,
    7417                 :             :                                          cheapest_path,
    7418                 :             :                                          info->pathkeys,
    7419                 :             :                                          -1.0);
    7420         [ +  + ]:       37912 :                 if (path == NULL)
    7421                 :         321 :                     continue;
    7422                 :             : 
    7423                 :             :                 /* Now decide what to stick atop it */
    7424         [ +  + ]:       37591 :                 if (parse->groupingSets)
    7425                 :             :                 {
    7426                 :         970 :                     consider_groupingsets_paths(root, grouped_rel,
    7427                 :             :                                                 path, true, can_hash,
    7428                 :             :                                                 gd, agg_costs, dNumGroups);
    7429                 :             :                 }
    7430         [ +  + ]:       36621 :                 else if (parse->hasAggs)
    7431                 :             :                 {
    7432                 :             :                     /*
    7433                 :             :                      * We have aggregation, possibly with plain GROUP BY. Make
    7434                 :             :                      * an AggPath.
    7435                 :             :                      */
    7436                 :       35939 :                     add_path(grouped_rel, (Path *)
    7437                 :       35939 :                              create_agg_path(root,
    7438                 :             :                                              grouped_rel,
    7439                 :             :                                              path,
    7440                 :       35939 :                                              grouped_rel->reltarget,
    7441                 :       35939 :                                              parse->groupClause ? AGG_SORTED : AGG_PLAIN,
    7442                 :             :                                              AGGSPLIT_SIMPLE,
    7443                 :             :                                              info->clauses,
    7444                 :             :                                              havingQual,
    7445                 :             :                                              agg_costs,
    7446                 :             :                                              dNumGroups));
    7447                 :             :                 }
    7448         [ +  - ]:         682 :                 else if (parse->groupClause)
    7449                 :             :                 {
    7450                 :             :                     /*
    7451                 :             :                      * We have GROUP BY without aggregation or grouping sets.
    7452                 :             :                      * Make a GroupPath.
    7453                 :             :                      */
    7454                 :         682 :                     add_path(grouped_rel, (Path *)
    7455                 :         682 :                              create_group_path(root,
    7456                 :             :                                                grouped_rel,
    7457                 :             :                                                path,
    7458                 :             :                                                info->clauses,
    7459                 :             :                                                havingQual,
    7460                 :             :                                                dNumGroups));
    7461                 :             :                 }
    7462                 :             :                 else
    7463                 :             :                 {
    7464                 :             :                     /* Other cases should have been handled above */
    7465                 :             :                     Assert(false);
    7466                 :             :                 }
    7467                 :             :             }
    7468                 :             :         }
    7469                 :             : 
    7470                 :             :         /*
    7471                 :             :          * Instead of operating directly on the input relation, we can
    7472                 :             :          * consider finalizing a partially aggregated path.
    7473                 :             :          */
    7474         [ +  + ]:       35174 :         if (partially_grouped_rel != NULL)
    7475                 :             :         {
    7476   [ +  -  +  +  :        6446 :             foreach(lc, partially_grouped_rel->pathlist)
                   +  + ]
    7477                 :             :             {
    7478                 :             :                 ListCell   *lc2;
    7479                 :        3946 :                 Path       *path = (Path *) lfirst(lc);
    7480                 :        3946 :                 Path       *path_save = path;
    7481                 :        3946 :                 List       *pathkey_orderings = NIL;
    7482                 :             : 
    7483                 :             :                 /* generate alternative group orderings that might be useful */
    7484                 :        3946 :                 pathkey_orderings = get_useful_group_keys_orderings(root, path);
    7485                 :             : 
    7486                 :             :                 Assert(list_length(pathkey_orderings) > 0);
    7487                 :             : 
    7488                 :             :                 /* process all potentially interesting grouping reorderings */
    7489   [ +  -  +  +  :        7892 :                 foreach(lc2, pathkey_orderings)
                   +  + ]
    7490                 :             :                 {
    7491                 :        3946 :                     GroupByOrdering *info = (GroupByOrdering *) lfirst(lc2);
    7492                 :             : 
    7493                 :             :                     /* restore the path (we replace it in the loop) */
    7494                 :        3946 :                     path = path_save;
    7495                 :             : 
    7496                 :        3946 :                     path = make_ordered_path(root,
    7497                 :             :                                              grouped_rel,
    7498                 :             :                                              path,
    7499                 :             :                                              cheapest_partially_grouped_path,
    7500                 :             :                                              info->pathkeys,
    7501                 :             :                                              -1.0);
    7502                 :             : 
    7503         [ +  + ]:        3946 :                     if (path == NULL)
    7504                 :         172 :                         continue;
    7505                 :             : 
    7506         [ +  + ]:        3774 :                     if (parse->hasAggs)
    7507                 :        3572 :                         add_path(grouped_rel, (Path *)
    7508                 :        3572 :                                  create_agg_path(root,
    7509                 :             :                                                  grouped_rel,
    7510                 :             :                                                  path,
    7511                 :        3572 :                                                  grouped_rel->reltarget,
    7512                 :        3572 :                                                  parse->groupClause ? AGG_SORTED : AGG_PLAIN,
    7513                 :             :                                                  AGGSPLIT_FINAL_DESERIAL,
    7514                 :             :                                                  info->clauses,
    7515                 :             :                                                  havingQual,
    7516                 :             :                                                  agg_final_costs,
    7517                 :             :                                                  dNumFinalGroups));
    7518                 :             :                     else
    7519                 :         202 :                         add_path(grouped_rel, (Path *)
    7520                 :         202 :                                  create_group_path(root,
    7521                 :             :                                                    grouped_rel,
    7522                 :             :                                                    path,
    7523                 :             :                                                    info->clauses,
    7524                 :             :                                                    havingQual,
    7525                 :             :                                                    dNumFinalGroups));
    7526                 :             : 
    7527                 :             :                 }
    7528                 :             :             }
    7529                 :             :         }
    7530                 :             :     }
    7531                 :             : 
    7532         [ +  + ]:       35179 :     if (can_hash)
    7533                 :             :     {
    7534         [ +  + ]:        5159 :         if (parse->groupingSets)
    7535                 :             :         {
    7536                 :             :             /*
    7537                 :             :              * Try for a hash-only groupingsets path over unsorted input.
    7538                 :             :              */
    7539                 :         807 :             consider_groupingsets_paths(root, grouped_rel,
    7540                 :             :                                         cheapest_path, false, true,
    7541                 :             :                                         gd, agg_costs, dNumGroups);
    7542                 :             :         }
    7543                 :             :         else
    7544                 :             :         {
    7545                 :             :             /*
    7546                 :             :              * Generate a HashAgg Path.  We just need an Agg over the
    7547                 :             :              * cheapest-total input path, since input order won't matter.
    7548                 :             :              */
    7549                 :        4352 :             add_path(grouped_rel, (Path *)
    7550                 :        4352 :                      create_agg_path(root, grouped_rel,
    7551                 :             :                                      cheapest_path,
    7552                 :        4352 :                                      grouped_rel->reltarget,
    7553                 :             :                                      AGG_HASHED,
    7554                 :             :                                      AGGSPLIT_SIMPLE,
    7555                 :             :                                      root->processed_groupClause,
    7556                 :             :                                      havingQual,
    7557                 :             :                                      agg_costs,
    7558                 :             :                                      dNumGroups));
    7559                 :             :         }
    7560                 :             : 
    7561                 :             :         /*
    7562                 :             :          * Generate a Finalize HashAgg Path atop of the cheapest partially
    7563                 :             :          * grouped path, assuming there is one
    7564                 :             :          */
    7565   [ +  +  +  - ]:        5159 :         if (partially_grouped_rel && partially_grouped_rel->pathlist)
    7566                 :             :         {
    7567                 :        1192 :             add_path(grouped_rel, (Path *)
    7568                 :        1192 :                      create_agg_path(root,
    7569                 :             :                                      grouped_rel,
    7570                 :             :                                      cheapest_partially_grouped_path,
    7571                 :        1192 :                                      grouped_rel->reltarget,
    7572                 :             :                                      AGG_HASHED,
    7573                 :             :                                      AGGSPLIT_FINAL_DESERIAL,
    7574                 :             :                                      root->processed_groupClause,
    7575                 :             :                                      havingQual,
    7576                 :             :                                      agg_final_costs,
    7577                 :             :                                      dNumFinalGroups));
    7578                 :             :         }
    7579                 :             :     }
    7580                 :             : 
    7581                 :             :     /*
    7582                 :             :      * When partitionwise aggregate is used, we might have fully aggregated
    7583                 :             :      * paths in the partial pathlist, because add_paths_to_append_rel() will
    7584                 :             :      * consider a path for grouped_rel consisting of a Parallel Append of
    7585                 :             :      * non-partial paths from each child.
    7586                 :             :      */
    7587         [ +  + ]:       35179 :     if (grouped_rel->partial_pathlist != NIL)
    7588                 :         265 :         gather_grouping_paths(root, grouped_rel);
    7589                 :       35179 : }
    7590                 :             : 
    7591                 :             : /*
    7592                 :             :  * create_partial_grouping_paths
    7593                 :             :  *
    7594                 :             :  * Create a new upper relation representing the result of partial aggregation
    7595                 :             :  * and populate it with appropriate paths.  Note that we don't finalize the
    7596                 :             :  * lists of paths here, so the caller can add additional partial or non-partial
    7597                 :             :  * paths and must afterward call gather_grouping_paths and set_cheapest on
    7598                 :             :  * the returned upper relation.
    7599                 :             :  *
    7600                 :             :  * All paths for this new upper relation -- both partial and non-partial --
    7601                 :             :  * have been partially aggregated but require a subsequent FinalizeAggregate
    7602                 :             :  * step.
    7603                 :             :  *
    7604                 :             :  * NB: This function is allowed to return NULL if it determines that there is
    7605                 :             :  * no real need to create a new RelOptInfo.
    7606                 :             :  */
    7607                 :             : static RelOptInfo *
    7608                 :       31896 : create_partial_grouping_paths(PlannerInfo *root,
    7609                 :             :                               RelOptInfo *grouped_rel,
    7610                 :             :                               RelOptInfo *input_rel,
    7611                 :             :                               grouping_sets_data *gd,
    7612                 :             :                               GroupPathExtraData *extra,
    7613                 :             :                               bool force_rel_creation)
    7614                 :             : {
    7615                 :       31896 :     Query      *parse = root->parse;
    7616                 :             :     RelOptInfo *partially_grouped_rel;
    7617                 :       31896 :     RelOptInfo *eager_agg_rel = NULL;
    7618                 :       31896 :     AggClauseCosts *agg_partial_costs = &extra->agg_partial_costs;
    7619                 :       31896 :     AggClauseCosts *agg_final_costs = &extra->agg_final_costs;
    7620                 :       31896 :     Path       *cheapest_partial_path = NULL;
    7621                 :       31896 :     Path       *cheapest_total_path = NULL;
    7622                 :       31896 :     double      dNumPartialGroups = 0;
    7623                 :       31896 :     double      dNumPartialPartialGroups = 0;
    7624                 :             :     ListCell   *lc;
    7625                 :       31896 :     bool        can_hash = (extra->flags & GROUPING_CAN_USE_HASH) != 0;
    7626                 :       31896 :     bool        can_sort = (extra->flags & GROUPING_CAN_USE_SORT) != 0;
    7627                 :             : 
    7628                 :             :     /*
    7629                 :             :      * Check whether any partially aggregated paths have been generated
    7630                 :             :      * through eager aggregation.
    7631                 :             :      */
    7632         [ +  + ]:       31896 :     if (input_rel->grouped_rel &&
    7633         [ +  - ]:         797 :         !IS_DUMMY_REL(input_rel->grouped_rel) &&
    7634         [ +  + ]:         797 :         input_rel->grouped_rel->pathlist != NIL)
    7635                 :         737 :         eager_agg_rel = input_rel->grouped_rel;
    7636                 :             : 
    7637                 :             :     /*
    7638                 :             :      * Consider whether we should generate partially aggregated non-partial
    7639                 :             :      * paths.  We can only do this if we have a non-partial path, and only if
    7640                 :             :      * the parent of the input rel is performing partial partitionwise
    7641                 :             :      * aggregation.  (Note that extra->patype is the type of partitionwise
    7642                 :             :      * aggregation being used at the parent level, not this level.)
    7643                 :             :      */
    7644         [ +  - ]:       31896 :     if (input_rel->pathlist != NIL &&
    7645         [ +  + ]:       31896 :         extra->patype == PARTITIONWISE_AGGREGATE_PARTIAL)
    7646                 :         713 :         cheapest_total_path = input_rel->cheapest_total_path;
    7647                 :             : 
    7648                 :             :     /*
    7649                 :             :      * If parallelism is possible for grouped_rel, then we should consider
    7650                 :             :      * generating partially-grouped partial paths.  However, if the input rel
    7651                 :             :      * has no partial paths, then we can't.
    7652                 :             :      */
    7653   [ +  +  +  + ]:       31896 :     if (grouped_rel->consider_parallel && input_rel->partial_pathlist != NIL)
    7654                 :        2742 :         cheapest_partial_path = linitial(input_rel->partial_pathlist);
    7655                 :             : 
    7656                 :             :     /*
    7657                 :             :      * If we can't partially aggregate partial paths, and we can't partially
    7658                 :             :      * aggregate non-partial paths, and no partially aggregated paths were
    7659                 :             :      * generated by eager aggregation, then don't bother creating the new
    7660                 :             :      * RelOptInfo at all, unless the caller specified force_rel_creation.
    7661                 :             :      */
    7662   [ +  +  +  + ]:       31896 :     if (cheapest_total_path == NULL &&
    7663         [ +  + ]:       28861 :         cheapest_partial_path == NULL &&
    7664                 :       28764 :         eager_agg_rel == NULL &&
    7665         [ +  + ]:       28764 :         !force_rel_creation)
    7666                 :       28683 :         return NULL;
    7667                 :             : 
    7668                 :             :     /*
    7669                 :             :      * Build a new upper relation to represent the result of partially
    7670                 :             :      * aggregating the rows from the input relation.
    7671                 :             :      */
    7672                 :        3213 :     partially_grouped_rel = fetch_upper_rel(root,
    7673                 :             :                                             UPPERREL_PARTIAL_GROUP_AGG,
    7674                 :             :                                             grouped_rel->relids);
    7675                 :        3213 :     partially_grouped_rel->consider_parallel =
    7676                 :        3213 :         grouped_rel->consider_parallel;
    7677                 :        3213 :     partially_grouped_rel->pgs_mask = grouped_rel->pgs_mask;
    7678                 :        3213 :     partially_grouped_rel->reloptkind = grouped_rel->reloptkind;
    7679                 :        3213 :     partially_grouped_rel->serverid = grouped_rel->serverid;
    7680                 :        3213 :     partially_grouped_rel->userid = grouped_rel->userid;
    7681                 :        3213 :     partially_grouped_rel->useridiscurrent = grouped_rel->useridiscurrent;
    7682                 :        3213 :     partially_grouped_rel->fdwroutine = grouped_rel->fdwroutine;
    7683                 :             : 
    7684                 :             :     /*
    7685                 :             :      * Build target list for partial aggregate paths.  These paths cannot just
    7686                 :             :      * emit the same tlist as regular aggregate paths, because (1) we must
    7687                 :             :      * include Vars and Aggrefs needed in HAVING, which might not appear in
    7688                 :             :      * the result tlist, and (2) the Aggrefs must be set in partial mode.
    7689                 :             :      */
    7690                 :        3213 :     partially_grouped_rel->reltarget =
    7691                 :        3213 :         make_partial_grouping_target(root, grouped_rel->reltarget,
    7692                 :             :                                      extra->havingQual);
    7693                 :             : 
    7694         [ +  + ]:        3213 :     if (!extra->partial_costs_set)
    7695                 :             :     {
    7696                 :             :         /*
    7697                 :             :          * Collect statistics about aggregates for estimating costs of
    7698                 :             :          * performing aggregation in parallel.
    7699                 :             :          */
    7700   [ +  -  +  -  :       11580 :         MemSet(agg_partial_costs, 0, sizeof(AggClauseCosts));
          +  -  +  -  +  
                      + ]
    7701   [ +  -  +  -  :       11580 :         MemSet(agg_final_costs, 0, sizeof(AggClauseCosts));
          +  -  +  -  +  
                      + ]
    7702         [ +  + ]:        1930 :         if (parse->hasAggs)
    7703                 :             :         {
    7704                 :             :             /* partial phase */
    7705                 :        1821 :             get_agg_clause_costs(root, AGGSPLIT_INITIAL_SERIAL,
    7706                 :             :                                  agg_partial_costs);
    7707                 :             : 
    7708                 :             :             /* final phase */
    7709                 :        1821 :             get_agg_clause_costs(root, AGGSPLIT_FINAL_DESERIAL,
    7710                 :             :                                  agg_final_costs);
    7711                 :             :         }
    7712                 :             : 
    7713                 :        1930 :         extra->partial_costs_set = true;
    7714                 :             :     }
    7715                 :             : 
    7716                 :             :     /* Estimate number of partial groups. */
    7717         [ +  + ]:        3213 :     if (cheapest_total_path != NULL)
    7718                 :             :         dNumPartialGroups =
    7719                 :         713 :             get_number_of_groups(root,
    7720                 :             :                                  cheapest_total_path->rows,
    7721                 :             :                                  gd,
    7722                 :             :                                  extra->targetList);
    7723         [ +  + ]:        3213 :     if (cheapest_partial_path != NULL)
    7724                 :             :         dNumPartialPartialGroups =
    7725                 :        2742 :             get_number_of_groups(root,
    7726                 :             :                                  cheapest_partial_path->rows,
    7727                 :             :                                  gd,
    7728                 :             :                                  extra->targetList);
    7729                 :             : 
    7730   [ +  -  +  + ]:        3213 :     if (can_sort && cheapest_total_path != NULL)
    7731                 :             :     {
    7732                 :             :         /* This should have been checked previously */
    7733                 :             :         Assert(parse->hasAggs || parse->groupClause);
    7734                 :             : 
    7735                 :             :         /*
    7736                 :             :          * Use any available suitably-sorted path as input, and also consider
    7737                 :             :          * sorting the cheapest partial path.
    7738                 :             :          */
    7739   [ +  -  +  +  :        1426 :         foreach(lc, input_rel->pathlist)
                   +  + ]
    7740                 :             :         {
    7741                 :             :             ListCell   *lc2;
    7742                 :         713 :             Path       *path = (Path *) lfirst(lc);
    7743                 :         713 :             Path       *path_save = path;
    7744                 :         713 :             List       *pathkey_orderings = NIL;
    7745                 :             : 
    7746                 :             :             /* generate alternative group orderings that might be useful */
    7747                 :         713 :             pathkey_orderings = get_useful_group_keys_orderings(root, path);
    7748                 :             : 
    7749                 :             :             Assert(list_length(pathkey_orderings) > 0);
    7750                 :             : 
    7751                 :             :             /* process all potentially interesting grouping reorderings */
    7752   [ +  -  +  +  :        1426 :             foreach(lc2, pathkey_orderings)
                   +  + ]
    7753                 :             :             {
    7754                 :         713 :                 GroupByOrdering *info = (GroupByOrdering *) lfirst(lc2);
    7755                 :             : 
    7756                 :             :                 /* restore the path (we replace it in the loop) */
    7757                 :         713 :                 path = path_save;
    7758                 :             : 
    7759                 :         713 :                 path = make_ordered_path(root,
    7760                 :             :                                          partially_grouped_rel,
    7761                 :             :                                          path,
    7762                 :             :                                          cheapest_total_path,
    7763                 :             :                                          info->pathkeys,
    7764                 :             :                                          -1.0);
    7765                 :             : 
    7766         [ -  + ]:         713 :                 if (path == NULL)
    7767                 :           0 :                     continue;
    7768                 :             : 
    7769         [ +  + ]:         713 :                 if (parse->hasAggs)
    7770                 :         653 :                     add_path(partially_grouped_rel, (Path *)
    7771                 :         653 :                              create_agg_path(root,
    7772                 :             :                                              partially_grouped_rel,
    7773                 :             :                                              path,
    7774                 :         653 :                                              partially_grouped_rel->reltarget,
    7775                 :         653 :                                              parse->groupClause ? AGG_SORTED : AGG_PLAIN,
    7776                 :             :                                              AGGSPLIT_INITIAL_SERIAL,
    7777                 :             :                                              info->clauses,
    7778                 :             :                                              NIL,
    7779                 :             :                                              agg_partial_costs,
    7780                 :             :                                              dNumPartialGroups));
    7781                 :             :                 else
    7782                 :          60 :                     add_path(partially_grouped_rel, (Path *)
    7783                 :          60 :                              create_group_path(root,
    7784                 :             :                                                partially_grouped_rel,
    7785                 :             :                                                path,
    7786                 :             :                                                info->clauses,
    7787                 :             :                                                NIL,
    7788                 :             :                                                dNumPartialGroups));
    7789                 :             :             }
    7790                 :             :         }
    7791                 :             :     }
    7792                 :             : 
    7793   [ +  -  +  + ]:        3213 :     if (can_sort && cheapest_partial_path != NULL)
    7794                 :             :     {
    7795                 :             :         /* Similar to above logic, but for partial paths. */
    7796   [ +  -  +  +  :        5859 :         foreach(lc, input_rel->partial_pathlist)
                   +  + ]
    7797                 :             :         {
    7798                 :             :             ListCell   *lc2;
    7799                 :        3117 :             Path       *path = (Path *) lfirst(lc);
    7800                 :        3117 :             Path       *path_save = path;
    7801                 :        3117 :             List       *pathkey_orderings = NIL;
    7802                 :             : 
    7803                 :             :             /* generate alternative group orderings that might be useful */
    7804                 :        3117 :             pathkey_orderings = get_useful_group_keys_orderings(root, path);
    7805                 :             : 
    7806                 :             :             Assert(list_length(pathkey_orderings) > 0);
    7807                 :             : 
    7808                 :             :             /* process all potentially interesting grouping reorderings */
    7809   [ +  -  +  +  :        6234 :             foreach(lc2, pathkey_orderings)
                   +  + ]
    7810                 :             :             {
    7811                 :        3117 :                 GroupByOrdering *info = (GroupByOrdering *) lfirst(lc2);
    7812                 :             : 
    7813                 :             : 
    7814                 :             :                 /* restore the path (we replace it in the loop) */
    7815                 :        3117 :                 path = path_save;
    7816                 :             : 
    7817                 :        3117 :                 path = make_ordered_path(root,
    7818                 :             :                                          partially_grouped_rel,
    7819                 :             :                                          path,
    7820                 :             :                                          cheapest_partial_path,
    7821                 :             :                                          info->pathkeys,
    7822                 :             :                                          -1.0);
    7823                 :             : 
    7824         [ +  + ]:        3117 :                 if (path == NULL)
    7825                 :           5 :                     continue;
    7826                 :             : 
    7827         [ +  + ]:        3112 :                 if (parse->hasAggs)
    7828                 :        3013 :                     add_partial_path(partially_grouped_rel, (Path *)
    7829                 :        3013 :                                      create_agg_path(root,
    7830                 :             :                                                      partially_grouped_rel,
    7831                 :             :                                                      path,
    7832                 :        3013 :                                                      partially_grouped_rel->reltarget,
    7833                 :        3013 :                                                      parse->groupClause ? AGG_SORTED : AGG_PLAIN,
    7834                 :             :                                                      AGGSPLIT_INITIAL_SERIAL,
    7835                 :             :                                                      info->clauses,
    7836                 :             :                                                      NIL,
    7837                 :             :                                                      agg_partial_costs,
    7838                 :             :                                                      dNumPartialPartialGroups));
    7839                 :             :                 else
    7840                 :          99 :                     add_partial_path(partially_grouped_rel, (Path *)
    7841                 :          99 :                                      create_group_path(root,
    7842                 :             :                                                        partially_grouped_rel,
    7843                 :             :                                                        path,
    7844                 :             :                                                        info->clauses,
    7845                 :             :                                                        NIL,
    7846                 :             :                                                        dNumPartialPartialGroups));
    7847                 :             :             }
    7848                 :             :         }
    7849                 :             :     }
    7850                 :             : 
    7851                 :             :     /*
    7852                 :             :      * Add a partially-grouped HashAgg Path where possible
    7853                 :             :      */
    7854   [ +  +  +  + ]:        3213 :     if (can_hash && cheapest_total_path != NULL)
    7855                 :             :     {
    7856                 :             :         /* Checked above */
    7857                 :             :         Assert(parse->hasAggs || parse->groupClause);
    7858                 :             : 
    7859                 :         713 :         add_path(partially_grouped_rel, (Path *)
    7860                 :         713 :                  create_agg_path(root,
    7861                 :             :                                  partially_grouped_rel,
    7862                 :             :                                  cheapest_total_path,
    7863                 :         713 :                                  partially_grouped_rel->reltarget,
    7864                 :             :                                  AGG_HASHED,
    7865                 :             :                                  AGGSPLIT_INITIAL_SERIAL,
    7866                 :             :                                  root->processed_groupClause,
    7867                 :             :                                  NIL,
    7868                 :             :                                  agg_partial_costs,
    7869                 :             :                                  dNumPartialGroups));
    7870                 :             :     }
    7871                 :             : 
    7872                 :             :     /*
    7873                 :             :      * Now add a partially-grouped HashAgg partial Path where possible
    7874                 :             :      */
    7875   [ +  +  +  + ]:        3213 :     if (can_hash && cheapest_partial_path != NULL)
    7876                 :             :     {
    7877                 :        1434 :         add_partial_path(partially_grouped_rel, (Path *)
    7878                 :        1434 :                          create_agg_path(root,
    7879                 :             :                                          partially_grouped_rel,
    7880                 :             :                                          cheapest_partial_path,
    7881                 :        1434 :                                          partially_grouped_rel->reltarget,
    7882                 :             :                                          AGG_HASHED,
    7883                 :             :                                          AGGSPLIT_INITIAL_SERIAL,
    7884                 :             :                                          root->processed_groupClause,
    7885                 :             :                                          NIL,
    7886                 :             :                                          agg_partial_costs,
    7887                 :             :                                          dNumPartialPartialGroups));
    7888                 :             :     }
    7889                 :             : 
    7890                 :             :     /*
    7891                 :             :      * Add any partially aggregated paths generated by eager aggregation to
    7892                 :             :      * the new upper relation after applying projection steps as needed.
    7893                 :             :      */
    7894         [ +  + ]:        3213 :     if (eager_agg_rel)
    7895                 :             :     {
    7896                 :             :         /* Add the paths */
    7897   [ +  -  +  +  :        1924 :         foreach(lc, eager_agg_rel->pathlist)
                   +  + ]
    7898                 :             :         {
    7899                 :        1187 :             Path       *path = (Path *) lfirst(lc);
    7900                 :             : 
    7901                 :             :             /* Shouldn't have any parameterized paths anymore */
    7902                 :             :             Assert(path->param_info == NULL);
    7903                 :             : 
    7904                 :        1187 :             path = (Path *) create_projection_path(root,
    7905                 :             :                                                    partially_grouped_rel,
    7906                 :             :                                                    path,
    7907                 :        1187 :                                                    partially_grouped_rel->reltarget);
    7908                 :             : 
    7909                 :        1187 :             add_path(partially_grouped_rel, path);
    7910                 :             :         }
    7911                 :             : 
    7912                 :             :         /*
    7913                 :             :          * Likewise add the partial paths, but only if parallelism is possible
    7914                 :             :          * for partially_grouped_rel.
    7915                 :             :          */
    7916         [ +  + ]:         737 :         if (partially_grouped_rel->consider_parallel)
    7917                 :             :         {
    7918   [ +  +  +  +  :        1700 :             foreach(lc, eager_agg_rel->partial_pathlist)
                   +  + ]
    7919                 :             :             {
    7920                 :        1010 :                 Path       *path = (Path *) lfirst(lc);
    7921                 :             : 
    7922                 :             :                 /* Shouldn't have any parameterized paths anymore */
    7923                 :             :                 Assert(path->param_info == NULL);
    7924                 :             : 
    7925                 :        1010 :                 path = (Path *) create_projection_path(root,
    7926                 :             :                                                        partially_grouped_rel,
    7927                 :             :                                                        path,
    7928                 :        1010 :                                                        partially_grouped_rel->reltarget);
    7929                 :             : 
    7930                 :        1010 :                 add_partial_path(partially_grouped_rel, path);
    7931                 :             :             }
    7932                 :             :         }
    7933                 :             :     }
    7934                 :             : 
    7935                 :             :     /*
    7936                 :             :      * If there is an FDW that's responsible for all baserels of the query,
    7937                 :             :      * let it consider adding partially grouped ForeignPaths.
    7938                 :             :      */
    7939         [ +  + ]:        3213 :     if (partially_grouped_rel->fdwroutine &&
    7940         [ +  - ]:           3 :         partially_grouped_rel->fdwroutine->GetForeignUpperPaths)
    7941                 :             :     {
    7942                 :           3 :         FdwRoutine *fdwroutine = partially_grouped_rel->fdwroutine;
    7943                 :             : 
    7944                 :           3 :         fdwroutine->GetForeignUpperPaths(root,
    7945                 :             :                                          UPPERREL_PARTIAL_GROUP_AGG,
    7946                 :             :                                          input_rel, partially_grouped_rel,
    7947                 :             :                                          extra);
    7948                 :             :     }
    7949                 :             : 
    7950                 :        3213 :     return partially_grouped_rel;
    7951                 :             : }
    7952                 :             : 
    7953                 :             : /*
    7954                 :             :  * make_ordered_path
    7955                 :             :  *      Return a path ordered by 'pathkeys' based on the given 'path'.  May
    7956                 :             :  *      return NULL if it doesn't make sense to generate an ordered path in
    7957                 :             :  *      this case.
    7958                 :             :  */
    7959                 :             : static Path *
    7960                 :       49743 : make_ordered_path(PlannerInfo *root, RelOptInfo *rel, Path *path,
    7961                 :             :                   Path *cheapest_path, List *pathkeys, double limit_tuples)
    7962                 :             : {
    7963                 :             :     bool        is_sorted;
    7964                 :             :     int         presorted_keys;
    7965                 :             : 
    7966                 :       49743 :     is_sorted = pathkeys_count_contained_in(pathkeys,
    7967                 :             :                                             path->pathkeys,
    7968                 :             :                                             &presorted_keys);
    7969                 :             : 
    7970         [ +  + ]:       49743 :     if (!is_sorted)
    7971                 :             :     {
    7972                 :             :         /*
    7973                 :             :          * Try at least sorting the cheapest path and also try incrementally
    7974                 :             :          * sorting any path which is partially sorted already (no need to deal
    7975                 :             :          * with paths which have presorted keys when incremental sort is
    7976                 :             :          * disabled unless it's the cheapest input path).
    7977                 :             :          */
    7978         [ +  + ]:       13316 :         if (path != cheapest_path &&
    7979   [ +  +  +  + ]:        2217 :             (presorted_keys == 0 || !enable_incremental_sort))
    7980                 :        1052 :             return NULL;
    7981                 :             : 
    7982                 :             :         /*
    7983                 :             :          * We've no need to consider both a sort and incremental sort. We'll
    7984                 :             :          * just do a sort if there are no presorted keys and an incremental
    7985                 :             :          * sort when there are presorted keys.
    7986                 :             :          */
    7987   [ +  +  +  + ]:       12264 :         if (presorted_keys == 0 || !enable_incremental_sort)
    7988                 :       10953 :             path = (Path *) create_sort_path(root,
    7989                 :             :                                              rel,
    7990                 :             :                                              path,
    7991                 :             :                                              pathkeys,
    7992                 :             :                                              limit_tuples);
    7993                 :             :         else
    7994                 :        1311 :             path = (Path *) create_incremental_sort_path(root,
    7995                 :             :                                                          rel,
    7996                 :             :                                                          path,
    7997                 :             :                                                          pathkeys,
    7998                 :             :                                                          presorted_keys,
    7999                 :             :                                                          limit_tuples);
    8000                 :             :     }
    8001                 :             : 
    8002                 :       48691 :     return path;
    8003                 :             : }
    8004                 :             : 
    8005                 :             : /*
    8006                 :             :  * Generate Gather and Gather Merge paths for a grouping relation or partial
    8007                 :             :  * grouping relation.
    8008                 :             :  *
    8009                 :             :  * generate_useful_gather_paths does most of the work, but we also consider a
    8010                 :             :  * special case: we could try sorting the data by the group_pathkeys and then
    8011                 :             :  * applying Gather Merge.
    8012                 :             :  *
    8013                 :             :  * NB: This function shouldn't be used for anything other than a grouped or
    8014                 :             :  * partially grouped relation not only because of the fact that it explicitly
    8015                 :             :  * references group_pathkeys but we pass "true" as the third argument to
    8016                 :             :  * generate_useful_gather_paths().
    8017                 :             :  */
    8018                 :             : static void
    8019                 :        2587 : gather_grouping_paths(PlannerInfo *root, RelOptInfo *rel)
    8020                 :             : {
    8021                 :             :     ListCell   *lc;
    8022                 :             :     Path       *cheapest_partial_path;
    8023                 :             :     List       *groupby_pathkeys;
    8024                 :             : 
    8025                 :             :     /*
    8026                 :             :      * This occurs after any partial aggregation has taken place, so trim off
    8027                 :             :      * any pathkeys added for ORDER BY / DISTINCT aggregates.
    8028                 :             :      */
    8029         [ +  + ]:        2587 :     if (list_length(root->group_pathkeys) > root->num_groupby_pathkeys)
    8030                 :          15 :         groupby_pathkeys = list_copy_head(root->group_pathkeys,
    8031                 :             :                                           root->num_groupby_pathkeys);
    8032                 :             :     else
    8033                 :        2572 :         groupby_pathkeys = root->group_pathkeys;
    8034                 :             : 
    8035                 :             :     /* Try Gather for unordered paths and Gather Merge for ordered ones. */
    8036                 :        2587 :     generate_useful_gather_paths(root, rel, true);
    8037                 :             : 
    8038                 :        2587 :     cheapest_partial_path = linitial(rel->partial_pathlist);
    8039                 :             : 
    8040                 :             :     /* XXX Shouldn't this also consider the group-key-reordering? */
    8041   [ +  -  +  +  :        6146 :     foreach(lc, rel->partial_pathlist)
                   +  + ]
    8042                 :             :     {
    8043                 :        3559 :         Path       *path = (Path *) lfirst(lc);
    8044                 :             :         bool        is_sorted;
    8045                 :             :         int         presorted_keys;
    8046                 :             :         double      total_groups;
    8047                 :             : 
    8048                 :        3559 :         is_sorted = pathkeys_count_contained_in(groupby_pathkeys,
    8049                 :             :                                                 path->pathkeys,
    8050                 :             :                                                 &presorted_keys);
    8051                 :             : 
    8052         [ +  + ]:        3559 :         if (is_sorted)
    8053                 :        2326 :             continue;
    8054                 :             : 
    8055                 :             :         /*
    8056                 :             :          * Try at least sorting the cheapest path and also try incrementally
    8057                 :             :          * sorting any path which is partially sorted already (no need to deal
    8058                 :             :          * with paths which have presorted keys when incremental sort is
    8059                 :             :          * disabled unless it's the cheapest input path).
    8060                 :             :          */
    8061         [ -  + ]:        1233 :         if (path != cheapest_partial_path &&
    8062   [ #  #  #  # ]:           0 :             (presorted_keys == 0 || !enable_incremental_sort))
    8063                 :           0 :             continue;
    8064                 :             : 
    8065                 :             :         /*
    8066                 :             :          * We've no need to consider both a sort and incremental sort. We'll
    8067                 :             :          * just do a sort if there are no presorted keys and an incremental
    8068                 :             :          * sort when there are presorted keys.
    8069                 :             :          */
    8070   [ -  +  -  - ]:        1233 :         if (presorted_keys == 0 || !enable_incremental_sort)
    8071                 :        1233 :             path = (Path *) create_sort_path(root, rel, path,
    8072                 :             :                                              groupby_pathkeys,
    8073                 :             :                                              -1.0);
    8074                 :             :         else
    8075                 :           0 :             path = (Path *) create_incremental_sort_path(root,
    8076                 :             :                                                          rel,
    8077                 :             :                                                          path,
    8078                 :             :                                                          groupby_pathkeys,
    8079                 :             :                                                          presorted_keys,
    8080                 :             :                                                          -1.0);
    8081                 :        1233 :         total_groups = compute_gather_rows(path);
    8082                 :             :         path = (Path *)
    8083                 :        1233 :             create_gather_merge_path(root,
    8084                 :             :                                      rel,
    8085                 :             :                                      path,
    8086                 :        1233 :                                      rel->reltarget,
    8087                 :             :                                      groupby_pathkeys,
    8088                 :             :                                      NULL,
    8089                 :             :                                      &total_groups);
    8090                 :             : 
    8091                 :        1233 :         add_path(rel, path);
    8092                 :             :     }
    8093                 :        2587 : }
    8094                 :             : 
    8095                 :             : /*
    8096                 :             :  * can_partial_agg
    8097                 :             :  *
    8098                 :             :  * Determines whether or not partial grouping and/or aggregation is possible.
    8099                 :             :  * Returns true when possible, false otherwise.
    8100                 :             :  */
    8101                 :             : static bool
    8102                 :       34097 : can_partial_agg(PlannerInfo *root)
    8103                 :             : {
    8104                 :       34097 :     Query      *parse = root->parse;
    8105                 :             : 
    8106   [ +  +  -  + ]:       34097 :     if (!parse->hasAggs && parse->groupClause == NIL)
    8107                 :             :     {
    8108                 :             :         /*
    8109                 :             :          * We don't know how to do parallel aggregation unless we have either
    8110                 :             :          * some aggregates or a grouping clause.
    8111                 :             :          */
    8112                 :           0 :         return false;
    8113                 :             :     }
    8114         [ +  + ]:       34097 :     else if (parse->groupingSets)
    8115                 :             :     {
    8116                 :             :         /* We don't know how to do grouping sets in parallel. */
    8117                 :         881 :         return false;
    8118                 :             :     }
    8119   [ +  +  +  + ]:       33216 :     else if (root->hasNonPartialAggs || root->hasNonSerialAggs)
    8120                 :             :     {
    8121                 :             :         /* Insufficient support for partial mode. */
    8122                 :        3055 :         return false;
    8123                 :             :     }
    8124                 :             : 
    8125                 :             :     /* Everything looks good. */
    8126                 :       30161 :     return true;
    8127                 :             : }
    8128                 :             : 
    8129                 :             : /*
    8130                 :             :  * apply_scanjoin_target_to_paths
    8131                 :             :  *
    8132                 :             :  * Adjust the final scan/join relation, and recursively all of its children,
    8133                 :             :  * to generate the final scan/join target.  It would be more correct to model
    8134                 :             :  * this as a separate planning step with a new RelOptInfo at the toplevel and
    8135                 :             :  * for each child relation, but doing it this way is noticeably cheaper.
    8136                 :             :  * Maybe that problem can be solved at some point, but for now we do this.
    8137                 :             :  *
    8138                 :             :  * If tlist_same_exprs is true, then the scan/join target to be applied has
    8139                 :             :  * the same expressions as the existing reltarget, so we need only insert the
    8140                 :             :  * appropriate sortgroupref information.  By avoiding the creation of
    8141                 :             :  * projection paths we save effort both immediately and at plan creation time.
    8142                 :             :  */
    8143                 :             : static void
    8144                 :      410081 : apply_scanjoin_target_to_paths(PlannerInfo *root,
    8145                 :             :                                RelOptInfo *rel,
    8146                 :             :                                List *scanjoin_targets,
    8147                 :             :                                List *scanjoin_targets_contain_srfs,
    8148                 :             :                                bool scanjoin_target_parallel_safe,
    8149                 :             :                                bool tlist_same_exprs)
    8150                 :             : {
    8151   [ +  +  +  +  :      410081 :     bool        rel_is_partitioned = IS_PARTITIONED_REL(rel);
          +  +  +  -  +  
                      + ]
    8152                 :             :     PathTarget *scanjoin_target;
    8153                 :             :     ListCell   *lc;
    8154                 :             : 
    8155                 :             :     /* This recurses, so be paranoid. */
    8156                 :      410081 :     check_stack_depth();
    8157                 :             : 
    8158                 :             :     /*
    8159                 :             :      * If the rel only has Append and MergeAppend paths, we want to drop its
    8160                 :             :      * existing paths and generate new ones.  This function would still be
    8161                 :             :      * correct if we kept the existing paths: we'd modify them to generate the
    8162                 :             :      * correct target above the partitioning Append, and then they'd compete
    8163                 :             :      * on cost with paths generating the target below the Append.  However, in
    8164                 :             :      * our current cost model the latter way is always the same or cheaper
    8165                 :             :      * cost, so modifying the existing paths would just be useless work.
    8166                 :             :      * Moreover, when the cost is the same, varying roundoff errors might
    8167                 :             :      * sometimes allow an existing path to be picked, resulting in undesirable
    8168                 :             :      * cross-platform plan variations.  So we drop old paths and thereby force
    8169                 :             :      * the work to be done below the Append.
    8170                 :             :      *
    8171                 :             :      * However, there are several cases when this optimization is not safe. If
    8172                 :             :      * the rel isn't partitioned, then none of the paths will be Append or
    8173                 :             :      * MergeAppend paths, so we should definitely not do this. If it is
    8174                 :             :      * partitioned but is a joinrel, it may have Append and MergeAppend paths,
    8175                 :             :      * but it can also have join paths that we can't afford to discard.
    8176                 :             :      *
    8177                 :             :      * Some care is needed, because we have to allow
    8178                 :             :      * generate_useful_gather_paths to see the old partial paths in the next
    8179                 :             :      * stanza.  Hence, zap the main pathlist here, then allow
    8180                 :             :      * generate_useful_gather_paths to add path(s) to the main list, and
    8181                 :             :      * finally zap the partial pathlist.
    8182                 :             :      */
    8183   [ +  +  +  +  :      410081 :     if (rel_is_partitioned && IS_SIMPLE_REL(rel))
                   +  + ]
    8184                 :        8747 :         rel->pathlist = NIL;
    8185                 :             : 
    8186                 :             :     /*
    8187                 :             :      * If the scan/join target is not parallel-safe, partial paths cannot
    8188                 :             :      * generate it.
    8189                 :             :      */
    8190         [ +  + ]:      410081 :     if (!scanjoin_target_parallel_safe)
    8191                 :             :     {
    8192                 :             :         /*
    8193                 :             :          * Since we can't generate the final scan/join target in parallel
    8194                 :             :          * workers, this is our last opportunity to use any partial paths that
    8195                 :             :          * exist; so build Gather path(s) that use them and emit whatever the
    8196                 :             :          * current reltarget is.  We don't do this in the case where the
    8197                 :             :          * target is parallel-safe, since we will be able to generate superior
    8198                 :             :          * paths by doing it after the final scan/join target has been
    8199                 :             :          * applied.
    8200                 :             :          */
    8201                 :       53030 :         generate_useful_gather_paths(root, rel, false);
    8202                 :             : 
    8203                 :             :         /* Can't use parallel query above this level. */
    8204                 :       53030 :         rel->partial_pathlist = NIL;
    8205                 :       53030 :         rel->consider_parallel = false;
    8206                 :             :     }
    8207                 :             : 
    8208                 :             :     /* Finish dropping old paths for a partitioned rel, per comment above */
    8209   [ +  +  +  +  :      410081 :     if (rel_is_partitioned && IS_SIMPLE_REL(rel))
                   +  + ]
    8210                 :        8747 :         rel->partial_pathlist = NIL;
    8211                 :             : 
    8212                 :             :     /* Extract SRF-free scan/join target. */
    8213                 :      410081 :     scanjoin_target = linitial_node(PathTarget, scanjoin_targets);
    8214                 :             : 
    8215                 :             :     /*
    8216                 :             :      * Apply the SRF-free scan/join target to each existing path.
    8217                 :             :      *
    8218                 :             :      * If the tlist exprs are the same, we can just inject the sortgroupref
    8219                 :             :      * information into the existing pathtargets.  Otherwise, replace each
    8220                 :             :      * path with a projection path that generates the SRF-free scan/join
    8221                 :             :      * target.  This can't change the ordering of paths within rel->pathlist,
    8222                 :             :      * so we just modify the list in place.
    8223                 :             :      */
    8224   [ +  +  +  +  :      855617 :     foreach(lc, rel->pathlist)
                   +  + ]
    8225                 :             :     {
    8226                 :      445536 :         Path       *subpath = (Path *) lfirst(lc);
    8227                 :             : 
    8228                 :             :         /* Shouldn't have any parameterized paths anymore */
    8229                 :             :         Assert(subpath->param_info == NULL);
    8230                 :             : 
    8231         [ +  + ]:      445536 :         if (tlist_same_exprs)
    8232                 :      160822 :             subpath->pathtarget->sortgrouprefs =
    8233                 :      160822 :                 scanjoin_target->sortgrouprefs;
    8234                 :             :         else
    8235                 :             :         {
    8236                 :             :             Path       *newpath;
    8237                 :             : 
    8238                 :      284714 :             newpath = (Path *) create_projection_path(root, rel, subpath,
    8239                 :             :                                                       scanjoin_target);
    8240                 :      284714 :             lfirst(lc) = newpath;
    8241                 :             :         }
    8242                 :             :     }
    8243                 :             : 
    8244                 :             :     /* Likewise adjust the targets for any partial paths. */
    8245   [ +  +  +  +  :      430332 :     foreach(lc, rel->partial_pathlist)
                   +  + ]
    8246                 :             :     {
    8247                 :       20251 :         Path       *subpath = (Path *) lfirst(lc);
    8248                 :             : 
    8249                 :             :         /* Shouldn't have any parameterized paths anymore */
    8250                 :             :         Assert(subpath->param_info == NULL);
    8251                 :             : 
    8252         [ +  + ]:       20251 :         if (tlist_same_exprs)
    8253                 :       16118 :             subpath->pathtarget->sortgrouprefs =
    8254                 :       16118 :                 scanjoin_target->sortgrouprefs;
    8255                 :             :         else
    8256                 :             :         {
    8257                 :             :             Path       *newpath;
    8258                 :             : 
    8259                 :        4133 :             newpath = (Path *) create_projection_path(root, rel, subpath,
    8260                 :             :                                                       scanjoin_target);
    8261                 :        4133 :             lfirst(lc) = newpath;
    8262                 :             :         }
    8263                 :             :     }
    8264                 :             : 
    8265                 :             :     /*
    8266                 :             :      * Now, if final scan/join target contains SRFs, insert ProjectSetPath(s)
    8267                 :             :      * atop each existing path.  (Note that this function doesn't look at the
    8268                 :             :      * cheapest-path fields, which is a good thing because they're bogus right
    8269                 :             :      * now.)
    8270                 :             :      */
    8271         [ +  + ]:      410081 :     if (root->parse->hasTargetSRFs)
    8272                 :       10227 :         adjust_paths_for_srfs(root, rel,
    8273                 :             :                               scanjoin_targets,
    8274                 :             :                               scanjoin_targets_contain_srfs);
    8275                 :             : 
    8276                 :             :     /*
    8277                 :             :      * Update the rel's target to be the final (with SRFs) scan/join target.
    8278                 :             :      * This now matches the actual output of all the paths, and we might get
    8279                 :             :      * confused in createplan.c if they don't agree.  We must do this now so
    8280                 :             :      * that any append paths made in the next part will use the correct
    8281                 :             :      * pathtarget (cf. create_append_path).
    8282                 :             :      *
    8283                 :             :      * Note that this is also necessary if GetForeignUpperPaths() gets called
    8284                 :             :      * on the final scan/join relation or on any of its children, since the
    8285                 :             :      * FDW might look at the rel's target to create ForeignPaths.
    8286                 :             :      */
    8287                 :      410081 :     rel->reltarget = llast_node(PathTarget, scanjoin_targets);
    8288                 :             : 
    8289                 :             :     /*
    8290                 :             :      * If the relation is partitioned, recursively apply the scan/join target
    8291                 :             :      * to all partitions, and generate brand-new Append paths in which the
    8292                 :             :      * scan/join target is computed below the Append rather than above it.
    8293                 :             :      * Since Append is not projection-capable, that might save a separate
    8294                 :             :      * Result node, and it also is important for partitionwise aggregate.
    8295                 :             :      */
    8296         [ +  + ]:      410081 :     if (rel_is_partitioned)
    8297                 :             :     {
    8298                 :       10050 :         List       *live_children = NIL;
    8299                 :             :         int         i;
    8300                 :             : 
    8301                 :             :         /* Adjust each partition. */
    8302                 :       10050 :         i = -1;
    8303         [ +  + ]:       30167 :         while ((i = bms_next_member(rel->live_parts, i)) >= 0)
    8304                 :             :         {
    8305                 :       20117 :             RelOptInfo *child_rel = rel->part_rels[i];
    8306                 :             :             AppendRelInfo **appinfos;
    8307                 :             :             int         nappinfos;
    8308                 :       20117 :             List       *child_scanjoin_targets = NIL;
    8309                 :             : 
    8310                 :             :             Assert(child_rel != NULL);
    8311                 :             : 
    8312                 :             :             /* Dummy children can be ignored. */
    8313         [ +  + ]:       20117 :             if (IS_DUMMY_REL(child_rel))
    8314                 :          40 :                 continue;
    8315                 :             : 
    8316                 :             :             /* Translate scan/join targets for this child. */
    8317                 :       20077 :             appinfos = find_appinfos_by_relids(root, child_rel->relids,
    8318                 :             :                                                &nappinfos);
    8319   [ +  -  +  +  :       40154 :             foreach(lc, scanjoin_targets)
                   +  + ]
    8320                 :             :             {
    8321                 :       20077 :                 PathTarget *target = lfirst_node(PathTarget, lc);
    8322                 :             : 
    8323                 :       20077 :                 target = copy_pathtarget(target);
    8324                 :       20077 :                 target->exprs = (List *)
    8325                 :       20077 :                     adjust_appendrel_attrs(root,
    8326                 :       20077 :                                            (Node *) target->exprs,
    8327                 :             :                                            nappinfos, appinfos);
    8328                 :       20077 :                 child_scanjoin_targets = lappend(child_scanjoin_targets,
    8329                 :             :                                                  target);
    8330                 :             :             }
    8331                 :       20077 :             pfree(appinfos);
    8332                 :             : 
    8333                 :             :             /* Recursion does the real work. */
    8334                 :       20077 :             apply_scanjoin_target_to_paths(root, child_rel,
    8335                 :             :                                            child_scanjoin_targets,
    8336                 :             :                                            scanjoin_targets_contain_srfs,
    8337                 :             :                                            scanjoin_target_parallel_safe,
    8338                 :             :                                            tlist_same_exprs);
    8339                 :             : 
    8340                 :             :             /* Save non-dummy children for Append paths. */
    8341         [ +  - ]:       20077 :             if (!IS_DUMMY_REL(child_rel))
    8342                 :       20077 :                 live_children = lappend(live_children, child_rel);
    8343                 :             :         }
    8344                 :             : 
    8345                 :             :         /* Build new paths for this relation by appending child paths. */
    8346                 :       10050 :         add_paths_to_append_rel(root, rel, live_children);
    8347                 :             :     }
    8348                 :             : 
    8349                 :             :     /*
    8350                 :             :      * Consider generating Gather or Gather Merge paths.  We must only do this
    8351                 :             :      * if the relation is parallel safe, and we don't do it for child rels to
    8352                 :             :      * avoid creating multiple Gather nodes within the same plan. We must do
    8353                 :             :      * this after all paths have been generated and before set_cheapest, since
    8354                 :             :      * one of the generated paths may turn out to be the cheapest one.
    8355                 :             :      */
    8356   [ +  +  +  +  :      410081 :     if (rel->consider_parallel && !IS_OTHER_REL(rel))
             +  +  +  - ]
    8357                 :      136754 :         generate_useful_gather_paths(root, rel, false);
    8358                 :             : 
    8359                 :             :     /*
    8360                 :             :      * Reassess which paths are the cheapest, now that we've potentially added
    8361                 :             :      * new Gather (or Gather Merge) and/or Append (or MergeAppend) paths to
    8362                 :             :      * this relation.
    8363                 :             :      */
    8364                 :      410081 :     set_cheapest(rel);
    8365                 :      410081 : }
    8366                 :             : 
    8367                 :             : /*
    8368                 :             :  * create_partitionwise_grouping_paths
    8369                 :             :  *
    8370                 :             :  * If the partition keys of input relation are part of the GROUP BY clause, all
    8371                 :             :  * the rows belonging to a given group come from a single partition.  This
    8372                 :             :  * allows aggregation/grouping over a partitioned relation to be broken down
    8373                 :             :  * into aggregation/grouping on each partition.  This should be no worse, and
    8374                 :             :  * often better, than the normal approach.
    8375                 :             :  *
    8376                 :             :  * However, if the GROUP BY clause does not contain all the partition keys,
    8377                 :             :  * rows from a given group may be spread across multiple partitions. In that
    8378                 :             :  * case, we perform partial aggregation for each group, append the results,
    8379                 :             :  * and then finalize aggregation.  This is less certain to win than the
    8380                 :             :  * previous case.  It may win if the PartialAggregate stage greatly reduces
    8381                 :             :  * the number of groups, because fewer rows will pass through the Append node.
    8382                 :             :  * It may lose if we have lots of small groups.
    8383                 :             :  */
    8384                 :             : static void
    8385                 :         685 : create_partitionwise_grouping_paths(PlannerInfo *root,
    8386                 :             :                                     RelOptInfo *input_rel,
    8387                 :             :                                     RelOptInfo *grouped_rel,
    8388                 :             :                                     RelOptInfo *partially_grouped_rel,
    8389                 :             :                                     const AggClauseCosts *agg_costs,
    8390                 :             :                                     grouping_sets_data *gd,
    8391                 :             :                                     PartitionwiseAggregateType patype,
    8392                 :             :                                     GroupPathExtraData *extra)
    8393                 :             : {
    8394                 :         685 :     List       *grouped_live_children = NIL;
    8395                 :         685 :     List       *partially_grouped_live_children = NIL;
    8396                 :         685 :     PathTarget *target = grouped_rel->reltarget;
    8397                 :         685 :     bool        partial_grouping_valid = true;
    8398                 :             :     int         i;
    8399                 :             : 
    8400                 :             :     Assert(patype != PARTITIONWISE_AGGREGATE_NONE);
    8401                 :             :     Assert(patype != PARTITIONWISE_AGGREGATE_PARTIAL ||
    8402                 :             :            partially_grouped_rel != NULL);
    8403                 :             : 
    8404                 :             :     /* Add paths for partitionwise aggregation/grouping. */
    8405                 :         685 :     i = -1;
    8406         [ +  + ]:        2480 :     while ((i = bms_next_member(input_rel->live_parts, i)) >= 0)
    8407                 :             :     {
    8408                 :        1795 :         RelOptInfo *child_input_rel = input_rel->part_rels[i];
    8409                 :             :         PathTarget *child_target;
    8410                 :             :         AppendRelInfo **appinfos;
    8411                 :             :         int         nappinfos;
    8412                 :             :         GroupPathExtraData child_extra;
    8413                 :             :         RelOptInfo *child_grouped_rel;
    8414                 :             :         RelOptInfo *child_partially_grouped_rel;
    8415                 :             : 
    8416                 :             :         Assert(child_input_rel != NULL);
    8417                 :             : 
    8418                 :             :         /* Dummy children can be ignored. */
    8419         [ -  + ]:        1795 :         if (IS_DUMMY_REL(child_input_rel))
    8420                 :           0 :             continue;
    8421                 :             : 
    8422                 :        1795 :         child_target = copy_pathtarget(target);
    8423                 :             : 
    8424                 :             :         /*
    8425                 :             :          * Copy the given "extra" structure as is and then override the
    8426                 :             :          * members specific to this child.
    8427                 :             :          */
    8428                 :        1795 :         memcpy(&child_extra, extra, sizeof(child_extra));
    8429                 :             : 
    8430                 :        1795 :         appinfos = find_appinfos_by_relids(root, child_input_rel->relids,
    8431                 :             :                                            &nappinfos);
    8432                 :             : 
    8433                 :        1795 :         child_target->exprs = (List *)
    8434                 :        1795 :             adjust_appendrel_attrs(root,
    8435                 :        1795 :                                    (Node *) target->exprs,
    8436                 :             :                                    nappinfos, appinfos);
    8437                 :             : 
    8438                 :             :         /* Translate havingQual and targetList. */
    8439                 :        1795 :         child_extra.havingQual = (Node *)
    8440                 :             :             adjust_appendrel_attrs(root,
    8441                 :             :                                    extra->havingQual,
    8442                 :             :                                    nappinfos, appinfos);
    8443                 :        1795 :         child_extra.targetList = (List *)
    8444                 :        1795 :             adjust_appendrel_attrs(root,
    8445                 :        1795 :                                    (Node *) extra->targetList,
    8446                 :             :                                    nappinfos, appinfos);
    8447                 :             : 
    8448                 :             :         /*
    8449                 :             :          * extra->patype was the value computed for our parent rel; patype is
    8450                 :             :          * the value for this relation.  For the child, our value is its
    8451                 :             :          * parent rel's value.
    8452                 :             :          */
    8453                 :        1795 :         child_extra.patype = patype;
    8454                 :             : 
    8455                 :             :         /*
    8456                 :             :          * Create grouping relation to hold fully aggregated grouping and/or
    8457                 :             :          * aggregation paths for the child.
    8458                 :             :          */
    8459                 :        1795 :         child_grouped_rel = make_grouping_rel(root, child_input_rel,
    8460                 :             :                                               child_target,
    8461                 :        1795 :                                               extra->target_parallel_safe,
    8462                 :             :                                               child_extra.havingQual);
    8463                 :             : 
    8464                 :             :         /* Create grouping paths for this child relation. */
    8465                 :        1795 :         create_ordinary_grouping_paths(root, child_input_rel,
    8466                 :             :                                        child_grouped_rel,
    8467                 :             :                                        agg_costs, gd, &child_extra,
    8468                 :             :                                        &child_partially_grouped_rel);
    8469                 :             : 
    8470         [ +  + ]:        1795 :         if (child_partially_grouped_rel)
    8471                 :             :         {
    8472                 :             :             partially_grouped_live_children =
    8473                 :        1283 :                 lappend(partially_grouped_live_children,
    8474                 :             :                         child_partially_grouped_rel);
    8475                 :             :         }
    8476                 :             :         else
    8477                 :         512 :             partial_grouping_valid = false;
    8478                 :             : 
    8479         [ +  + ]:        1795 :         if (patype == PARTITIONWISE_AGGREGATE_FULL)
    8480                 :             :         {
    8481                 :        1082 :             set_cheapest(child_grouped_rel);
    8482                 :        1082 :             grouped_live_children = lappend(grouped_live_children,
    8483                 :             :                                             child_grouped_rel);
    8484                 :             :         }
    8485                 :             : 
    8486                 :        1795 :         pfree(appinfos);
    8487                 :             :     }
    8488                 :             : 
    8489                 :             :     /*
    8490                 :             :      * Try to create append paths for partially grouped children. For full
    8491                 :             :      * partitionwise aggregation, we might have paths in the partial_pathlist
    8492                 :             :      * if parallel aggregation is possible.  For partial partitionwise
    8493                 :             :      * aggregation, we may have paths in both pathlist and partial_pathlist.
    8494                 :             :      *
    8495                 :             :      * NB: We must have a partially grouped path for every child in order to
    8496                 :             :      * generate a partially grouped path for this relation.
    8497                 :             :      */
    8498   [ +  +  +  + ]:         685 :     if (partially_grouped_rel && partial_grouping_valid)
    8499                 :             :     {
    8500                 :             :         Assert(partially_grouped_live_children != NIL);
    8501                 :             : 
    8502                 :         501 :         add_paths_to_append_rel(root, partially_grouped_rel,
    8503                 :             :                                 partially_grouped_live_children);
    8504                 :             :     }
    8505                 :             : 
    8506                 :             :     /* If possible, create append paths for fully grouped children. */
    8507         [ +  + ]:         685 :     if (patype == PARTITIONWISE_AGGREGATE_FULL)
    8508                 :             :     {
    8509                 :             :         Assert(grouped_live_children != NIL);
    8510                 :             : 
    8511                 :         404 :         add_paths_to_append_rel(root, grouped_rel, grouped_live_children);
    8512                 :             :     }
    8513                 :         685 : }
    8514                 :             : 
    8515                 :             : /*
    8516                 :             :  * group_by_has_partkey
    8517                 :             :  *
    8518                 :             :  * Returns true if all the partition keys of the given relation are part of
    8519                 :             :  * the GROUP BY clauses, including having matching collation, false otherwise.
    8520                 :             :  */
    8521                 :             : static bool
    8522                 :         640 : group_by_has_partkey(RelOptInfo *input_rel,
    8523                 :             :                      List *targetList,
    8524                 :             :                      List *groupClause)
    8525                 :             : {
    8526                 :         640 :     List       *groupexprs = get_sortgrouplist_exprs(groupClause, targetList);
    8527                 :         640 :     int         cnt = 0;
    8528                 :             :     int         partnatts;
    8529                 :             : 
    8530                 :             :     /* Input relation should be partitioned. */
    8531                 :             :     Assert(input_rel->part_scheme);
    8532                 :             : 
    8533                 :             :     /* Rule out early, if there are no partition keys present. */
    8534         [ -  + ]:         640 :     if (!input_rel->partexprs)
    8535                 :           0 :         return false;
    8536                 :             : 
    8537                 :         640 :     partnatts = input_rel->part_scheme->partnatts;
    8538                 :             : 
    8539         [ +  + ]:        1074 :     for (cnt = 0; cnt < partnatts; cnt++)
    8540                 :             :     {
    8541                 :         670 :         List       *partexprs = input_rel->partexprs[cnt];
    8542                 :             :         ListCell   *lc;
    8543                 :         670 :         bool        found = false;
    8544                 :             : 
    8545   [ +  +  +  +  :        1001 :         foreach(lc, partexprs)
                   +  + ]
    8546                 :             :         {
    8547                 :             :             ListCell   *lg;
    8548                 :         775 :             Expr       *partexpr = lfirst(lc);
    8549                 :         775 :             Oid         partcoll = input_rel->part_scheme->partcollation[cnt];
    8550                 :             : 
    8551   [ +  -  +  +  :        1206 :             foreach(lg, groupexprs)
                   +  + ]
    8552                 :             :             {
    8553                 :         875 :                 Expr       *groupexpr = lfirst(lg);
    8554                 :         875 :                 Oid         groupcoll = exprCollation((Node *) groupexpr);
    8555                 :             : 
    8556                 :             :                 /*
    8557                 :             :                  * Note: we can assume there is at most one RelabelType node;
    8558                 :             :                  * eval_const_expressions() will have simplified if more than
    8559                 :             :                  * one.
    8560                 :             :                  */
    8561         [ +  + ]:         875 :                 if (IsA(groupexpr, RelabelType))
    8562                 :          20 :                     groupexpr = ((RelabelType *) groupexpr)->arg;
    8563                 :             : 
    8564         [ +  + ]:         875 :                 if (equal(groupexpr, partexpr))
    8565                 :             :                 {
    8566                 :             :                     /*
    8567                 :             :                      * Reject a match if the grouping collation does not match
    8568                 :             :                      * the partitioning collation.
    8569                 :             :                      */
    8570   [ +  +  +  -  :         444 :                     if (OidIsValid(partcoll) && OidIsValid(groupcoll) &&
                   +  + ]
    8571                 :             :                         partcoll != groupcoll)
    8572                 :          10 :                         return false;
    8573                 :             : 
    8574                 :         434 :                     found = true;
    8575                 :         434 :                     break;
    8576                 :             :                 }
    8577                 :             :             }
    8578                 :             : 
    8579         [ +  + ]:         765 :             if (found)
    8580                 :         434 :                 break;
    8581                 :             :         }
    8582                 :             : 
    8583                 :             :         /*
    8584                 :             :          * If none of the partition key expressions match with any of the
    8585                 :             :          * GROUP BY expression, return false.
    8586                 :             :          */
    8587         [ +  + ]:         660 :         if (!found)
    8588                 :         226 :             return false;
    8589                 :             :     }
    8590                 :             : 
    8591                 :         404 :     return true;
    8592                 :             : }
    8593                 :             : 
    8594                 :             : /*
    8595                 :             :  * generate_setop_child_grouplist
    8596                 :             :  *      Build a SortGroupClause list defining the sort/grouping properties
    8597                 :             :  *      of the child of a set operation.
    8598                 :             :  *
    8599                 :             :  * This is similar to generate_setop_grouplist() but differs as the setop
    8600                 :             :  * child query's targetlist entries may already have a tleSortGroupRef
    8601                 :             :  * assigned for other purposes, such as GROUP BYs.  Here we keep the
    8602                 :             :  * SortGroupClause list in the same order as 'op' groupClauses and just adjust
    8603                 :             :  * the tleSortGroupRef to reference the TargetEntry's 'ressortgroupref'.  If
    8604                 :             :  * any of the columns in the targetlist don't match to the setop's colTypes
    8605                 :             :  * then we return an empty list.  This may leave some TLEs with unreferenced
    8606                 :             :  * ressortgroupref markings, but that's harmless.
    8607                 :             :  */
    8608                 :             : static List *
    8609                 :       10734 : generate_setop_child_grouplist(SetOperationStmt *op, List *targetlist)
    8610                 :             : {
    8611                 :       10734 :     List       *grouplist = copyObject(op->groupClauses);
    8612                 :             :     ListCell   *lg;
    8613                 :             :     ListCell   *lt;
    8614                 :             :     ListCell   *ct;
    8615                 :             : 
    8616                 :       10734 :     lg = list_head(grouplist);
    8617                 :       10734 :     ct = list_head(op->colTypes);
    8618   [ +  +  +  +  :       41363 :     foreach(lt, targetlist)
                   +  + ]
    8619                 :             :     {
    8620                 :       30870 :         TargetEntry *tle = (TargetEntry *) lfirst(lt);
    8621                 :             :         SortGroupClause *sgc;
    8622                 :             :         Oid         coltype;
    8623                 :             : 
    8624                 :             :         /* resjunk columns could have sortgrouprefs.  Leave these alone */
    8625         [ -  + ]:       30870 :         if (tle->resjunk)
    8626                 :           0 :             continue;
    8627                 :             : 
    8628                 :             :         /*
    8629                 :             :          * We expect every non-resjunk target to have a SortGroupClause and
    8630                 :             :          * colTypes.
    8631                 :             :          */
    8632                 :             :         Assert(lg != NULL);
    8633                 :             :         Assert(ct != NULL);
    8634                 :       30870 :         sgc = (SortGroupClause *) lfirst(lg);
    8635                 :       30870 :         coltype = lfirst_oid(ct);
    8636                 :             : 
    8637                 :             :         /* reject if target type isn't the same as the setop target type */
    8638         [ +  + ]:       30870 :         if (coltype != exprType((Node *) tle->expr))
    8639                 :         241 :             return NIL;
    8640                 :             : 
    8641                 :       30629 :         lg = lnext(grouplist, lg);
    8642                 :       30629 :         ct = lnext(op->colTypes, ct);
    8643                 :             : 
    8644                 :             :         /* assign a tleSortGroupRef, or reuse the existing one */
    8645                 :       30629 :         sgc->tleSortGroupRef = assignSortGroupRef(tle, targetlist);
    8646                 :             :     }
    8647                 :             : 
    8648                 :             :     Assert(lg == NULL);
    8649                 :             :     Assert(ct == NULL);
    8650                 :             : 
    8651                 :       10493 :     return grouplist;
    8652                 :             : }
    8653                 :             : 
    8654                 :             : /*
    8655                 :             :  * create_unique_paths
    8656                 :             :  *    Build a new RelOptInfo containing Paths that represent elimination of
    8657                 :             :  *    distinct rows from the input data.  Distinct-ness is defined according to
    8658                 :             :  *    the needs of the semijoin represented by sjinfo.  If it is not possible
    8659                 :             :  *    to identify how to make the data unique, NULL is returned.
    8660                 :             :  *
    8661                 :             :  * If used at all, this is likely to be called repeatedly on the same rel,
    8662                 :             :  * so we cache the result.
    8663                 :             :  */
    8664                 :             : RelOptInfo *
    8665                 :        6964 : create_unique_paths(PlannerInfo *root, RelOptInfo *rel, SpecialJoinInfo *sjinfo)
    8666                 :             : {
    8667                 :             :     RelOptInfo *unique_rel;
    8668                 :        6964 :     List       *sortPathkeys = NIL;
    8669                 :        6964 :     List       *groupClause = NIL;
    8670                 :             :     MemoryContext oldcontext;
    8671                 :             : 
    8672                 :             :     /* Caller made a mistake if SpecialJoinInfo is the wrong one */
    8673                 :             :     Assert(sjinfo->jointype == JOIN_SEMI);
    8674                 :             :     Assert(bms_equal(rel->relids, sjinfo->syn_righthand));
    8675                 :             : 
    8676                 :             :     /* If result already cached, return it */
    8677         [ +  + ]:        6964 :     if (rel->unique_rel)
    8678                 :        1206 :         return rel->unique_rel;
    8679                 :             : 
    8680                 :             :     /* If it's not possible to unique-ify, return NULL */
    8681   [ +  +  +  - ]:        5758 :     if (!(sjinfo->semi_can_btree || sjinfo->semi_can_hash))
    8682                 :         104 :         return NULL;
    8683                 :             : 
    8684                 :             :     /*
    8685                 :             :      * Punt if this is a child relation and we failed to build a unique-ified
    8686                 :             :      * relation for its parent.  This can happen if all the RHS columns were
    8687                 :             :      * found to be equated to constants when unique-ifying the parent table,
    8688                 :             :      * leaving no columns to unique-ify.
    8689                 :             :      */
    8690   [ +  +  +  +  :        5654 :     if (IS_OTHER_REL(rel) && rel->top_parent->unique_rel == NULL)
             -  +  +  + ]
    8691                 :          10 :         return NULL;
    8692                 :             : 
    8693                 :             :     /*
    8694                 :             :      * When called during GEQO join planning, we are in a short-lived memory
    8695                 :             :      * context.  We must make sure that the unique rel and any subsidiary data
    8696                 :             :      * structures created for a baserel survive the GEQO cycle, else the
    8697                 :             :      * baserel is trashed for future GEQO cycles.  On the other hand, when we
    8698                 :             :      * are creating those for a joinrel during GEQO, we don't want them to
    8699                 :             :      * clutter the main planning context.  Upshot is that the best solution is
    8700                 :             :      * to explicitly allocate memory in the same context the given RelOptInfo
    8701                 :             :      * is in.
    8702                 :             :      */
    8703                 :        5644 :     oldcontext = MemoryContextSwitchTo(GetMemoryChunkContext(rel));
    8704                 :             : 
    8705                 :        5644 :     unique_rel = makeNode(RelOptInfo);
    8706                 :        5644 :     memcpy(unique_rel, rel, sizeof(RelOptInfo));
    8707                 :             : 
    8708                 :             :     /*
    8709                 :             :      * clear path info
    8710                 :             :      */
    8711                 :        5644 :     unique_rel->pathlist = NIL;
    8712                 :        5644 :     unique_rel->ppilist = NIL;
    8713                 :        5644 :     unique_rel->partial_pathlist = NIL;
    8714                 :        5644 :     unique_rel->cheapest_startup_path = NULL;
    8715                 :        5644 :     unique_rel->cheapest_total_path = NULL;
    8716                 :        5644 :     unique_rel->cheapest_parameterized_paths = NIL;
    8717                 :             : 
    8718                 :             :     /*
    8719                 :             :      * Build the target list for the unique rel.  We also build the pathkeys
    8720                 :             :      * that represent the ordering requirements for the sort-based
    8721                 :             :      * implementation, and the list of SortGroupClause nodes that represent
    8722                 :             :      * the columns to be grouped on for the hash-based implementation.
    8723                 :             :      *
    8724                 :             :      * For a child rel, we can construct these fields from those of its
    8725                 :             :      * parent.
    8726                 :             :      */
    8727   [ +  +  +  +  :        5644 :     if (IS_OTHER_REL(rel))
                   -  + ]
    8728                 :         360 :     {
    8729                 :             :         PathTarget *child_unique_target;
    8730                 :             :         PathTarget *parent_unique_target;
    8731                 :             : 
    8732                 :         360 :         parent_unique_target = rel->top_parent->unique_rel->reltarget;
    8733                 :             : 
    8734                 :         360 :         child_unique_target = copy_pathtarget(parent_unique_target);
    8735                 :             : 
    8736                 :             :         /* Translate the target expressions */
    8737                 :         360 :         child_unique_target->exprs = (List *)
    8738                 :         360 :             adjust_appendrel_attrs_multilevel(root,
    8739                 :         360 :                                               (Node *) parent_unique_target->exprs,
    8740                 :             :                                               rel,
    8741                 :         360 :                                               rel->top_parent);
    8742                 :             : 
    8743                 :         360 :         unique_rel->reltarget = child_unique_target;
    8744                 :             : 
    8745                 :         360 :         sortPathkeys = rel->top_parent->unique_pathkeys;
    8746                 :         360 :         groupClause = rel->top_parent->unique_groupclause;
    8747                 :             :     }
    8748                 :             :     else
    8749                 :             :     {
    8750                 :             :         List       *newtlist;
    8751                 :             :         int         nextresno;
    8752                 :        5284 :         List       *sortList = NIL;
    8753                 :             :         ListCell   *lc1;
    8754                 :             :         ListCell   *lc2;
    8755                 :             : 
    8756                 :             :         /*
    8757                 :             :          * The values we are supposed to unique-ify may be expressions in the
    8758                 :             :          * variables of the input rel's targetlist.  We have to add any such
    8759                 :             :          * expressions to the unique rel's targetlist.
    8760                 :             :          *
    8761                 :             :          * To complicate matters, some of the values to be unique-ified may be
    8762                 :             :          * known redundant by the EquivalenceClass machinery (e.g., because
    8763                 :             :          * they have been equated to constants).  There is no need to compare
    8764                 :             :          * such values during unique-ification, and indeed we had better not
    8765                 :             :          * try because the Vars involved may not have propagated as high as
    8766                 :             :          * the semijoin's level.  We use make_pathkeys_for_sortclauses to
    8767                 :             :          * detect such cases, which is a tad inefficient but it doesn't seem
    8768                 :             :          * worth building specialized infrastructure for this.
    8769                 :             :          */
    8770                 :        5284 :         newtlist = make_tlist_from_pathtarget(rel->reltarget);
    8771                 :        5284 :         nextresno = list_length(newtlist) + 1;
    8772                 :             : 
    8773   [ +  -  +  +  :       10769 :         forboth(lc1, sjinfo->semi_rhs_exprs, lc2, sjinfo->semi_operators)
          +  -  +  +  +  
             +  +  -  +  
                      + ]
    8774                 :             :         {
    8775                 :        5485 :             Expr       *uniqexpr = lfirst(lc1);
    8776                 :        5485 :             Oid         in_oper = lfirst_oid(lc2);
    8777                 :             :             Oid         sortop;
    8778                 :             :             TargetEntry *tle;
    8779                 :        5485 :             bool        made_tle = false;
    8780                 :             : 
    8781                 :        5485 :             tle = tlist_member(uniqexpr, newtlist);
    8782         [ +  + ]:        5485 :             if (!tle)
    8783                 :             :             {
    8784                 :        2772 :                 tle = makeTargetEntry(uniqexpr,
    8785                 :             :                                       nextresno,
    8786                 :             :                                       NULL,
    8787                 :             :                                       false);
    8788                 :        2772 :                 newtlist = lappend(newtlist, tle);
    8789                 :        2772 :                 nextresno++;
    8790                 :        2772 :                 made_tle = true;
    8791                 :             :             }
    8792                 :             : 
    8793                 :             :             /*
    8794                 :             :              * Try to build an ORDER BY list to sort the input compatibly.  We
    8795                 :             :              * do this for each sortable clause even when the clauses are not
    8796                 :             :              * all sortable, so that we can detect clauses that are redundant
    8797                 :             :              * according to the pathkey machinery.
    8798                 :             :              */
    8799                 :        5485 :             sortop = get_ordering_op_for_equality_op(in_oper, false);
    8800         [ +  - ]:        5485 :             if (OidIsValid(sortop))
    8801                 :             :             {
    8802                 :             :                 Oid         eqop;
    8803                 :             :                 SortGroupClause *sortcl;
    8804                 :             : 
    8805                 :             :                 /*
    8806                 :             :                  * The Unique node will need equality operators.  Normally
    8807                 :             :                  * these are the same as the IN clause operators, but if those
    8808                 :             :                  * are cross-type operators then the equality operators are
    8809                 :             :                  * the ones for the IN clause operators' RHS datatype.
    8810                 :             :                  */
    8811                 :        5485 :                 eqop = get_equality_op_for_ordering_op(sortop, NULL);
    8812         [ -  + ]:        5485 :                 if (!OidIsValid(eqop))  /* shouldn't happen */
    8813         [ #  # ]:           0 :                     elog(ERROR, "could not find equality operator for ordering operator %u",
    8814                 :             :                          sortop);
    8815                 :             : 
    8816                 :        5485 :                 sortcl = makeNode(SortGroupClause);
    8817                 :        5485 :                 sortcl->tleSortGroupRef = assignSortGroupRef(tle, newtlist);
    8818                 :        5485 :                 sortcl->eqop = eqop;
    8819                 :        5485 :                 sortcl->sortop = sortop;
    8820                 :        5485 :                 sortcl->reverse_sort = false;
    8821                 :        5485 :                 sortcl->nulls_first = false;
    8822                 :        5485 :                 sortcl->hashable = false;    /* no need to make this accurate */
    8823                 :        5485 :                 sortList = lappend(sortList, sortcl);
    8824                 :             : 
    8825                 :             :                 /*
    8826                 :             :                  * At each step, convert the SortGroupClause list to pathkey
    8827                 :             :                  * form.  If the just-added SortGroupClause is redundant, the
    8828                 :             :                  * result will be shorter than the SortGroupClause list.
    8829                 :             :                  */
    8830                 :        5485 :                 sortPathkeys = make_pathkeys_for_sortclauses(root, sortList,
    8831                 :             :                                                              newtlist);
    8832         [ +  + ]:        5485 :                 if (list_length(sortPathkeys) != list_length(sortList))
    8833                 :             :                 {
    8834                 :             :                     /* Drop the redundant SortGroupClause */
    8835                 :        1710 :                     sortList = list_delete_last(sortList);
    8836                 :             :                     Assert(list_length(sortPathkeys) == list_length(sortList));
    8837                 :             :                     /* Undo tlist addition, if we made one */
    8838         [ +  + ]:        1710 :                     if (made_tle)
    8839                 :             :                     {
    8840                 :          10 :                         newtlist = list_delete_last(newtlist);
    8841                 :          10 :                         nextresno--;
    8842                 :             :                     }
    8843                 :             :                     /* We need not consider this clause for hashing, either */
    8844                 :        1710 :                     continue;
    8845                 :             :                 }
    8846                 :             :             }
    8847         [ #  # ]:           0 :             else if (sjinfo->semi_can_btree) /* shouldn't happen */
    8848         [ #  # ]:           0 :                 elog(ERROR, "could not find ordering operator for equality operator %u",
    8849                 :             :                      in_oper);
    8850                 :             : 
    8851         [ +  - ]:        3775 :             if (sjinfo->semi_can_hash)
    8852                 :             :             {
    8853                 :             :                 /* Create a GROUP BY list for the Agg node to use */
    8854                 :             :                 Oid         eq_oper;
    8855                 :             :                 SortGroupClause *groupcl;
    8856                 :             : 
    8857                 :             :                 /*
    8858                 :             :                  * Get the hashable equality operators for the Agg node to
    8859                 :             :                  * use. Normally these are the same as the IN clause
    8860                 :             :                  * operators, but if those are cross-type operators then the
    8861                 :             :                  * equality operators are the ones for the IN clause
    8862                 :             :                  * operators' RHS datatype.
    8863                 :             :                  */
    8864         [ -  + ]:        3775 :                 if (!get_compatible_hash_operators(in_oper, NULL, &eq_oper))
    8865         [ #  # ]:           0 :                     elog(ERROR, "could not find compatible hash operator for operator %u",
    8866                 :             :                          in_oper);
    8867                 :             : 
    8868                 :        3775 :                 groupcl = makeNode(SortGroupClause);
    8869                 :        3775 :                 groupcl->tleSortGroupRef = assignSortGroupRef(tle, newtlist);
    8870                 :        3775 :                 groupcl->eqop = eq_oper;
    8871                 :        3775 :                 groupcl->sortop = sortop;
    8872                 :        3775 :                 groupcl->reverse_sort = false;
    8873                 :        3775 :                 groupcl->nulls_first = false;
    8874                 :        3775 :                 groupcl->hashable = true;
    8875                 :        3775 :                 groupClause = lappend(groupClause, groupcl);
    8876                 :             :             }
    8877                 :             :         }
    8878                 :             : 
    8879                 :             :         /*
    8880                 :             :          * Done building the sortPathkeys and groupClause.  But the
    8881                 :             :          * sortPathkeys are bogus if not all the clauses were sortable.
    8882                 :             :          */
    8883         [ -  + ]:        5284 :         if (!sjinfo->semi_can_btree)
    8884                 :           0 :             sortPathkeys = NIL;
    8885                 :             : 
    8886                 :             :         /*
    8887                 :             :          * It can happen that all the RHS columns are equated to constants.
    8888                 :             :          * We'd have to do something special to unique-ify in that case, and
    8889                 :             :          * it's such an unlikely-in-the-real-world case that it's not worth
    8890                 :             :          * the effort.  So just punt if we found no columns to unique-ify.
    8891                 :             :          */
    8892   [ +  +  +  - ]:        5284 :         if (sortPathkeys == NIL && groupClause == NIL)
    8893                 :             :         {
    8894                 :        1625 :             MemoryContextSwitchTo(oldcontext);
    8895                 :        1625 :             return NULL;
    8896                 :             :         }
    8897                 :             : 
    8898                 :             :         /* Convert the required targetlist back to PathTarget form */
    8899                 :        3659 :         unique_rel->reltarget = create_pathtarget(root, newtlist);
    8900                 :             :     }
    8901                 :             : 
    8902                 :             :     /* build unique paths based on input rel's pathlist */
    8903                 :        4019 :     create_final_unique_paths(root, rel, sortPathkeys, groupClause,
    8904                 :             :                               sjinfo, unique_rel);
    8905                 :             : 
    8906                 :             :     /* build unique paths based on input rel's partial_pathlist */
    8907                 :        4019 :     create_partial_unique_paths(root, rel, sortPathkeys, groupClause,
    8908                 :             :                                 sjinfo, unique_rel);
    8909                 :             : 
    8910                 :             :     /* Now choose the best path(s) */
    8911                 :        4019 :     set_cheapest(unique_rel);
    8912                 :             : 
    8913                 :             :     /*
    8914                 :             :      * There shouldn't be any partial paths for the unique relation;
    8915                 :             :      * otherwise, we won't be able to properly guarantee uniqueness.
    8916                 :             :      */
    8917                 :             :     Assert(unique_rel->partial_pathlist == NIL);
    8918                 :             : 
    8919                 :             :     /* Cache the result */
    8920                 :        4019 :     rel->unique_rel = unique_rel;
    8921                 :        4019 :     rel->unique_pathkeys = sortPathkeys;
    8922                 :        4019 :     rel->unique_groupclause = groupClause;
    8923                 :             : 
    8924                 :        4019 :     MemoryContextSwitchTo(oldcontext);
    8925                 :             : 
    8926                 :        4019 :     return unique_rel;
    8927                 :             : }
    8928                 :             : 
    8929                 :             : /*
    8930                 :             :  * create_final_unique_paths
    8931                 :             :  *    Create unique paths in 'unique_rel' based on 'input_rel' pathlist
    8932                 :             :  */
    8933                 :             : static void
    8934                 :        7171 : create_final_unique_paths(PlannerInfo *root, RelOptInfo *input_rel,
    8935                 :             :                           List *sortPathkeys, List *groupClause,
    8936                 :             :                           SpecialJoinInfo *sjinfo, RelOptInfo *unique_rel)
    8937                 :             : {
    8938                 :        7171 :     Path       *cheapest_input_path = input_rel->cheapest_total_path;
    8939                 :             : 
    8940                 :             :     /* Estimate number of output rows */
    8941                 :        7171 :     unique_rel->rows = estimate_num_groups(root,
    8942                 :             :                                            sjinfo->semi_rhs_exprs,
    8943                 :             :                                            cheapest_input_path->rows,
    8944                 :             :                                            NULL,
    8945                 :             :                                            NULL);
    8946                 :             : 
    8947                 :             :     /* Consider sort-based implementations, if possible. */
    8948         [ +  - ]:        7171 :     if (sjinfo->semi_can_btree)
    8949                 :             :     {
    8950                 :             :         ListCell   *lc;
    8951                 :             : 
    8952                 :             :         /*
    8953                 :             :          * Use any available suitably-sorted path as input, and also consider
    8954                 :             :          * sorting the cheapest-total path and incremental sort on any paths
    8955                 :             :          * with presorted keys.
    8956                 :             :          *
    8957                 :             :          * To save planning time, we ignore parameterized input paths unless
    8958                 :             :          * they are the cheapest-total path.
    8959                 :             :          */
    8960   [ +  -  +  +  :       15620 :         foreach(lc, input_rel->pathlist)
                   +  + ]
    8961                 :             :         {
    8962                 :        8449 :             Path       *input_path = (Path *) lfirst(lc);
    8963                 :             :             Path       *path;
    8964                 :             :             bool        is_sorted;
    8965                 :             :             int         presorted_keys;
    8966                 :             : 
    8967                 :             :             /*
    8968                 :             :              * Ignore parameterized paths that are not the cheapest-total
    8969                 :             :              * path.
    8970                 :             :              */
    8971   [ +  +  +  + ]:        8449 :             if (input_path->param_info &&
    8972                 :             :                 input_path != cheapest_input_path)
    8973                 :         740 :                 continue;
    8974                 :             : 
    8975                 :        7745 :             is_sorted = pathkeys_count_contained_in(sortPathkeys,
    8976                 :             :                                                     input_path->pathkeys,
    8977                 :             :                                                     &presorted_keys);
    8978                 :             : 
    8979                 :             :             /*
    8980                 :             :              * Ignore paths that are not suitably or partially sorted, unless
    8981                 :             :              * they are the cheapest total path (no need to deal with paths
    8982                 :             :              * which have presorted keys when incremental sort is disabled).
    8983                 :             :              */
    8984   [ +  +  +  + ]:        7745 :             if (!is_sorted && input_path != cheapest_input_path &&
    8985   [ +  +  -  + ]:          76 :                 (presorted_keys == 0 || !enable_incremental_sort))
    8986                 :          36 :                 continue;
    8987                 :             : 
    8988                 :             :             /*
    8989                 :             :              * Make a separate ProjectionPath in case we need a Result node.
    8990                 :             :              */
    8991                 :        7709 :             path = (Path *) create_projection_path(root,
    8992                 :             :                                                    unique_rel,
    8993                 :             :                                                    input_path,
    8994                 :        7709 :                                                    unique_rel->reltarget);
    8995                 :             : 
    8996         [ +  + ]:        7709 :             if (!is_sorted)
    8997                 :             :             {
    8998                 :             :                 /*
    8999                 :             :                  * We've no need to consider both a sort and incremental sort.
    9000                 :             :                  * We'll just do a sort if there are no presorted keys and an
    9001                 :             :                  * incremental sort when there are presorted keys.
    9002                 :             :                  */
    9003   [ +  +  -  + ]:        4002 :                 if (presorted_keys == 0 || !enable_incremental_sort)
    9004                 :        3962 :                     path = (Path *) create_sort_path(root,
    9005                 :             :                                                      unique_rel,
    9006                 :             :                                                      path,
    9007                 :             :                                                      sortPathkeys,
    9008                 :             :                                                      -1.0);
    9009                 :             :                 else
    9010                 :          40 :                     path = (Path *) create_incremental_sort_path(root,
    9011                 :             :                                                                  unique_rel,
    9012                 :             :                                                                  path,
    9013                 :             :                                                                  sortPathkeys,
    9014                 :             :                                                                  presorted_keys,
    9015                 :             :                                                                  -1.0);
    9016                 :             :             }
    9017                 :             : 
    9018                 :        7709 :             path = (Path *) create_unique_path(root, unique_rel, path,
    9019                 :             :                                                list_length(sortPathkeys),
    9020                 :             :                                                unique_rel->rows);
    9021                 :             : 
    9022                 :        7709 :             add_path(unique_rel, path);
    9023                 :             :         }
    9024                 :             :     }
    9025                 :             : 
    9026                 :             :     /* Consider hash-based implementation, if possible. */
    9027         [ +  - ]:        7171 :     if (sjinfo->semi_can_hash)
    9028                 :             :     {
    9029                 :             :         Path       *path;
    9030                 :             : 
    9031                 :             :         /*
    9032                 :             :          * Make a separate ProjectionPath in case we need a Result node.
    9033                 :             :          */
    9034                 :        7171 :         path = (Path *) create_projection_path(root,
    9035                 :             :                                                unique_rel,
    9036                 :             :                                                cheapest_input_path,
    9037                 :        7171 :                                                unique_rel->reltarget);
    9038                 :             : 
    9039                 :        7171 :         path = (Path *) create_agg_path(root,
    9040                 :             :                                         unique_rel,
    9041                 :             :                                         path,
    9042                 :             :                                         cheapest_input_path->pathtarget,
    9043                 :             :                                         AGG_HASHED,
    9044                 :             :                                         AGGSPLIT_SIMPLE,
    9045                 :             :                                         groupClause,
    9046                 :             :                                         NIL,
    9047                 :             :                                         NULL,
    9048                 :             :                                         unique_rel->rows);
    9049                 :             : 
    9050                 :        7171 :         add_path(unique_rel, path);
    9051                 :             :     }
    9052                 :        7171 : }
    9053                 :             : 
    9054                 :             : /*
    9055                 :             :  * create_partial_unique_paths
    9056                 :             :  *    Create unique paths in 'unique_rel' based on 'input_rel' partial_pathlist
    9057                 :             :  */
    9058                 :             : static void
    9059                 :        4019 : create_partial_unique_paths(PlannerInfo *root, RelOptInfo *input_rel,
    9060                 :             :                             List *sortPathkeys, List *groupClause,
    9061                 :             :                             SpecialJoinInfo *sjinfo, RelOptInfo *unique_rel)
    9062                 :             : {
    9063                 :             :     RelOptInfo *partial_unique_rel;
    9064                 :             :     Path       *cheapest_partial_path;
    9065                 :             : 
    9066                 :             :     /* nothing to do when there are no partial paths in the input rel */
    9067   [ +  +  +  + ]:        4019 :     if (!input_rel->consider_parallel || input_rel->partial_pathlist == NIL)
    9068                 :         867 :         return;
    9069                 :             : 
    9070                 :             :     /*
    9071                 :             :      * nothing to do if there's anything in the targetlist that's
    9072                 :             :      * parallel-restricted.
    9073                 :             :      */
    9074         [ -  + ]:        3152 :     if (!is_parallel_safe(root, (Node *) unique_rel->reltarget->exprs))
    9075                 :           0 :         return;
    9076                 :             : 
    9077                 :        3152 :     cheapest_partial_path = linitial(input_rel->partial_pathlist);
    9078                 :             : 
    9079                 :        3152 :     partial_unique_rel = makeNode(RelOptInfo);
    9080                 :        3152 :     memcpy(partial_unique_rel, input_rel, sizeof(RelOptInfo));
    9081                 :             : 
    9082                 :             :     /*
    9083                 :             :      * clear path info
    9084                 :             :      */
    9085                 :        3152 :     partial_unique_rel->pathlist = NIL;
    9086                 :        3152 :     partial_unique_rel->ppilist = NIL;
    9087                 :        3152 :     partial_unique_rel->partial_pathlist = NIL;
    9088                 :        3152 :     partial_unique_rel->cheapest_startup_path = NULL;
    9089                 :        3152 :     partial_unique_rel->cheapest_total_path = NULL;
    9090                 :        3152 :     partial_unique_rel->cheapest_parameterized_paths = NIL;
    9091                 :             : 
    9092                 :             :     /* Estimate number of output rows */
    9093                 :        3152 :     partial_unique_rel->rows = estimate_num_groups(root,
    9094                 :             :                                                    sjinfo->semi_rhs_exprs,
    9095                 :             :                                                    cheapest_partial_path->rows,
    9096                 :             :                                                    NULL,
    9097                 :             :                                                    NULL);
    9098                 :        3152 :     partial_unique_rel->reltarget = unique_rel->reltarget;
    9099                 :             : 
    9100                 :             :     /* Consider sort-based implementations, if possible. */
    9101         [ +  - ]:        3152 :     if (sjinfo->semi_can_btree)
    9102                 :             :     {
    9103                 :             :         ListCell   *lc;
    9104                 :             : 
    9105                 :             :         /*
    9106                 :             :          * Use any available suitably-sorted path as input, and also consider
    9107                 :             :          * sorting the cheapest partial path and incremental sort on any paths
    9108                 :             :          * with presorted keys.
    9109                 :             :          */
    9110   [ +  -  +  +  :        6558 :         foreach(lc, input_rel->partial_pathlist)
                   +  + ]
    9111                 :             :         {
    9112                 :        3406 :             Path       *input_path = (Path *) lfirst(lc);
    9113                 :             :             Path       *path;
    9114                 :             :             bool        is_sorted;
    9115                 :             :             int         presorted_keys;
    9116                 :             : 
    9117                 :        3406 :             is_sorted = pathkeys_count_contained_in(sortPathkeys,
    9118                 :             :                                                     input_path->pathkeys,
    9119                 :             :                                                     &presorted_keys);
    9120                 :             : 
    9121                 :             :             /*
    9122                 :             :              * Ignore paths that are not suitably or partially sorted, unless
    9123                 :             :              * they are the cheapest partial path (no need to deal with paths
    9124                 :             :              * which have presorted keys when incremental sort is disabled).
    9125                 :             :              */
    9126   [ +  +  -  + ]:        3406 :             if (!is_sorted && input_path != cheapest_partial_path &&
    9127   [ #  #  #  # ]:           0 :                 (presorted_keys == 0 || !enable_incremental_sort))
    9128                 :           0 :                 continue;
    9129                 :             : 
    9130                 :             :             /*
    9131                 :             :              * Make a separate ProjectionPath in case we need a Result node.
    9132                 :             :              */
    9133                 :        3406 :             path = (Path *) create_projection_path(root,
    9134                 :             :                                                    partial_unique_rel,
    9135                 :             :                                                    input_path,
    9136                 :        3406 :                                                    partial_unique_rel->reltarget);
    9137                 :             : 
    9138         [ +  + ]:        3406 :             if (!is_sorted)
    9139                 :             :             {
    9140                 :             :                 /*
    9141                 :             :                  * We've no need to consider both a sort and incremental sort.
    9142                 :             :                  * We'll just do a sort if there are no presorted keys and an
    9143                 :             :                  * incremental sort when there are presorted keys.
    9144                 :             :                  */
    9145   [ -  +  -  - ]:        3112 :                 if (presorted_keys == 0 || !enable_incremental_sort)
    9146                 :        3112 :                     path = (Path *) create_sort_path(root,
    9147                 :             :                                                      partial_unique_rel,
    9148                 :             :                                                      path,
    9149                 :             :                                                      sortPathkeys,
    9150                 :             :                                                      -1.0);
    9151                 :             :                 else
    9152                 :           0 :                     path = (Path *) create_incremental_sort_path(root,
    9153                 :             :                                                                  partial_unique_rel,
    9154                 :             :                                                                  path,
    9155                 :             :                                                                  sortPathkeys,
    9156                 :             :                                                                  presorted_keys,
    9157                 :             :                                                                  -1.0);
    9158                 :             :             }
    9159                 :             : 
    9160                 :        3406 :             path = (Path *) create_unique_path(root, partial_unique_rel, path,
    9161                 :             :                                                list_length(sortPathkeys),
    9162                 :             :                                                partial_unique_rel->rows);
    9163                 :             : 
    9164                 :        3406 :             add_partial_path(partial_unique_rel, path);
    9165                 :             :         }
    9166                 :             :     }
    9167                 :             : 
    9168                 :             :     /* Consider hash-based implementation, if possible. */
    9169         [ +  - ]:        3152 :     if (sjinfo->semi_can_hash)
    9170                 :             :     {
    9171                 :             :         Path       *path;
    9172                 :             : 
    9173                 :             :         /*
    9174                 :             :          * Make a separate ProjectionPath in case we need a Result node.
    9175                 :             :          */
    9176                 :        3152 :         path = (Path *) create_projection_path(root,
    9177                 :             :                                                partial_unique_rel,
    9178                 :             :                                                cheapest_partial_path,
    9179                 :        3152 :                                                partial_unique_rel->reltarget);
    9180                 :             : 
    9181                 :        3152 :         path = (Path *) create_agg_path(root,
    9182                 :             :                                         partial_unique_rel,
    9183                 :             :                                         path,
    9184                 :             :                                         cheapest_partial_path->pathtarget,
    9185                 :             :                                         AGG_HASHED,
    9186                 :             :                                         AGGSPLIT_SIMPLE,
    9187                 :             :                                         groupClause,
    9188                 :             :                                         NIL,
    9189                 :             :                                         NULL,
    9190                 :             :                                         partial_unique_rel->rows);
    9191                 :             : 
    9192                 :        3152 :         add_partial_path(partial_unique_rel, path);
    9193                 :             :     }
    9194                 :             : 
    9195         [ +  - ]:        3152 :     if (partial_unique_rel->partial_pathlist != NIL)
    9196                 :             :     {
    9197                 :        3152 :         generate_useful_gather_paths(root, partial_unique_rel, true);
    9198                 :        3152 :         set_cheapest(partial_unique_rel);
    9199                 :             : 
    9200                 :             :         /*
    9201                 :             :          * Finally, create paths to unique-ify the final result.  This step is
    9202                 :             :          * needed to remove any duplicates due to combining rows from parallel
    9203                 :             :          * workers.
    9204                 :             :          */
    9205                 :        3152 :         create_final_unique_paths(root, partial_unique_rel,
    9206                 :             :                                   sortPathkeys, groupClause,
    9207                 :             :                                   sjinfo, unique_rel);
    9208                 :             :     }
    9209                 :             : }
    9210                 :             : 
    9211                 :             : /*
    9212                 :             :  * Choose a unique name for some subroot.
    9213                 :             :  *
    9214                 :             :  * Modifies glob->subplanNames to track names already used.
    9215                 :             :  */
    9216                 :             : char *
    9217                 :       63244 : choose_plan_name(PlannerGlobal *glob, const char *name, bool always_number)
    9218                 :             : {
    9219                 :             :     unsigned    n;
    9220                 :             : 
    9221                 :             :     /*
    9222                 :             :      * If a numeric suffix is not required, then search the list of
    9223                 :             :      * previously-assigned names for a match. If none is found, then we can
    9224                 :             :      * use the provided name without modification.
    9225                 :             :      */
    9226         [ +  + ]:       63244 :     if (!always_number)
    9227                 :             :     {
    9228                 :       18822 :         bool        found = false;
    9229                 :             : 
    9230   [ +  +  +  +  :       45722 :         foreach_ptr(char, subplan_name, glob->subplanNames)
                   +  + ]
    9231                 :             :         {
    9232         [ +  + ]:       11620 :             if (strcmp(subplan_name, name) == 0)
    9233                 :             :             {
    9234                 :        3542 :                 found = true;
    9235                 :        3542 :                 break;
    9236                 :             :             }
    9237                 :             :         }
    9238                 :             : 
    9239         [ +  + ]:       18822 :         if (!found)
    9240                 :             :         {
    9241                 :             :             /* pstrdup here is just to avoid cast-away-const */
    9242                 :       15280 :             char       *chosen_name = pstrdup(name);
    9243                 :             : 
    9244                 :       15280 :             glob->subplanNames = lappend(glob->subplanNames, chosen_name);
    9245                 :       15280 :             return chosen_name;
    9246                 :             :         }
    9247                 :             :     }
    9248                 :             : 
    9249                 :             :     /*
    9250                 :             :      * If a numeric suffix is required or if the un-suffixed name is already
    9251                 :             :      * in use, then loop until we find a positive integer that produces a
    9252                 :             :      * novel name.
    9253                 :             :      */
    9254                 :       47964 :     for (n = 1; true; ++n)
    9255                 :       37950 :     {
    9256                 :       85914 :         char       *proposed_name = psprintf("%s_%u", name, n);
    9257                 :       85914 :         bool        found = false;
    9258                 :             : 
    9259   [ +  +  +  +  :      307284 :         foreach_ptr(char, subplan_name, glob->subplanNames)
                   +  + ]
    9260                 :             :         {
    9261         [ +  + ]:      173406 :             if (strcmp(subplan_name, proposed_name) == 0)
    9262                 :             :             {
    9263                 :       37950 :                 found = true;
    9264                 :       37950 :                 break;
    9265                 :             :             }
    9266                 :             :         }
    9267                 :             : 
    9268         [ +  + ]:       85914 :         if (!found)
    9269                 :             :         {
    9270                 :       47964 :             glob->subplanNames = lappend(glob->subplanNames, proposed_name);
    9271                 :       47964 :             return proposed_name;
    9272                 :             :         }
    9273                 :             : 
    9274                 :       37950 :         pfree(proposed_name);
    9275                 :             :     }
    9276                 :             : }
        

Generated by: LCOV version 2.0-1