mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-08-22 09:33:24 +02:00
postgres_fdw would push ORDER BY clauses to the remote side without
verifying that the sort operator is safe to ship. Moreover, it failed
to print a suitable USING clause if the sort operator isn't default
for the sort expression's type. The net result of this is that the
remote sort might not have anywhere near the semantics we expect,
which'd be disastrous for locally-performed merge joins in particular.
We addressed similar issues in the context of ORDER BY within an
aggregate function call in commit 7012b132d
, but failed to notice
that query-level ORDER BY was broken. Thus, much of the necessary
logic already existed, but it requires refactoring to be usable
in both cases.
Back-patch to all supported branches. In HEAD only, remove the
core code's copy of find_em_expr_for_rel, which is no longer used
and really should never have been pushed into equivclass.c in the
first place.
Ronan Dunklau, per report from David Rowley;
reviews by David Rowley, Ranier Vilela, and myself
Discussion: https://postgr.es/m/CAApHDvr4OeC2DBVY--zVP83-K=bYrTD7F8SZDhN4g+pj2f2S-A@mail.gmail.com
239 lines
8.0 KiB
C
239 lines
8.0 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* postgres_fdw.h
|
|
* Foreign-data wrapper for remote PostgreSQL servers
|
|
*
|
|
* Portions Copyright (c) 2012-2021, PostgreSQL Global Development Group
|
|
*
|
|
* IDENTIFICATION
|
|
* contrib/postgres_fdw/postgres_fdw.h
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
#ifndef POSTGRES_FDW_H
|
|
#define POSTGRES_FDW_H
|
|
|
|
#include "foreign/foreign.h"
|
|
#include "lib/stringinfo.h"
|
|
#include "libpq-fe.h"
|
|
#include "nodes/execnodes.h"
|
|
#include "nodes/pathnodes.h"
|
|
#include "utils/relcache.h"
|
|
|
|
/*
|
|
* FDW-specific planner information kept in RelOptInfo.fdw_private for a
|
|
* postgres_fdw foreign table. For a baserel, this struct is created by
|
|
* postgresGetForeignRelSize, although some fields are not filled till later.
|
|
* postgresGetForeignJoinPaths creates it for a joinrel, and
|
|
* postgresGetForeignUpperPaths creates it for an upperrel.
|
|
*/
|
|
typedef struct PgFdwRelationInfo
|
|
{
|
|
/*
|
|
* True means that the relation can be pushed down. Always true for simple
|
|
* foreign scan.
|
|
*/
|
|
bool pushdown_safe;
|
|
|
|
/*
|
|
* Restriction clauses, divided into safe and unsafe to pushdown subsets.
|
|
* All entries in these lists should have RestrictInfo wrappers; that
|
|
* improves efficiency of selectivity and cost estimation.
|
|
*/
|
|
List *remote_conds;
|
|
List *local_conds;
|
|
|
|
/* Actual remote restriction clauses for scan (sans RestrictInfos) */
|
|
List *final_remote_exprs;
|
|
|
|
/* Bitmap of attr numbers we need to fetch from the remote server. */
|
|
Bitmapset *attrs_used;
|
|
|
|
/* True means that the query_pathkeys is safe to push down */
|
|
bool qp_is_pushdown_safe;
|
|
|
|
/* Cost and selectivity of local_conds. */
|
|
QualCost local_conds_cost;
|
|
Selectivity local_conds_sel;
|
|
|
|
/* Selectivity of join conditions */
|
|
Selectivity joinclause_sel;
|
|
|
|
/* Estimated size and cost for a scan, join, or grouping/aggregation. */
|
|
double rows;
|
|
int width;
|
|
Cost startup_cost;
|
|
Cost total_cost;
|
|
|
|
/*
|
|
* Estimated number of rows fetched from the foreign server, and costs
|
|
* excluding costs for transferring those rows from the foreign server.
|
|
* These are only used by estimate_path_cost_size().
|
|
*/
|
|
double retrieved_rows;
|
|
Cost rel_startup_cost;
|
|
Cost rel_total_cost;
|
|
|
|
/* Options extracted from catalogs. */
|
|
bool use_remote_estimate;
|
|
Cost fdw_startup_cost;
|
|
Cost fdw_tuple_cost;
|
|
List *shippable_extensions; /* OIDs of shippable extensions */
|
|
bool async_capable;
|
|
|
|
/* Cached catalog information. */
|
|
ForeignTable *table;
|
|
ForeignServer *server;
|
|
UserMapping *user; /* only set in use_remote_estimate mode */
|
|
|
|
int fetch_size; /* fetch size for this remote table */
|
|
|
|
/*
|
|
* Name of the relation, for use while EXPLAINing ForeignScan. It is used
|
|
* for join and upper relations but is set for all relations. For a base
|
|
* relation, this is really just the RT index as a string; we convert that
|
|
* while producing EXPLAIN output. For join and upper relations, the name
|
|
* indicates which base foreign tables are included and the join type or
|
|
* aggregation type used.
|
|
*/
|
|
char *relation_name;
|
|
|
|
/* Join information */
|
|
RelOptInfo *outerrel;
|
|
RelOptInfo *innerrel;
|
|
JoinType jointype;
|
|
/* joinclauses contains only JOIN/ON conditions for an outer join */
|
|
List *joinclauses; /* List of RestrictInfo */
|
|
|
|
/* Upper relation information */
|
|
UpperRelationKind stage;
|
|
|
|
/* Grouping information */
|
|
List *grouped_tlist;
|
|
|
|
/* Subquery information */
|
|
bool make_outerrel_subquery; /* do we deparse outerrel as a
|
|
* subquery? */
|
|
bool make_innerrel_subquery; /* do we deparse innerrel as a
|
|
* subquery? */
|
|
Relids lower_subquery_rels; /* all relids appearing in lower
|
|
* subqueries */
|
|
|
|
/*
|
|
* Index of the relation. It is used to create an alias to a subquery
|
|
* representing the relation.
|
|
*/
|
|
int relation_index;
|
|
} PgFdwRelationInfo;
|
|
|
|
/*
|
|
* Extra control information relating to a connection.
|
|
*/
|
|
typedef struct PgFdwConnState
|
|
{
|
|
AsyncRequest *pendingAreq; /* pending async request */
|
|
} PgFdwConnState;
|
|
|
|
/* in postgres_fdw.c */
|
|
extern int set_transmission_modes(void);
|
|
extern void reset_transmission_modes(int nestlevel);
|
|
extern void process_pending_request(AsyncRequest *areq);
|
|
|
|
/* in connection.c */
|
|
extern PGconn *GetConnection(UserMapping *user, bool will_prep_stmt,
|
|
PgFdwConnState **state);
|
|
extern void ReleaseConnection(PGconn *conn);
|
|
extern unsigned int GetCursorNumber(PGconn *conn);
|
|
extern unsigned int GetPrepStmtNumber(PGconn *conn);
|
|
extern void do_sql_command(PGconn *conn, const char *sql);
|
|
extern PGresult *pgfdw_get_result(PGconn *conn, const char *query);
|
|
extern PGresult *pgfdw_exec_query(PGconn *conn, const char *query,
|
|
PgFdwConnState *state);
|
|
extern void pgfdw_report_error(int elevel, PGresult *res, PGconn *conn,
|
|
bool clear, const char *sql);
|
|
|
|
/* in option.c */
|
|
extern int ExtractConnectionOptions(List *defelems,
|
|
const char **keywords,
|
|
const char **values);
|
|
extern List *ExtractExtensionList(const char *extensionsString,
|
|
bool warnOnMissing);
|
|
|
|
/* in deparse.c */
|
|
extern void classifyConditions(PlannerInfo *root,
|
|
RelOptInfo *baserel,
|
|
List *input_conds,
|
|
List **remote_conds,
|
|
List **local_conds);
|
|
extern bool is_foreign_expr(PlannerInfo *root,
|
|
RelOptInfo *baserel,
|
|
Expr *expr);
|
|
extern bool is_foreign_param(PlannerInfo *root,
|
|
RelOptInfo *baserel,
|
|
Expr *expr);
|
|
extern bool is_foreign_pathkey(PlannerInfo *root,
|
|
RelOptInfo *baserel,
|
|
PathKey *pathkey);
|
|
extern void deparseInsertSql(StringInfo buf, RangeTblEntry *rte,
|
|
Index rtindex, Relation rel,
|
|
List *targetAttrs, bool doNothing,
|
|
List *withCheckOptionList, List *returningList,
|
|
List **retrieved_attrs, int *values_end_len);
|
|
extern void rebuildInsertSql(StringInfo buf, Relation rel,
|
|
char *orig_query, List *target_attrs,
|
|
int values_end_len, int num_params,
|
|
int num_rows);
|
|
extern void deparseUpdateSql(StringInfo buf, RangeTblEntry *rte,
|
|
Index rtindex, Relation rel,
|
|
List *targetAttrs,
|
|
List *withCheckOptionList, List *returningList,
|
|
List **retrieved_attrs);
|
|
extern void deparseDirectUpdateSql(StringInfo buf, PlannerInfo *root,
|
|
Index rtindex, Relation rel,
|
|
RelOptInfo *foreignrel,
|
|
List *targetlist,
|
|
List *targetAttrs,
|
|
List *remote_conds,
|
|
List **params_list,
|
|
List *returningList,
|
|
List **retrieved_attrs);
|
|
extern void deparseDeleteSql(StringInfo buf, RangeTblEntry *rte,
|
|
Index rtindex, Relation rel,
|
|
List *returningList,
|
|
List **retrieved_attrs);
|
|
extern void deparseDirectDeleteSql(StringInfo buf, PlannerInfo *root,
|
|
Index rtindex, Relation rel,
|
|
RelOptInfo *foreignrel,
|
|
List *remote_conds,
|
|
List **params_list,
|
|
List *returningList,
|
|
List **retrieved_attrs);
|
|
extern void deparseAnalyzeSizeSql(StringInfo buf, Relation rel);
|
|
extern void deparseAnalyzeSql(StringInfo buf, Relation rel,
|
|
List **retrieved_attrs);
|
|
extern void deparseTruncateSql(StringInfo buf,
|
|
List *rels,
|
|
DropBehavior behavior,
|
|
bool restart_seqs);
|
|
extern void deparseStringLiteral(StringInfo buf, const char *val);
|
|
extern EquivalenceMember *find_em_for_rel(PlannerInfo *root,
|
|
EquivalenceClass *ec,
|
|
RelOptInfo *rel);
|
|
extern EquivalenceMember *find_em_for_rel_target(PlannerInfo *root,
|
|
EquivalenceClass *ec,
|
|
RelOptInfo *rel);
|
|
extern List *build_tlist_to_deparse(RelOptInfo *foreignrel);
|
|
extern void deparseSelectStmtForRel(StringInfo buf, PlannerInfo *root,
|
|
RelOptInfo *foreignrel, List *tlist,
|
|
List *remote_conds, List *pathkeys,
|
|
bool has_final_sort, bool has_limit,
|
|
bool is_subquery,
|
|
List **retrieved_attrs, List **params_list);
|
|
extern const char *get_jointype_name(JoinType jointype);
|
|
|
|
/* in shippable.c */
|
|
extern bool is_builtin(Oid objectId);
|
|
extern bool is_shippable(Oid objectId, Oid classId, PgFdwRelationInfo *fpinfo);
|
|
|
|
#endif /* POSTGRES_FDW_H */
|