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-07-11 15:16:30 Functions: 100.0 % 66 66
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 85.7 % 2244 1922

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

Generated by: LCOV version 2.0-1