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 % 2604 2517
Test Date: 2026-07-03 19:57:34 Functions: 100.0 % 65 65
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 85.3 % 2300 1963

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

Generated by: LCOV version 2.0-1