mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-29 22:49:41 +03:00 
			
		
		
		
	This replaces dblink's blocking libpq calls, allowing cancellation and allowing DROP DATABASE (of a database not involved in the query). Apart from explicit dblink_cancel_query() calls, dblink still doesn't cancel the remote side. The replacement for the blocking calls consists of new, general-purpose query execution wrappers in the libpqsrv facility. Out-of-tree extensions should adopt these. Use them in postgres_fdw, replacing a local implementation from which the libpqsrv implementation derives. This is a bug fix for dblink. Code inspection identified the bug at least thirteen years ago, but user complaints have not appeared. Hence, no back-patch for now. Discussion: https://postgr.es/m/20231122012945.74@rfd.leadboat.com
		
			
				
	
	
		
			260 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			260 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*-------------------------------------------------------------------------
 | |
|  *
 | |
|  * postgres_fdw.h
 | |
|  *		  Foreign-data wrapper for remote PostgreSQL servers
 | |
|  *
 | |
|  * Portions Copyright (c) 2012-2024, 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 */
 | |
| 	Relids		hidden_subquery_rels;	/* relids, which can't be referred to
 | |
| 										 * from upper relations, used
 | |
| 										 * internally for equivalence member
 | |
| 										 * search */
 | |
| 
 | |
| 	/*
 | |
| 	 * 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;
 | |
| 
 | |
| /*
 | |
|  * Method used by ANALYZE to sample remote rows.
 | |
|  */
 | |
| typedef enum PgFdwSamplingMethod
 | |
| {
 | |
| 	ANALYZE_SAMPLE_OFF,			/* no remote sampling */
 | |
| 	ANALYZE_SAMPLE_AUTO,		/* choose by server version */
 | |
| 	ANALYZE_SAMPLE_RANDOM,		/* remote random() */
 | |
| 	ANALYZE_SAMPLE_SYSTEM,		/* TABLESAMPLE system */
 | |
| 	ANALYZE_SAMPLE_BERNOULLI,	/* TABLESAMPLE bernoulli */
 | |
| } PgFdwSamplingMethod;
 | |
| 
 | |
| /* 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);
 | |
| 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);
 | |
| extern char *process_pgfdw_appname(const char *appname);
 | |
| extern char *pgfdw_application_name;
 | |
| 
 | |
| /* 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 deparseAnalyzeInfoSql(StringInfo buf, Relation rel);
 | |
| extern void deparseAnalyzeSql(StringInfo buf, Relation rel,
 | |
| 							  PgFdwSamplingMethod sample_method,
 | |
| 							  double sample_frac,
 | |
| 							  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 *rel, 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 */
 |