mirror of
https://github.com/postgres/postgres.git
synced 2026-07-04 15:25:50 -04:00
postgres_fdw's postgresGetForeignPlan() assumes without checking that the outer_plan it's given for a join relation must have a NestLoop, MergeJoin, or HashJoin node at the top. That's been wrong at least since commit4bbf6edfb(which could cause insertion of a Sort node on top) and it seems like a pretty unsafe thing to Just Assume even without that. Through blind good fortune, this doesn't seem to have any worse consequences today than strange EXPLAIN output, but it's clearly trouble waiting to happen. To fix, test the node type explicitly before touching Join-specific fields, and avoid jamming the new tlist into a node type that can't do projection. Export a new support function from createplan.c to avoid building low-level knowledge about the latter into FDWs. Back-patch to 9.6 where the faulty coding was added. Note that the associated regression test cases don't show any changes before v11, apparently because the tests back-patched with4bbf6edfbdon't actually exercise the problem case before then (there's no top-level Sort in those plans). Discussion: https://postgr.es/m/8946.1544644803@sss.pgh.pa.us
125 lines
4.1 KiB
C
125 lines
4.1 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* planmain.h
|
|
* prototypes for various files in optimizer/plan
|
|
*
|
|
*
|
|
* Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
*
|
|
* src/include/optimizer/planmain.h
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
#ifndef PLANMAIN_H
|
|
#define PLANMAIN_H
|
|
|
|
#include "nodes/plannodes.h"
|
|
#include "nodes/relation.h"
|
|
|
|
/* possible values for force_parallel_mode */
|
|
typedef enum
|
|
{
|
|
FORCE_PARALLEL_OFF,
|
|
FORCE_PARALLEL_ON,
|
|
FORCE_PARALLEL_REGRESS
|
|
} ForceParallelMode;
|
|
|
|
/* GUC parameters */
|
|
#define DEFAULT_CURSOR_TUPLE_FRACTION 0.1
|
|
extern double cursor_tuple_fraction;
|
|
extern int force_parallel_mode;
|
|
|
|
/* query_planner callback to compute query_pathkeys */
|
|
typedef void (*query_pathkeys_callback) (PlannerInfo *root, void *extra);
|
|
|
|
/*
|
|
* prototypes for plan/planmain.c
|
|
*/
|
|
extern RelOptInfo *query_planner(PlannerInfo *root, List *tlist,
|
|
query_pathkeys_callback qp_callback, void *qp_extra);
|
|
|
|
/*
|
|
* prototypes for plan/planagg.c
|
|
*/
|
|
extern void preprocess_minmax_aggregates(PlannerInfo *root, List *tlist);
|
|
|
|
/*
|
|
* prototypes for plan/createplan.c
|
|
*/
|
|
extern Plan *create_plan(PlannerInfo *root, Path *best_path);
|
|
extern ForeignScan *make_foreignscan(List *qptlist, List *qpqual,
|
|
Index scanrelid, List *fdw_exprs, List *fdw_private,
|
|
List *fdw_scan_tlist, List *fdw_recheck_quals,
|
|
Plan *outer_plan);
|
|
extern Plan *change_plan_targetlist(Plan *subplan, List *tlist,
|
|
bool tlist_parallel_safe);
|
|
extern Plan *materialize_finished_plan(Plan *subplan);
|
|
extern bool is_projection_capable_path(Path *path);
|
|
extern bool is_projection_capable_plan(Plan *plan);
|
|
|
|
/* External use of these functions is deprecated: */
|
|
extern Sort *make_sort_from_sortclauses(List *sortcls, Plan *lefttree);
|
|
extern Agg *make_agg(List *tlist, List *qual,
|
|
AggStrategy aggstrategy, AggSplit aggsplit,
|
|
int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators,
|
|
List *groupingSets, List *chain,
|
|
double dNumGroups, Plan *lefttree);
|
|
extern Limit *make_limit(Plan *lefttree, Node *limitOffset, Node *limitCount);
|
|
|
|
/*
|
|
* prototypes for plan/initsplan.c
|
|
*/
|
|
extern int from_collapse_limit;
|
|
extern int join_collapse_limit;
|
|
|
|
extern void add_base_rels_to_query(PlannerInfo *root, Node *jtnode);
|
|
extern void build_base_rel_tlists(PlannerInfo *root, List *final_tlist);
|
|
extern void add_vars_to_targetlist(PlannerInfo *root, List *vars,
|
|
Relids where_needed, bool create_new_ph);
|
|
extern void find_lateral_references(PlannerInfo *root);
|
|
extern void create_lateral_join_info(PlannerInfo *root);
|
|
extern List *deconstruct_jointree(PlannerInfo *root);
|
|
extern void distribute_restrictinfo_to_rels(PlannerInfo *root,
|
|
RestrictInfo *restrictinfo);
|
|
extern void process_implied_equality(PlannerInfo *root,
|
|
Oid opno,
|
|
Oid collation,
|
|
Expr *item1,
|
|
Expr *item2,
|
|
Relids qualscope,
|
|
Relids nullable_relids,
|
|
Index security_level,
|
|
bool below_outer_join,
|
|
bool both_const);
|
|
extern RestrictInfo *build_implied_join_equality(Oid opno,
|
|
Oid collation,
|
|
Expr *item1,
|
|
Expr *item2,
|
|
Relids qualscope,
|
|
Relids nullable_relids,
|
|
Index security_level);
|
|
extern void match_foreign_keys_to_quals(PlannerInfo *root);
|
|
|
|
/*
|
|
* prototypes for plan/analyzejoins.c
|
|
*/
|
|
extern List *remove_useless_joins(PlannerInfo *root, List *joinlist);
|
|
extern void reduce_unique_semijoins(PlannerInfo *root);
|
|
extern bool query_supports_distinctness(Query *query);
|
|
extern bool query_is_distinct_for(Query *query, List *colnos, List *opids);
|
|
extern bool innerrel_is_unique(PlannerInfo *root,
|
|
Relids outerrelids, RelOptInfo *innerrel,
|
|
JoinType jointype, List *restrictlist, bool force_cache);
|
|
|
|
/*
|
|
* prototypes for plan/setrefs.c
|
|
*/
|
|
extern Plan *set_plan_references(PlannerInfo *root, Plan *plan);
|
|
extern void record_plan_function_dependency(PlannerInfo *root, Oid funcid);
|
|
extern void extract_query_dependencies(Node *query,
|
|
List **relationOids,
|
|
List **invalItems,
|
|
bool *hasRowSecurity);
|
|
|
|
#endif /* PLANMAIN_H */
|