PostgreSQL Source Code  git master
postgres_fdw.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * postgres_fdw.c
4  * Foreign-data wrapper for remote PostgreSQL servers
5  *
6  * Portions Copyright (c) 2012-2024, PostgreSQL Global Development Group
7  *
8  * IDENTIFICATION
9  * contrib/postgres_fdw/postgres_fdw.c
10  *
11  *-------------------------------------------------------------------------
12  */
13 #include "postgres.h"
14 
15 #include <limits.h>
16 
17 #include "access/htup_details.h"
18 #include "access/sysattr.h"
19 #include "access/table.h"
20 #include "catalog/pg_class.h"
21 #include "catalog/pg_opfamily.h"
22 #include "commands/defrem.h"
23 #include "commands/explain.h"
24 #include "commands/vacuum.h"
25 #include "executor/execAsync.h"
26 #include "foreign/fdwapi.h"
27 #include "funcapi.h"
28 #include "miscadmin.h"
29 #include "nodes/makefuncs.h"
30 #include "nodes/nodeFuncs.h"
31 #include "optimizer/appendinfo.h"
32 #include "optimizer/clauses.h"
33 #include "optimizer/cost.h"
34 #include "optimizer/inherit.h"
35 #include "optimizer/optimizer.h"
36 #include "optimizer/pathnode.h"
37 #include "optimizer/paths.h"
38 #include "optimizer/planmain.h"
39 #include "optimizer/prep.h"
40 #include "optimizer/restrictinfo.h"
41 #include "optimizer/tlist.h"
42 #include "parser/parsetree.h"
43 #include "postgres_fdw.h"
44 #include "storage/latch.h"
45 #include "utils/builtins.h"
46 #include "utils/float.h"
47 #include "utils/guc.h"
48 #include "utils/lsyscache.h"
49 #include "utils/memutils.h"
50 #include "utils/rel.h"
51 #include "utils/sampling.h"
52 #include "utils/selfuncs.h"
53 
55 
56 /* Default CPU cost to start up a foreign query. */
57 #define DEFAULT_FDW_STARTUP_COST 100.0
58 
59 /* Default CPU cost to process 1 row (above and beyond cpu_tuple_cost). */
60 #define DEFAULT_FDW_TUPLE_COST 0.2
61 
62 /* If no remote estimates, assume a sort costs 20% extra */
63 #define DEFAULT_FDW_SORT_MULTIPLIER 1.2
64 
65 /*
66  * Indexes of FDW-private information stored in fdw_private lists.
67  *
68  * These items are indexed with the enum FdwScanPrivateIndex, so an item
69  * can be fetched with list_nth(). For example, to get the SELECT statement:
70  * sql = strVal(list_nth(fdw_private, FdwScanPrivateSelectSql));
71  */
73 {
74  /* SQL statement to execute remotely (as a String node) */
76  /* Integer list of attribute numbers retrieved by the SELECT */
78  /* Integer representing the desired fetch_size */
80 
81  /*
82  * String describing join i.e. names of relations being joined and types
83  * of join, added when the scan is join
84  */
86 };
87 
88 /*
89  * Similarly, this enum describes what's kept in the fdw_private list for
90  * a ModifyTable node referencing a postgres_fdw foreign table. We store:
91  *
92  * 1) INSERT/UPDATE/DELETE statement text to be sent to the remote server
93  * 2) Integer list of target attribute numbers for INSERT/UPDATE
94  * (NIL for a DELETE)
95  * 3) Length till the end of VALUES clause for INSERT
96  * (-1 for a DELETE/UPDATE)
97  * 4) Boolean flag showing if the remote query has a RETURNING clause
98  * 5) Integer list of attribute numbers retrieved by RETURNING, if any
99  */
101 {
102  /* SQL statement to execute remotely (as a String node) */
104  /* Integer list of target attribute numbers for INSERT/UPDATE */
106  /* Length till the end of VALUES clause (as an Integer node) */
108  /* has-returning flag (as a Boolean node) */
110  /* Integer list of attribute numbers retrieved by RETURNING */
112 };
113 
114 /*
115  * Similarly, this enum describes what's kept in the fdw_private list for
116  * a ForeignScan node that modifies a foreign table directly. We store:
117  *
118  * 1) UPDATE/DELETE statement text to be sent to the remote server
119  * 2) Boolean flag showing if the remote query has a RETURNING clause
120  * 3) Integer list of attribute numbers retrieved by RETURNING, if any
121  * 4) Boolean flag showing if we set the command es_processed
122  */
124 {
125  /* SQL statement to execute remotely (as a String node) */
127  /* has-returning flag (as a Boolean node) */
129  /* Integer list of attribute numbers retrieved by RETURNING */
131  /* set-processed flag (as a Boolean node) */
133 };
134 
135 /*
136  * Execution state of a foreign scan using postgres_fdw.
137  */
138 typedef struct PgFdwScanState
139 {
140  Relation rel; /* relcache entry for the foreign table. NULL
141  * for a foreign join scan. */
142  TupleDesc tupdesc; /* tuple descriptor of scan */
143  AttInMetadata *attinmeta; /* attribute datatype conversion metadata */
144 
145  /* extracted fdw_private data */
146  char *query; /* text of SELECT command */
147  List *retrieved_attrs; /* list of retrieved attribute numbers */
148 
149  /* for remote query execution */
150  PGconn *conn; /* connection for the scan */
151  PgFdwConnState *conn_state; /* extra per-connection state */
152  unsigned int cursor_number; /* quasi-unique ID for my cursor */
153  bool cursor_exists; /* have we created the cursor? */
154  int numParams; /* number of parameters passed to query */
155  FmgrInfo *param_flinfo; /* output conversion functions for them */
156  List *param_exprs; /* executable expressions for param values */
157  const char **param_values; /* textual values of query parameters */
158 
159  /* for storing result tuples */
160  HeapTuple *tuples; /* array of currently-retrieved tuples */
161  int num_tuples; /* # of tuples in array */
162  int next_tuple; /* index of next one to return */
163 
164  /* batch-level state, for optimizing rewinds and avoiding useless fetch */
165  int fetch_ct_2; /* Min(# of fetches done, 2) */
166  bool eof_reached; /* true if last fetch reached EOF */
167 
168  /* for asynchronous execution */
169  bool async_capable; /* engage asynchronous-capable logic? */
170 
171  /* working memory contexts */
172  MemoryContext batch_cxt; /* context holding current batch of tuples */
173  MemoryContext temp_cxt; /* context for per-tuple temporary data */
174 
175  int fetch_size; /* number of tuples per fetch */
177 
178 /*
179  * Execution state of a foreign insert/update/delete operation.
180  */
181 typedef struct PgFdwModifyState
182 {
183  Relation rel; /* relcache entry for the foreign table */
184  AttInMetadata *attinmeta; /* attribute datatype conversion metadata */
185 
186  /* for remote query execution */
187  PGconn *conn; /* connection for the scan */
188  PgFdwConnState *conn_state; /* extra per-connection state */
189  char *p_name; /* name of prepared statement, if created */
190 
191  /* extracted fdw_private data */
192  char *query; /* text of INSERT/UPDATE/DELETE command */
193  char *orig_query; /* original text of INSERT command */
194  List *target_attrs; /* list of target attribute numbers */
195  int values_end; /* length up to the end of VALUES */
196  int batch_size; /* value of FDW option "batch_size" */
197  bool has_returning; /* is there a RETURNING clause? */
198  List *retrieved_attrs; /* attr numbers retrieved by RETURNING */
199 
200  /* info about parameters for prepared statement */
201  AttrNumber ctidAttno; /* attnum of input resjunk ctid column */
202  int p_nums; /* number of parameters to transmit */
203  FmgrInfo *p_flinfo; /* output conversion functions for them */
204 
205  /* batch operation stuff */
206  int num_slots; /* number of slots to insert */
207 
208  /* working memory context */
209  MemoryContext temp_cxt; /* context for per-tuple temporary data */
210 
211  /* for update row movement if subplan result rel */
212  struct PgFdwModifyState *aux_fmstate; /* foreign-insert state, if
213  * created */
215 
216 /*
217  * Execution state of a foreign scan that modifies a foreign table directly.
218  */
220 {
221  Relation rel; /* relcache entry for the foreign table */
222  AttInMetadata *attinmeta; /* attribute datatype conversion metadata */
223 
224  /* extracted fdw_private data */
225  char *query; /* text of UPDATE/DELETE command */
226  bool has_returning; /* is there a RETURNING clause? */
227  List *retrieved_attrs; /* attr numbers retrieved by RETURNING */
228  bool set_processed; /* do we set the command es_processed? */
229 
230  /* for remote query execution */
231  PGconn *conn; /* connection for the update */
232  PgFdwConnState *conn_state; /* extra per-connection state */
233  int numParams; /* number of parameters passed to query */
234  FmgrInfo *param_flinfo; /* output conversion functions for them */
235  List *param_exprs; /* executable expressions for param values */
236  const char **param_values; /* textual values of query parameters */
237 
238  /* for storing result tuples */
239  PGresult *result; /* result for query */
240  int num_tuples; /* # of result tuples */
241  int next_tuple; /* index of next one to return */
242  Relation resultRel; /* relcache entry for the target relation */
243  AttrNumber *attnoMap; /* array of attnums of input user columns */
244  AttrNumber ctidAttno; /* attnum of input ctid column */
245  AttrNumber oidAttno; /* attnum of input oid column */
246  bool hasSystemCols; /* are there system columns of resultRel? */
247 
248  /* working memory context */
249  MemoryContext temp_cxt; /* context for per-tuple temporary data */
251 
252 /*
253  * Workspace for analyzing a foreign table.
254  */
255 typedef struct PgFdwAnalyzeState
256 {
257  Relation rel; /* relcache entry for the foreign table */
258  AttInMetadata *attinmeta; /* attribute datatype conversion metadata */
259  List *retrieved_attrs; /* attr numbers retrieved by query */
260 
261  /* collected sample rows */
262  HeapTuple *rows; /* array of size targrows */
263  int targrows; /* target # of sample rows */
264  int numrows; /* # of sample rows collected */
265 
266  /* for random sampling */
267  double samplerows; /* # of rows fetched */
268  double rowstoskip; /* # of rows to skip before next sample */
269  ReservoirStateData rstate; /* state for reservoir sampling */
270 
271  /* working memory contexts */
272  MemoryContext anl_cxt; /* context for per-analyze lifespan data */
273  MemoryContext temp_cxt; /* context for per-tuple temporary data */
275 
276 /*
277  * This enum describes what's kept in the fdw_private list for a ForeignPath.
278  * We store:
279  *
280  * 1) Boolean flag showing if the remote query has the final sort
281  * 2) Boolean flag showing if the remote query has the LIMIT clause
282  */
284 {
285  /* has-final-sort flag (as a Boolean node) */
287  /* has-limit flag (as a Boolean node) */
289 };
290 
291 /* Struct for extra information passed to estimate_path_cost_size() */
292 typedef struct
293 {
296  bool has_limit;
297  double limit_tuples;
298  int64 count_est;
299  int64 offset_est;
301 
302 /*
303  * Identify the attribute where data conversion fails.
304  */
305 typedef struct ConversionLocation
306 {
307  AttrNumber cur_attno; /* attribute number being processed, or 0 */
308  Relation rel; /* foreign table being processed, or NULL */
309  ForeignScanState *fsstate; /* plan node being processed, or NULL */
311 
312 /* Callback argument for ec_member_matches_foreign */
313 typedef struct
314 {
315  Expr *current; /* current expr, or NULL if not yet found */
316  List *already_used; /* expressions already dealt with */
318 
319 /*
320  * SQL functions
321  */
323 
324 /*
325  * FDW callback routines
326  */
328  RelOptInfo *baserel,
329  Oid foreigntableid);
331  RelOptInfo *baserel,
332  Oid foreigntableid);
334  RelOptInfo *foreignrel,
335  Oid foreigntableid,
336  ForeignPath *best_path,
337  List *tlist,
338  List *scan_clauses,
339  Plan *outer_plan);
340 static void postgresBeginForeignScan(ForeignScanState *node, int eflags);
343 static void postgresEndForeignScan(ForeignScanState *node);
345  Index rtindex,
346  RangeTblEntry *target_rte,
347  Relation target_relation);
349  ModifyTable *plan,
350  Index resultRelation,
351  int subplan_index);
352 static void postgresBeginForeignModify(ModifyTableState *mtstate,
353  ResultRelInfo *resultRelInfo,
354  List *fdw_private,
355  int subplan_index,
356  int eflags);
358  ResultRelInfo *resultRelInfo,
359  TupleTableSlot *slot,
360  TupleTableSlot *planSlot);
362  ResultRelInfo *resultRelInfo,
363  TupleTableSlot **slots,
364  TupleTableSlot **planSlots,
365  int *numSlots);
366 static int postgresGetForeignModifyBatchSize(ResultRelInfo *resultRelInfo);
368  ResultRelInfo *resultRelInfo,
369  TupleTableSlot *slot,
370  TupleTableSlot *planSlot);
372  ResultRelInfo *resultRelInfo,
373  TupleTableSlot *slot,
374  TupleTableSlot *planSlot);
375 static void postgresEndForeignModify(EState *estate,
376  ResultRelInfo *resultRelInfo);
377 static void postgresBeginForeignInsert(ModifyTableState *mtstate,
378  ResultRelInfo *resultRelInfo);
379 static void postgresEndForeignInsert(EState *estate,
380  ResultRelInfo *resultRelInfo);
383  ModifyTable *plan,
384  Index resultRelation,
385  int subplan_index);
386 static void postgresBeginDirectModify(ForeignScanState *node, int eflags);
388 static void postgresEndDirectModify(ForeignScanState *node);
390  ExplainState *es);
392  ResultRelInfo *rinfo,
393  List *fdw_private,
394  int subplan_index,
395  ExplainState *es);
397  ExplainState *es);
398 static void postgresExecForeignTruncate(List *rels,
399  DropBehavior behavior,
400  bool restart_seqs);
401 static bool postgresAnalyzeForeignTable(Relation relation,
402  AcquireSampleRowsFunc *func,
403  BlockNumber *totalpages);
405  Oid serverOid);
407  RelOptInfo *joinrel,
408  RelOptInfo *outerrel,
409  RelOptInfo *innerrel,
410  JoinType jointype,
411  JoinPathExtraData *extra);
413  TupleTableSlot *slot);
415  UpperRelationKind stage,
416  RelOptInfo *input_rel,
417  RelOptInfo *output_rel,
418  void *extra);
420 static void postgresForeignAsyncRequest(AsyncRequest *areq);
422 static void postgresForeignAsyncNotify(AsyncRequest *areq);
423 
424 /*
425  * Helper functions
426  */
428  RelOptInfo *foreignrel,
429  List *param_join_conds,
430  List *pathkeys,
431  PgFdwPathExtraData *fpextra,
432  double *p_rows, int *p_width,
433  int *p_disabled_nodes,
434  Cost *p_startup_cost, Cost *p_total_cost);
435 static void get_remote_estimate(const char *sql,
436  PGconn *conn,
437  double *rows,
438  int *width,
439  Cost *startup_cost,
440  Cost *total_cost);
442  List *pathkeys,
443  double retrieved_rows,
444  double width,
445  double limit_tuples,
446  int *disabled_nodes,
447  Cost *p_startup_cost,
448  Cost *p_run_cost);
451  void *arg);
452 static void create_cursor(ForeignScanState *node);
453 static void fetch_more_data(ForeignScanState *node);
454 static void close_cursor(PGconn *conn, unsigned int cursor_number,
455  PgFdwConnState *conn_state);
457  RangeTblEntry *rte,
458  ResultRelInfo *resultRelInfo,
459  CmdType operation,
460  Plan *subplan,
461  char *query,
462  List *target_attrs,
463  int values_end,
464  bool has_returning,
465  List *retrieved_attrs);
467  ResultRelInfo *resultRelInfo,
468  CmdType operation,
469  TupleTableSlot **slots,
470  TupleTableSlot **planSlots,
471  int *numSlots);
472 static void prepare_foreign_modify(PgFdwModifyState *fmstate);
473 static const char **convert_prep_stmt_params(PgFdwModifyState *fmstate,
474  ItemPointer tupleid,
475  TupleTableSlot **slots,
476  int numSlots);
477 static void store_returning_result(PgFdwModifyState *fmstate,
478  TupleTableSlot *slot, PGresult *res);
479 static void finish_foreign_modify(PgFdwModifyState *fmstate);
480 static void deallocate_query(PgFdwModifyState *fmstate);
481 static List *build_remote_returning(Index rtindex, Relation rel,
482  List *returningList);
483 static void rebuild_fdw_scan_tlist(ForeignScan *fscan, List *tlist);
484 static void execute_dml_stmt(ForeignScanState *node);
486 static void init_returning_filter(PgFdwDirectModifyState *dmstate,
487  List *fdw_scan_tlist,
488  Index rtindex);
490  ResultRelInfo *resultRelInfo,
491  TupleTableSlot *slot,
492  EState *estate);
493 static void prepare_query_params(PlanState *node,
494  List *fdw_exprs,
495  int numParams,
496  FmgrInfo **param_flinfo,
497  List **param_exprs,
498  const char ***param_values);
499 static void process_query_params(ExprContext *econtext,
500  FmgrInfo *param_flinfo,
501  List *param_exprs,
502  const char **param_values);
503 static int postgresAcquireSampleRowsFunc(Relation relation, int elevel,
504  HeapTuple *rows, int targrows,
505  double *totalrows,
506  double *totaldeadrows);
507 static void analyze_row_processor(PGresult *res, int row,
508  PgFdwAnalyzeState *astate);
509 static void produce_tuple_asynchronously(AsyncRequest *areq, bool fetch);
510 static void fetch_more_data_begin(AsyncRequest *areq);
511 static void complete_pending_request(AsyncRequest *areq);
513  int row,
514  Relation rel,
515  AttInMetadata *attinmeta,
516  List *retrieved_attrs,
517  ForeignScanState *fsstate,
518  MemoryContext temp_context);
519 static void conversion_error_callback(void *arg);
520 static bool foreign_join_ok(PlannerInfo *root, RelOptInfo *joinrel,
521  JoinType jointype, RelOptInfo *outerrel, RelOptInfo *innerrel,
522  JoinPathExtraData *extra);
523 static bool foreign_grouping_ok(PlannerInfo *root, RelOptInfo *grouped_rel,
524  Node *havingQual);
526  RelOptInfo *rel);
529  Path *epq_path, List *restrictlist);
531  RelOptInfo *input_rel,
532  RelOptInfo *grouped_rel,
533  GroupPathExtraData *extra);
535  RelOptInfo *input_rel,
536  RelOptInfo *ordered_rel);
538  RelOptInfo *input_rel,
539  RelOptInfo *final_rel,
540  FinalPathExtraData *extra);
541 static void apply_server_options(PgFdwRelationInfo *fpinfo);
542 static void apply_table_options(PgFdwRelationInfo *fpinfo);
543 static void merge_fdw_options(PgFdwRelationInfo *fpinfo,
544  const PgFdwRelationInfo *fpinfo_o,
545  const PgFdwRelationInfo *fpinfo_i);
546 static int get_batch_size_option(Relation rel);
547 
548 
549 /*
550  * Foreign-data wrapper handler function: return a struct with pointers
551  * to my callback routines.
552  */
553 Datum
555 {
556  FdwRoutine *routine = makeNode(FdwRoutine);
557 
558  /* Functions for scanning foreign tables */
566 
567  /* Functions for updating foreign tables */
584 
585  /* Function for EvalPlanQual rechecks */
587  /* Support functions for EXPLAIN */
591 
592  /* Support function for TRUNCATE */
594 
595  /* Support functions for ANALYZE */
597 
598  /* Support functions for IMPORT FOREIGN SCHEMA */
600 
601  /* Support functions for join push-down */
603 
604  /* Support functions for upper relation push-down */
606 
607  /* Support functions for asynchronous execution */
612 
613  PG_RETURN_POINTER(routine);
614 }
615 
616 /*
617  * postgresGetForeignRelSize
618  * Estimate # of rows and width of the result of the scan
619  *
620  * We should consider the effect of all baserestrictinfo clauses here, but
621  * not any join clauses.
622  */
623 static void
625  RelOptInfo *baserel,
626  Oid foreigntableid)
627 {
628  PgFdwRelationInfo *fpinfo;
629  ListCell *lc;
630 
631  /*
632  * We use PgFdwRelationInfo to pass various information to subsequent
633  * functions.
634  */
635  fpinfo = (PgFdwRelationInfo *) palloc0(sizeof(PgFdwRelationInfo));
636  baserel->fdw_private = (void *) fpinfo;
637 
638  /* Base foreign tables need to be pushed down always. */
639  fpinfo->pushdown_safe = true;
640 
641  /* Look up foreign-table catalog info. */
642  fpinfo->table = GetForeignTable(foreigntableid);
643  fpinfo->server = GetForeignServer(fpinfo->table->serverid);
644 
645  /*
646  * Extract user-settable option values. Note that per-table settings of
647  * use_remote_estimate, fetch_size and async_capable override per-server
648  * settings of them, respectively.
649  */
650  fpinfo->use_remote_estimate = false;
653  fpinfo->shippable_extensions = NIL;
654  fpinfo->fetch_size = 100;
655  fpinfo->async_capable = false;
656 
657  apply_server_options(fpinfo);
658  apply_table_options(fpinfo);
659 
660  /*
661  * If the table or the server is configured to use remote estimates,
662  * identify which user to do remote access as during planning. This
663  * should match what ExecCheckPermissions() does. If we fail due to lack
664  * of permissions, the query would have failed at runtime anyway.
665  */
666  if (fpinfo->use_remote_estimate)
667  {
668  Oid userid;
669 
670  userid = OidIsValid(baserel->userid) ? baserel->userid : GetUserId();
671  fpinfo->user = GetUserMapping(userid, fpinfo->server->serverid);
672  }
673  else
674  fpinfo->user = NULL;
675 
676  /*
677  * Identify which baserestrictinfo clauses can be sent to the remote
678  * server and which can't.
679  */
680  classifyConditions(root, baserel, baserel->baserestrictinfo,
681  &fpinfo->remote_conds, &fpinfo->local_conds);
682 
683  /*
684  * Identify which attributes will need to be retrieved from the remote
685  * server. These include all attrs needed for joins or final output, plus
686  * all attrs used in the local_conds. (Note: if we end up using a
687  * parameterized scan, it's possible that some of the join clauses will be
688  * sent to the remote and thus we wouldn't really need to retrieve the
689  * columns used in them. Doesn't seem worth detecting that case though.)
690  */
691  fpinfo->attrs_used = NULL;
692  pull_varattnos((Node *) baserel->reltarget->exprs, baserel->relid,
693  &fpinfo->attrs_used);
694  foreach(lc, fpinfo->local_conds)
695  {
696  RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
697 
698  pull_varattnos((Node *) rinfo->clause, baserel->relid,
699  &fpinfo->attrs_used);
700  }
701 
702  /*
703  * Compute the selectivity and cost of the local_conds, so we don't have
704  * to do it over again for each path. The best we can do for these
705  * conditions is to estimate selectivity on the basis of local statistics.
706  */
708  fpinfo->local_conds,
709  baserel->relid,
710  JOIN_INNER,
711  NULL);
712 
713  cost_qual_eval(&fpinfo->local_conds_cost, fpinfo->local_conds, root);
714 
715  /*
716  * Set # of retrieved rows and cached relation costs to some negative
717  * value, so that we can detect when they are set to some sensible values,
718  * during one (usually the first) of the calls to estimate_path_cost_size.
719  */
720  fpinfo->retrieved_rows = -1;
721  fpinfo->rel_startup_cost = -1;
722  fpinfo->rel_total_cost = -1;
723 
724  /*
725  * If the table or the server is configured to use remote estimates,
726  * connect to the foreign server and execute EXPLAIN to estimate the
727  * number of rows selected by the restriction clauses, as well as the
728  * average row width. Otherwise, estimate using whatever statistics we
729  * have locally, in a way similar to ordinary tables.
730  */
731  if (fpinfo->use_remote_estimate)
732  {
733  /*
734  * Get cost/size estimates with help of remote server. Save the
735  * values in fpinfo so we don't need to do it again to generate the
736  * basic foreign path.
737  */
738  estimate_path_cost_size(root, baserel, NIL, NIL, NULL,
739  &fpinfo->rows, &fpinfo->width,
740  &fpinfo->disabled_nodes,
741  &fpinfo->startup_cost, &fpinfo->total_cost);
742 
743  /* Report estimated baserel size to planner. */
744  baserel->rows = fpinfo->rows;
745  baserel->reltarget->width = fpinfo->width;
746  }
747  else
748  {
749  /*
750  * If the foreign table has never been ANALYZEd, it will have
751  * reltuples < 0, meaning "unknown". We can't do much if we're not
752  * allowed to consult the remote server, but we can use a hack similar
753  * to plancat.c's treatment of empty relations: use a minimum size
754  * estimate of 10 pages, and divide by the column-datatype-based width
755  * estimate to get the corresponding number of tuples.
756  */
757  if (baserel->tuples < 0)
758  {
759  baserel->pages = 10;
760  baserel->tuples =
761  (10 * BLCKSZ) / (baserel->reltarget->width +
763  }
764 
765  /* Estimate baserel size as best we can with local statistics. */
767 
768  /* Fill in basically-bogus cost estimates for use later. */
769  estimate_path_cost_size(root, baserel, NIL, NIL, NULL,
770  &fpinfo->rows, &fpinfo->width,
771  &fpinfo->disabled_nodes,
772  &fpinfo->startup_cost, &fpinfo->total_cost);
773  }
774 
775  /*
776  * fpinfo->relation_name gets the numeric rangetable index of the foreign
777  * table RTE. (If this query gets EXPLAIN'd, we'll convert that to a
778  * human-readable string at that time.)
779  */
780  fpinfo->relation_name = psprintf("%u", baserel->relid);
781 
782  /* No outer and inner relations. */
783  fpinfo->make_outerrel_subquery = false;
784  fpinfo->make_innerrel_subquery = false;
785  fpinfo->lower_subquery_rels = NULL;
786  fpinfo->hidden_subquery_rels = NULL;
787  /* Set the relation index. */
788  fpinfo->relation_index = baserel->relid;
789 }
790 
791 /*
792  * get_useful_ecs_for_relation
793  * Determine which EquivalenceClasses might be involved in useful
794  * orderings of this relation.
795  *
796  * This function is in some respects a mirror image of the core function
797  * pathkeys_useful_for_merging: for a regular table, we know what indexes
798  * we have and want to test whether any of them are useful. For a foreign
799  * table, we don't know what indexes are present on the remote side but
800  * want to speculate about which ones we'd like to use if they existed.
801  *
802  * This function returns a list of potentially-useful equivalence classes,
803  * but it does not guarantee that an EquivalenceMember exists which contains
804  * Vars only from the given relation. For example, given ft1 JOIN t1 ON
805  * ft1.x + t1.x = 0, this function will say that the equivalence class
806  * containing ft1.x + t1.x is potentially useful. Supposing ft1 is remote and
807  * t1 is local (or on a different server), it will turn out that no useful
808  * ORDER BY clause can be generated. It's not our job to figure that out
809  * here; we're only interested in identifying relevant ECs.
810  */
811 static List *
813 {
814  List *useful_eclass_list = NIL;
815  ListCell *lc;
816  Relids relids;
817 
818  /*
819  * First, consider whether any active EC is potentially useful for a merge
820  * join against this relation.
821  */
822  if (rel->has_eclass_joins)
823  {
824  foreach(lc, root->eq_classes)
825  {
826  EquivalenceClass *cur_ec = (EquivalenceClass *) lfirst(lc);
827 
828  if (eclass_useful_for_merging(root, cur_ec, rel))
829  useful_eclass_list = lappend(useful_eclass_list, cur_ec);
830  }
831  }
832 
833  /*
834  * Next, consider whether there are any non-EC derivable join clauses that
835  * are merge-joinable. If the joininfo list is empty, we can exit
836  * quickly.
837  */
838  if (rel->joininfo == NIL)
839  return useful_eclass_list;
840 
841  /* If this is a child rel, we must use the topmost parent rel to search. */
842  if (IS_OTHER_REL(rel))
843  {
845  relids = rel->top_parent_relids;
846  }
847  else
848  relids = rel->relids;
849 
850  /* Check each join clause in turn. */
851  foreach(lc, rel->joininfo)
852  {
853  RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(lc);
854 
855  /* Consider only mergejoinable clauses */
856  if (restrictinfo->mergeopfamilies == NIL)
857  continue;
858 
859  /* Make sure we've got canonical ECs. */
860  update_mergeclause_eclasses(root, restrictinfo);
861 
862  /*
863  * restrictinfo->mergeopfamilies != NIL is sufficient to guarantee
864  * that left_ec and right_ec will be initialized, per comments in
865  * distribute_qual_to_rels.
866  *
867  * We want to identify which side of this merge-joinable clause
868  * contains columns from the relation produced by this RelOptInfo. We
869  * test for overlap, not containment, because there could be extra
870  * relations on either side. For example, suppose we've got something
871  * like ((A JOIN B ON A.x = B.x) JOIN C ON A.y = C.y) LEFT JOIN D ON
872  * A.y = D.y. The input rel might be the joinrel between A and B, and
873  * we'll consider the join clause A.y = D.y. relids contains a
874  * relation not involved in the join class (B) and the equivalence
875  * class for the left-hand side of the clause contains a relation not
876  * involved in the input rel (C). Despite the fact that we have only
877  * overlap and not containment in either direction, A.y is potentially
878  * useful as a sort column.
879  *
880  * Note that it's even possible that relids overlaps neither side of
881  * the join clause. For example, consider A LEFT JOIN B ON A.x = B.x
882  * AND A.x = 1. The clause A.x = 1 will appear in B's joininfo list,
883  * but overlaps neither side of B. In that case, we just skip this
884  * join clause, since it doesn't suggest a useful sort order for this
885  * relation.
886  */
887  if (bms_overlap(relids, restrictinfo->right_ec->ec_relids))
888  useful_eclass_list = list_append_unique_ptr(useful_eclass_list,
889  restrictinfo->right_ec);
890  else if (bms_overlap(relids, restrictinfo->left_ec->ec_relids))
891  useful_eclass_list = list_append_unique_ptr(useful_eclass_list,
892  restrictinfo->left_ec);
893  }
894 
895  return useful_eclass_list;
896 }
897 
898 /*
899  * get_useful_pathkeys_for_relation
900  * Determine which orderings of a relation might be useful.
901  *
902  * Getting data in sorted order can be useful either because the requested
903  * order matches the final output ordering for the overall query we're
904  * planning, or because it enables an efficient merge join. Here, we try
905  * to figure out which pathkeys to consider.
906  */
907 static List *
909 {
910  List *useful_pathkeys_list = NIL;
911  List *useful_eclass_list;
912  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) rel->fdw_private;
913  EquivalenceClass *query_ec = NULL;
914  ListCell *lc;
915 
916  /*
917  * Pushing the query_pathkeys to the remote server is always worth
918  * considering, because it might let us avoid a local sort.
919  */
920  fpinfo->qp_is_pushdown_safe = false;
921  if (root->query_pathkeys)
922  {
923  bool query_pathkeys_ok = true;
924 
925  foreach(lc, root->query_pathkeys)
926  {
927  PathKey *pathkey = (PathKey *) lfirst(lc);
928 
929  /*
930  * The planner and executor don't have any clever strategy for
931  * taking data sorted by a prefix of the query's pathkeys and
932  * getting it to be sorted by all of those pathkeys. We'll just
933  * end up resorting the entire data set. So, unless we can push
934  * down all of the query pathkeys, forget it.
935  */
936  if (!is_foreign_pathkey(root, rel, pathkey))
937  {
938  query_pathkeys_ok = false;
939  break;
940  }
941  }
942 
943  if (query_pathkeys_ok)
944  {
945  useful_pathkeys_list = list_make1(list_copy(root->query_pathkeys));
946  fpinfo->qp_is_pushdown_safe = true;
947  }
948  }
949 
950  /*
951  * Even if we're not using remote estimates, having the remote side do the
952  * sort generally won't be any worse than doing it locally, and it might
953  * be much better if the remote side can generate data in the right order
954  * without needing a sort at all. However, what we're going to do next is
955  * try to generate pathkeys that seem promising for possible merge joins,
956  * and that's more speculative. A wrong choice might hurt quite a bit, so
957  * bail out if we can't use remote estimates.
958  */
959  if (!fpinfo->use_remote_estimate)
960  return useful_pathkeys_list;
961 
962  /* Get the list of interesting EquivalenceClasses. */
963  useful_eclass_list = get_useful_ecs_for_relation(root, rel);
964 
965  /* Extract unique EC for query, if any, so we don't consider it again. */
966  if (list_length(root->query_pathkeys) == 1)
967  {
968  PathKey *query_pathkey = linitial(root->query_pathkeys);
969 
970  query_ec = query_pathkey->pk_eclass;
971  }
972 
973  /*
974  * As a heuristic, the only pathkeys we consider here are those of length
975  * one. It's surely possible to consider more, but since each one we
976  * choose to consider will generate a round-trip to the remote side, we
977  * need to be a bit cautious here. It would sure be nice to have a local
978  * cache of information about remote index definitions...
979  */
980  foreach(lc, useful_eclass_list)
981  {
982  EquivalenceClass *cur_ec = lfirst(lc);
983  PathKey *pathkey;
984 
985  /* If redundant with what we did above, skip it. */
986  if (cur_ec == query_ec)
987  continue;
988 
989  /* Can't push down the sort if the EC's opfamily is not shippable. */
991  OperatorFamilyRelationId, fpinfo))
992  continue;
993 
994  /* If no pushable expression for this rel, skip it. */
995  if (find_em_for_rel(root, cur_ec, rel) == NULL)
996  continue;
997 
998  /* Looks like we can generate a pathkey, so let's do it. */
999  pathkey = make_canonical_pathkey(root, cur_ec,
1000  linitial_oid(cur_ec->ec_opfamilies),
1002  false);
1003  useful_pathkeys_list = lappend(useful_pathkeys_list,
1004  list_make1(pathkey));
1005  }
1006 
1007  return useful_pathkeys_list;
1008 }
1009 
1010 /*
1011  * postgresGetForeignPaths
1012  * Create possible scan paths for a scan on the foreign table
1013  */
1014 static void
1016  RelOptInfo *baserel,
1017  Oid foreigntableid)
1018 {
1019  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) baserel->fdw_private;
1020  ForeignPath *path;
1021  List *ppi_list;
1022  ListCell *lc;
1023 
1024  /*
1025  * Create simplest ForeignScan path node and add it to baserel. This path
1026  * corresponds to SeqScan path of regular tables (though depending on what
1027  * baserestrict conditions we were able to send to remote, there might
1028  * actually be an indexscan happening there). We already did all the work
1029  * to estimate cost and size of this path.
1030  *
1031  * Although this path uses no join clauses, it could still have required
1032  * parameterization due to LATERAL refs in its tlist.
1033  */
1034  path = create_foreignscan_path(root, baserel,
1035  NULL, /* default pathtarget */
1036  fpinfo->rows,
1037  fpinfo->disabled_nodes,
1038  fpinfo->startup_cost,
1039  fpinfo->total_cost,
1040  NIL, /* no pathkeys */
1041  baserel->lateral_relids,
1042  NULL, /* no extra plan */
1043  NIL, /* no fdw_restrictinfo list */
1044  NIL); /* no fdw_private list */
1045  add_path(baserel, (Path *) path);
1046 
1047  /* Add paths with pathkeys */
1048  add_paths_with_pathkeys_for_rel(root, baserel, NULL, NIL);
1049 
1050  /*
1051  * If we're not using remote estimates, stop here. We have no way to
1052  * estimate whether any join clauses would be worth sending across, so
1053  * don't bother building parameterized paths.
1054  */
1055  if (!fpinfo->use_remote_estimate)
1056  return;
1057 
1058  /*
1059  * Thumb through all join clauses for the rel to identify which outer
1060  * relations could supply one or more safe-to-send-to-remote join clauses.
1061  * We'll build a parameterized path for each such outer relation.
1062  *
1063  * It's convenient to manage this by representing each candidate outer
1064  * relation by the ParamPathInfo node for it. We can then use the
1065  * ppi_clauses list in the ParamPathInfo node directly as a list of the
1066  * interesting join clauses for that rel. This takes care of the
1067  * possibility that there are multiple safe join clauses for such a rel,
1068  * and also ensures that we account for unsafe join clauses that we'll
1069  * still have to enforce locally (since the parameterized-path machinery
1070  * insists that we handle all movable clauses).
1071  */
1072  ppi_list = NIL;
1073  foreach(lc, baserel->joininfo)
1074  {
1075  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1076  Relids required_outer;
1077  ParamPathInfo *param_info;
1078 
1079  /* Check if clause can be moved to this rel */
1080  if (!join_clause_is_movable_to(rinfo, baserel))
1081  continue;
1082 
1083  /* See if it is safe to send to remote */
1084  if (!is_foreign_expr(root, baserel, rinfo->clause))
1085  continue;
1086 
1087  /* Calculate required outer rels for the resulting path */
1088  required_outer = bms_union(rinfo->clause_relids,
1089  baserel->lateral_relids);
1090  /* We do not want the foreign rel itself listed in required_outer */
1091  required_outer = bms_del_member(required_outer, baserel->relid);
1092 
1093  /*
1094  * required_outer probably can't be empty here, but if it were, we
1095  * couldn't make a parameterized path.
1096  */
1097  if (bms_is_empty(required_outer))
1098  continue;
1099 
1100  /* Get the ParamPathInfo */
1101  param_info = get_baserel_parampathinfo(root, baserel,
1102  required_outer);
1103  Assert(param_info != NULL);
1104 
1105  /*
1106  * Add it to list unless we already have it. Testing pointer equality
1107  * is OK since get_baserel_parampathinfo won't make duplicates.
1108  */
1109  ppi_list = list_append_unique_ptr(ppi_list, param_info);
1110  }
1111 
1112  /*
1113  * The above scan examined only "generic" join clauses, not those that
1114  * were absorbed into EquivalenceClauses. See if we can make anything out
1115  * of EquivalenceClauses.
1116  */
1117  if (baserel->has_eclass_joins)
1118  {
1119  /*
1120  * We repeatedly scan the eclass list looking for column references
1121  * (or expressions) belonging to the foreign rel. Each time we find
1122  * one, we generate a list of equivalence joinclauses for it, and then
1123  * see if any are safe to send to the remote. Repeat till there are
1124  * no more candidate EC members.
1125  */
1127 
1128  arg.already_used = NIL;
1129  for (;;)
1130  {
1131  List *clauses;
1132 
1133  /* Make clauses, skipping any that join to lateral_referencers */
1134  arg.current = NULL;
1136  baserel,
1138  (void *) &arg,
1139  baserel->lateral_referencers);
1140 
1141  /* Done if there are no more expressions in the foreign rel */
1142  if (arg.current == NULL)
1143  {
1144  Assert(clauses == NIL);
1145  break;
1146  }
1147 
1148  /* Scan the extracted join clauses */
1149  foreach(lc, clauses)
1150  {
1151  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1152  Relids required_outer;
1153  ParamPathInfo *param_info;
1154 
1155  /* Check if clause can be moved to this rel */
1156  if (!join_clause_is_movable_to(rinfo, baserel))
1157  continue;
1158 
1159  /* See if it is safe to send to remote */
1160  if (!is_foreign_expr(root, baserel, rinfo->clause))
1161  continue;
1162 
1163  /* Calculate required outer rels for the resulting path */
1164  required_outer = bms_union(rinfo->clause_relids,
1165  baserel->lateral_relids);
1166  required_outer = bms_del_member(required_outer, baserel->relid);
1167  if (bms_is_empty(required_outer))
1168  continue;
1169 
1170  /* Get the ParamPathInfo */
1171  param_info = get_baserel_parampathinfo(root, baserel,
1172  required_outer);
1173  Assert(param_info != NULL);
1174 
1175  /* Add it to list unless we already have it */
1176  ppi_list = list_append_unique_ptr(ppi_list, param_info);
1177  }
1178 
1179  /* Try again, now ignoring the expression we found this time */
1180  arg.already_used = lappend(arg.already_used, arg.current);
1181  }
1182  }
1183 
1184  /*
1185  * Now build a path for each useful outer relation.
1186  */
1187  foreach(lc, ppi_list)
1188  {
1189  ParamPathInfo *param_info = (ParamPathInfo *) lfirst(lc);
1190  double rows;
1191  int width;
1192  int disabled_nodes;
1193  Cost startup_cost;
1194  Cost total_cost;
1195 
1196  /* Get a cost estimate from the remote */
1197  estimate_path_cost_size(root, baserel,
1198  param_info->ppi_clauses, NIL, NULL,
1199  &rows, &width, &disabled_nodes,
1200  &startup_cost, &total_cost);
1201 
1202  /*
1203  * ppi_rows currently won't get looked at by anything, but still we
1204  * may as well ensure that it matches our idea of the rowcount.
1205  */
1206  param_info->ppi_rows = rows;
1207 
1208  /* Make the path */
1209  path = create_foreignscan_path(root, baserel,
1210  NULL, /* default pathtarget */
1211  rows,
1212  disabled_nodes,
1213  startup_cost,
1214  total_cost,
1215  NIL, /* no pathkeys */
1216  param_info->ppi_req_outer,
1217  NULL,
1218  NIL, /* no fdw_restrictinfo list */
1219  NIL); /* no fdw_private list */
1220  add_path(baserel, (Path *) path);
1221  }
1222 }
1223 
1224 /*
1225  * postgresGetForeignPlan
1226  * Create ForeignScan plan node which implements selected best path
1227  */
1228 static ForeignScan *
1230  RelOptInfo *foreignrel,
1231  Oid foreigntableid,
1232  ForeignPath *best_path,
1233  List *tlist,
1234  List *scan_clauses,
1235  Plan *outer_plan)
1236 {
1237  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
1238  Index scan_relid;
1239  List *fdw_private;
1240  List *remote_exprs = NIL;
1241  List *local_exprs = NIL;
1242  List *params_list = NIL;
1243  List *fdw_scan_tlist = NIL;
1244  List *fdw_recheck_quals = NIL;
1245  List *retrieved_attrs;
1246  StringInfoData sql;
1247  bool has_final_sort = false;
1248  bool has_limit = false;
1249  ListCell *lc;
1250 
1251  /*
1252  * Get FDW private data created by postgresGetForeignUpperPaths(), if any.
1253  */
1254  if (best_path->fdw_private)
1255  {
1256  has_final_sort = boolVal(list_nth(best_path->fdw_private,
1258  has_limit = boolVal(list_nth(best_path->fdw_private,
1260  }
1261 
1262  if (IS_SIMPLE_REL(foreignrel))
1263  {
1264  /*
1265  * For base relations, set scan_relid as the relid of the relation.
1266  */
1267  scan_relid = foreignrel->relid;
1268 
1269  /*
1270  * In a base-relation scan, we must apply the given scan_clauses.
1271  *
1272  * Separate the scan_clauses into those that can be executed remotely
1273  * and those that can't. baserestrictinfo clauses that were
1274  * previously determined to be safe or unsafe by classifyConditions
1275  * are found in fpinfo->remote_conds and fpinfo->local_conds. Anything
1276  * else in the scan_clauses list will be a join clause, which we have
1277  * to check for remote-safety.
1278  *
1279  * Note: the join clauses we see here should be the exact same ones
1280  * previously examined by postgresGetForeignPaths. Possibly it'd be
1281  * worth passing forward the classification work done then, rather
1282  * than repeating it here.
1283  *
1284  * This code must match "extract_actual_clauses(scan_clauses, false)"
1285  * except for the additional decision about remote versus local
1286  * execution.
1287  */
1288  foreach(lc, scan_clauses)
1289  {
1290  RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
1291 
1292  /* Ignore any pseudoconstants, they're dealt with elsewhere */
1293  if (rinfo->pseudoconstant)
1294  continue;
1295 
1296  if (list_member_ptr(fpinfo->remote_conds, rinfo))
1297  remote_exprs = lappend(remote_exprs, rinfo->clause);
1298  else if (list_member_ptr(fpinfo->local_conds, rinfo))
1299  local_exprs = lappend(local_exprs, rinfo->clause);
1300  else if (is_foreign_expr(root, foreignrel, rinfo->clause))
1301  remote_exprs = lappend(remote_exprs, rinfo->clause);
1302  else
1303  local_exprs = lappend(local_exprs, rinfo->clause);
1304  }
1305 
1306  /*
1307  * For a base-relation scan, we have to support EPQ recheck, which
1308  * should recheck all the remote quals.
1309  */
1310  fdw_recheck_quals = remote_exprs;
1311  }
1312  else
1313  {
1314  /*
1315  * Join relation or upper relation - set scan_relid to 0.
1316  */
1317  scan_relid = 0;
1318 
1319  /*
1320  * For a join rel, baserestrictinfo is NIL and we are not considering
1321  * parameterization right now, so there should be no scan_clauses for
1322  * a joinrel or an upper rel either.
1323  */
1324  Assert(!scan_clauses);
1325 
1326  /*
1327  * Instead we get the conditions to apply from the fdw_private
1328  * structure.
1329  */
1330  remote_exprs = extract_actual_clauses(fpinfo->remote_conds, false);
1331  local_exprs = extract_actual_clauses(fpinfo->local_conds, false);
1332 
1333  /*
1334  * We leave fdw_recheck_quals empty in this case, since we never need
1335  * to apply EPQ recheck clauses. In the case of a joinrel, EPQ
1336  * recheck is handled elsewhere --- see postgresGetForeignJoinPaths().
1337  * If we're planning an upperrel (ie, remote grouping or aggregation)
1338  * then there's no EPQ to do because SELECT FOR UPDATE wouldn't be
1339  * allowed, and indeed we *can't* put the remote clauses into
1340  * fdw_recheck_quals because the unaggregated Vars won't be available
1341  * locally.
1342  */
1343 
1344  /* Build the list of columns to be fetched from the foreign server. */
1345  fdw_scan_tlist = build_tlist_to_deparse(foreignrel);
1346 
1347  /*
1348  * Ensure that the outer plan produces a tuple whose descriptor
1349  * matches our scan tuple slot. Also, remove the local conditions
1350  * from outer plan's quals, lest they be evaluated twice, once by the
1351  * local plan and once by the scan.
1352  */
1353  if (outer_plan)
1354  {
1355  /*
1356  * Right now, we only consider grouping and aggregation beyond
1357  * joins. Queries involving aggregates or grouping do not require
1358  * EPQ mechanism, hence should not have an outer plan here.
1359  */
1360  Assert(!IS_UPPER_REL(foreignrel));
1361 
1362  /*
1363  * First, update the plan's qual list if possible. In some cases
1364  * the quals might be enforced below the topmost plan level, in
1365  * which case we'll fail to remove them; it's not worth working
1366  * harder than this.
1367  */
1368  foreach(lc, local_exprs)
1369  {
1370  Node *qual = lfirst(lc);
1371 
1372  outer_plan->qual = list_delete(outer_plan->qual, qual);
1373 
1374  /*
1375  * For an inner join the local conditions of foreign scan plan
1376  * can be part of the joinquals as well. (They might also be
1377  * in the mergequals or hashquals, but we can't touch those
1378  * without breaking the plan.)
1379  */
1380  if (IsA(outer_plan, NestLoop) ||
1381  IsA(outer_plan, MergeJoin) ||
1382  IsA(outer_plan, HashJoin))
1383  {
1384  Join *join_plan = (Join *) outer_plan;
1385 
1386  if (join_plan->jointype == JOIN_INNER)
1387  join_plan->joinqual = list_delete(join_plan->joinqual,
1388  qual);
1389  }
1390  }
1391 
1392  /*
1393  * Now fix the subplan's tlist --- this might result in inserting
1394  * a Result node atop the plan tree.
1395  */
1396  outer_plan = change_plan_targetlist(outer_plan, fdw_scan_tlist,
1397  best_path->path.parallel_safe);
1398  }
1399  }
1400 
1401  /*
1402  * Build the query string to be sent for execution, and identify
1403  * expressions to be sent as parameters.
1404  */
1405  initStringInfo(&sql);
1406  deparseSelectStmtForRel(&sql, root, foreignrel, fdw_scan_tlist,
1407  remote_exprs, best_path->path.pathkeys,
1408  has_final_sort, has_limit, false,
1409  &retrieved_attrs, &params_list);
1410 
1411  /* Remember remote_exprs for possible use by postgresPlanDirectModify */
1412  fpinfo->final_remote_exprs = remote_exprs;
1413 
1414  /*
1415  * Build the fdw_private list that will be available to the executor.
1416  * Items in the list must match order in enum FdwScanPrivateIndex.
1417  */
1418  fdw_private = list_make3(makeString(sql.data),
1419  retrieved_attrs,
1420  makeInteger(fpinfo->fetch_size));
1421  if (IS_JOIN_REL(foreignrel) || IS_UPPER_REL(foreignrel))
1422  fdw_private = lappend(fdw_private,
1423  makeString(fpinfo->relation_name));
1424 
1425  /*
1426  * Create the ForeignScan node for the given relation.
1427  *
1428  * Note that the remote parameter expressions are stored in the fdw_exprs
1429  * field of the finished plan node; we can't keep them in private state
1430  * because then they wouldn't be subject to later planner processing.
1431  */
1432  return make_foreignscan(tlist,
1433  local_exprs,
1434  scan_relid,
1435  params_list,
1436  fdw_private,
1437  fdw_scan_tlist,
1438  fdw_recheck_quals,
1439  outer_plan);
1440 }
1441 
1442 /*
1443  * Construct a tuple descriptor for the scan tuples handled by a foreign join.
1444  */
1445 static TupleDesc
1447 {
1448  ForeignScan *fsplan = (ForeignScan *) node->ss.ps.plan;
1449  EState *estate = node->ss.ps.state;
1450  TupleDesc tupdesc;
1451 
1452  /*
1453  * The core code has already set up a scan tuple slot based on
1454  * fsplan->fdw_scan_tlist, and this slot's tupdesc is mostly good enough,
1455  * but there's one case where it isn't. If we have any whole-row row
1456  * identifier Vars, they may have vartype RECORD, and we need to replace
1457  * that with the associated table's actual composite type. This ensures
1458  * that when we read those ROW() expression values from the remote server,
1459  * we can convert them to a composite type the local server knows.
1460  */
1462  for (int i = 0; i < tupdesc->natts; i++)
1463  {
1464  Form_pg_attribute att = TupleDescAttr(tupdesc, i);
1465  Var *var;
1466  RangeTblEntry *rte;
1467  Oid reltype;
1468 
1469  /* Nothing to do if it's not a generic RECORD attribute */
1470  if (att->atttypid != RECORDOID || att->atttypmod >= 0)
1471  continue;
1472 
1473  /*
1474  * If we can't identify the referenced table, do nothing. This'll
1475  * likely lead to failure later, but perhaps we can muddle through.
1476  */
1477  var = (Var *) list_nth_node(TargetEntry, fsplan->fdw_scan_tlist,
1478  i)->expr;
1479  if (!IsA(var, Var) || var->varattno != 0)
1480  continue;
1481  rte = list_nth(estate->es_range_table, var->varno - 1);
1482  if (rte->rtekind != RTE_RELATION)
1483  continue;
1484  reltype = get_rel_type_id(rte->relid);
1485  if (!OidIsValid(reltype))
1486  continue;
1487  att->atttypid = reltype;
1488  /* shouldn't need to change anything else */
1489  }
1490  return tupdesc;
1491 }
1492 
1493 /*
1494  * postgresBeginForeignScan
1495  * Initiate an executor scan of a foreign PostgreSQL table.
1496  */
1497 static void
1499 {
1500  ForeignScan *fsplan = (ForeignScan *) node->ss.ps.plan;
1501  EState *estate = node->ss.ps.state;
1502  PgFdwScanState *fsstate;
1503  RangeTblEntry *rte;
1504  Oid userid;
1505  ForeignTable *table;
1506  UserMapping *user;
1507  int rtindex;
1508  int numParams;
1509 
1510  /*
1511  * Do nothing in EXPLAIN (no ANALYZE) case. node->fdw_state stays NULL.
1512  */
1513  if (eflags & EXEC_FLAG_EXPLAIN_ONLY)
1514  return;
1515 
1516  /*
1517  * We'll save private state in node->fdw_state.
1518  */
1519  fsstate = (PgFdwScanState *) palloc0(sizeof(PgFdwScanState));
1520  node->fdw_state = (void *) fsstate;
1521 
1522  /*
1523  * Identify which user to do the remote access as. This should match what
1524  * ExecCheckPermissions() does.
1525  */
1526  userid = OidIsValid(fsplan->checkAsUser) ? fsplan->checkAsUser : GetUserId();
1527  if (fsplan->scan.scanrelid > 0)
1528  rtindex = fsplan->scan.scanrelid;
1529  else
1530  rtindex = bms_next_member(fsplan->fs_base_relids, -1);
1531  rte = exec_rt_fetch(rtindex, estate);
1532 
1533  /* Get info about foreign table. */
1534  table = GetForeignTable(rte->relid);
1535  user = GetUserMapping(userid, table->serverid);
1536 
1537  /*
1538  * Get connection to the foreign server. Connection manager will
1539  * establish new connection if necessary.
1540  */
1541  fsstate->conn = GetConnection(user, false, &fsstate->conn_state);
1542 
1543  /* Assign a unique ID for my cursor */
1544  fsstate->cursor_number = GetCursorNumber(fsstate->conn);
1545  fsstate->cursor_exists = false;
1546 
1547  /* Get private info created by planner functions. */
1548  fsstate->query = strVal(list_nth(fsplan->fdw_private,
1550  fsstate->retrieved_attrs = (List *) list_nth(fsplan->fdw_private,
1552  fsstate->fetch_size = intVal(list_nth(fsplan->fdw_private,
1554 
1555  /* Create contexts for batches of tuples and per-tuple temp workspace. */
1556  fsstate->batch_cxt = AllocSetContextCreate(estate->es_query_cxt,
1557  "postgres_fdw tuple data",
1559  fsstate->temp_cxt = AllocSetContextCreate(estate->es_query_cxt,
1560  "postgres_fdw temporary data",
1562 
1563  /*
1564  * Get info we'll need for converting data fetched from the foreign server
1565  * into local representation and error reporting during that process.
1566  */
1567  if (fsplan->scan.scanrelid > 0)
1568  {
1569  fsstate->rel = node->ss.ss_currentRelation;
1570  fsstate->tupdesc = RelationGetDescr(fsstate->rel);
1571  }
1572  else
1573  {
1574  fsstate->rel = NULL;
1575  fsstate->tupdesc = get_tupdesc_for_join_scan_tuples(node);
1576  }
1577 
1578  fsstate->attinmeta = TupleDescGetAttInMetadata(fsstate->tupdesc);
1579 
1580  /*
1581  * Prepare for processing of parameters used in remote query, if any.
1582  */
1583  numParams = list_length(fsplan->fdw_exprs);
1584  fsstate->numParams = numParams;
1585  if (numParams > 0)
1587  fsplan->fdw_exprs,
1588  numParams,
1589  &fsstate->param_flinfo,
1590  &fsstate->param_exprs,
1591  &fsstate->param_values);
1592 
1593  /* Set the async-capable flag */
1594  fsstate->async_capable = node->ss.ps.async_capable;
1595 }
1596 
1597 /*
1598  * postgresIterateForeignScan
1599  * Retrieve next row from the result set, or clear tuple slot to indicate
1600  * EOF.
1601  */
1602 static TupleTableSlot *
1604 {
1605  PgFdwScanState *fsstate = (PgFdwScanState *) node->fdw_state;
1606  TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
1607 
1608  /*
1609  * In sync mode, if this is the first call after Begin or ReScan, we need
1610  * to create the cursor on the remote side. In async mode, we would have
1611  * already created the cursor before we get here, even if this is the
1612  * first call after Begin or ReScan.
1613  */
1614  if (!fsstate->cursor_exists)
1615  create_cursor(node);
1616 
1617  /*
1618  * Get some more tuples, if we've run out.
1619  */
1620  if (fsstate->next_tuple >= fsstate->num_tuples)
1621  {
1622  /* In async mode, just clear tuple slot. */
1623  if (fsstate->async_capable)
1624  return ExecClearTuple(slot);
1625  /* No point in another fetch if we already detected EOF, though. */
1626  if (!fsstate->eof_reached)
1627  fetch_more_data(node);
1628  /* If we didn't get any tuples, must be end of data. */
1629  if (fsstate->next_tuple >= fsstate->num_tuples)
1630  return ExecClearTuple(slot);
1631  }
1632 
1633  /*
1634  * Return the next tuple.
1635  */
1636  ExecStoreHeapTuple(fsstate->tuples[fsstate->next_tuple++],
1637  slot,
1638  false);
1639 
1640  return slot;
1641 }
1642 
1643 /*
1644  * postgresReScanForeignScan
1645  * Restart the scan.
1646  */
1647 static void
1649 {
1650  PgFdwScanState *fsstate = (PgFdwScanState *) node->fdw_state;
1651  char sql[64];
1652  PGresult *res;
1653 
1654  /* If we haven't created the cursor yet, nothing to do. */
1655  if (!fsstate->cursor_exists)
1656  return;
1657 
1658  /*
1659  * If the node is async-capable, and an asynchronous fetch for it has
1660  * begun, the asynchronous fetch might not have yet completed. Check if
1661  * the node is async-capable, and an asynchronous fetch for it is still in
1662  * progress; if so, complete the asynchronous fetch before restarting the
1663  * scan.
1664  */
1665  if (fsstate->async_capable &&
1666  fsstate->conn_state->pendingAreq &&
1667  fsstate->conn_state->pendingAreq->requestee == (PlanState *) node)
1668  fetch_more_data(node);
1669 
1670  /*
1671  * If any internal parameters affecting this node have changed, we'd
1672  * better destroy and recreate the cursor. Otherwise, if the remote
1673  * server is v14 or older, rewinding it should be good enough; if not,
1674  * rewind is only allowed for scrollable cursors, but we don't have a way
1675  * to check the scrollability of it, so destroy and recreate it in any
1676  * case. If we've only fetched zero or one batch, we needn't even rewind
1677  * the cursor, just rescan what we have.
1678  */
1679  if (node->ss.ps.chgParam != NULL)
1680  {
1681  fsstate->cursor_exists = false;
1682  snprintf(sql, sizeof(sql), "CLOSE c%u",
1683  fsstate->cursor_number);
1684  }
1685  else if (fsstate->fetch_ct_2 > 1)
1686  {
1687  if (PQserverVersion(fsstate->conn) < 150000)
1688  snprintf(sql, sizeof(sql), "MOVE BACKWARD ALL IN c%u",
1689  fsstate->cursor_number);
1690  else
1691  {
1692  fsstate->cursor_exists = false;
1693  snprintf(sql, sizeof(sql), "CLOSE c%u",
1694  fsstate->cursor_number);
1695  }
1696  }
1697  else
1698  {
1699  /* Easy: just rescan what we already have in memory, if anything */
1700  fsstate->next_tuple = 0;
1701  return;
1702  }
1703 
1704  /*
1705  * We don't use a PG_TRY block here, so be careful not to throw error
1706  * without releasing the PGresult.
1707  */
1708  res = pgfdw_exec_query(fsstate->conn, sql, fsstate->conn_state);
1710  pgfdw_report_error(ERROR, res, fsstate->conn, true, sql);
1711  PQclear(res);
1712 
1713  /* Now force a fresh FETCH. */
1714  fsstate->tuples = NULL;
1715  fsstate->num_tuples = 0;
1716  fsstate->next_tuple = 0;
1717  fsstate->fetch_ct_2 = 0;
1718  fsstate->eof_reached = false;
1719 }
1720 
1721 /*
1722  * postgresEndForeignScan
1723  * Finish scanning foreign table and dispose objects used for this scan
1724  */
1725 static void
1727 {
1728  PgFdwScanState *fsstate = (PgFdwScanState *) node->fdw_state;
1729 
1730  /* if fsstate is NULL, we are in EXPLAIN; nothing to do */
1731  if (fsstate == NULL)
1732  return;
1733 
1734  /* Close the cursor if open, to prevent accumulation of cursors */
1735  if (fsstate->cursor_exists)
1736  close_cursor(fsstate->conn, fsstate->cursor_number,
1737  fsstate->conn_state);
1738 
1739  /* Release remote connection */
1740  ReleaseConnection(fsstate->conn);
1741  fsstate->conn = NULL;
1742 
1743  /* MemoryContexts will be deleted automatically. */
1744 }
1745 
1746 /*
1747  * postgresAddForeignUpdateTargets
1748  * Add resjunk column(s) needed for update/delete on a foreign table
1749  */
1750 static void
1752  Index rtindex,
1753  RangeTblEntry *target_rte,
1754  Relation target_relation)
1755 {
1756  Var *var;
1757 
1758  /*
1759  * In postgres_fdw, what we need is the ctid, same as for a regular table.
1760  */
1761 
1762  /* Make a Var representing the desired value */
1763  var = makeVar(rtindex,
1765  TIDOID,
1766  -1,
1767  InvalidOid,
1768  0);
1769 
1770  /* Register it as a row-identity column needed by this target rel */
1771  add_row_identity_var(root, var, rtindex, "ctid");
1772 }
1773 
1774 /*
1775  * postgresPlanForeignModify
1776  * Plan an insert/update/delete operation on a foreign table
1777  */
1778 static List *
1780  ModifyTable *plan,
1781  Index resultRelation,
1782  int subplan_index)
1783 {
1784  CmdType operation = plan->operation;
1785  RangeTblEntry *rte = planner_rt_fetch(resultRelation, root);
1786  Relation rel;
1787  StringInfoData sql;
1788  List *targetAttrs = NIL;
1789  List *withCheckOptionList = NIL;
1790  List *returningList = NIL;
1791  List *retrieved_attrs = NIL;
1792  bool doNothing = false;
1793  int values_end_len = -1;
1794 
1795  initStringInfo(&sql);
1796 
1797  /*
1798  * Core code already has some lock on each rel being planned, so we can
1799  * use NoLock here.
1800  */
1801  rel = table_open(rte->relid, NoLock);
1802 
1803  /*
1804  * In an INSERT, we transmit all columns that are defined in the foreign
1805  * table. In an UPDATE, if there are BEFORE ROW UPDATE triggers on the
1806  * foreign table, we transmit all columns like INSERT; else we transmit
1807  * only columns that were explicitly targets of the UPDATE, so as to avoid
1808  * unnecessary data transmission. (We can't do that for INSERT since we
1809  * would miss sending default values for columns not listed in the source
1810  * statement, and for UPDATE if there are BEFORE ROW UPDATE triggers since
1811  * those triggers might change values for non-target columns, in which
1812  * case we would miss sending changed values for those columns.)
1813  */
1814  if (operation == CMD_INSERT ||
1815  (operation == CMD_UPDATE &&
1816  rel->trigdesc &&
1818  {
1819  TupleDesc tupdesc = RelationGetDescr(rel);
1820  int attnum;
1821 
1822  for (attnum = 1; attnum <= tupdesc->natts; attnum++)
1823  {
1824  Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1);
1825 
1826  if (!attr->attisdropped)
1827  targetAttrs = lappend_int(targetAttrs, attnum);
1828  }
1829  }
1830  else if (operation == CMD_UPDATE)
1831  {
1832  int col;
1833  RelOptInfo *rel = find_base_rel(root, resultRelation);
1834  Bitmapset *allUpdatedCols = get_rel_all_updated_cols(root, rel);
1835 
1836  col = -1;
1837  while ((col = bms_next_member(allUpdatedCols, col)) >= 0)
1838  {
1839  /* bit numbers are offset by FirstLowInvalidHeapAttributeNumber */
1841 
1842  if (attno <= InvalidAttrNumber) /* shouldn't happen */
1843  elog(ERROR, "system-column update is not supported");
1844  targetAttrs = lappend_int(targetAttrs, attno);
1845  }
1846  }
1847 
1848  /*
1849  * Extract the relevant WITH CHECK OPTION list if any.
1850  */
1851  if (plan->withCheckOptionLists)
1852  withCheckOptionList = (List *) list_nth(plan->withCheckOptionLists,
1853  subplan_index);
1854 
1855  /*
1856  * Extract the relevant RETURNING list if any.
1857  */
1858  if (plan->returningLists)
1859  returningList = (List *) list_nth(plan->returningLists, subplan_index);
1860 
1861  /*
1862  * ON CONFLICT DO UPDATE and DO NOTHING case with inference specification
1863  * should have already been rejected in the optimizer, as presently there
1864  * is no way to recognize an arbiter index on a foreign table. Only DO
1865  * NOTHING is supported without an inference specification.
1866  */
1867  if (plan->onConflictAction == ONCONFLICT_NOTHING)
1868  doNothing = true;
1869  else if (plan->onConflictAction != ONCONFLICT_NONE)
1870  elog(ERROR, "unexpected ON CONFLICT specification: %d",
1871  (int) plan->onConflictAction);
1872 
1873  /*
1874  * Construct the SQL command string.
1875  */
1876  switch (operation)
1877  {
1878  case CMD_INSERT:
1879  deparseInsertSql(&sql, rte, resultRelation, rel,
1880  targetAttrs, doNothing,
1881  withCheckOptionList, returningList,
1882  &retrieved_attrs, &values_end_len);
1883  break;
1884  case CMD_UPDATE:
1885  deparseUpdateSql(&sql, rte, resultRelation, rel,
1886  targetAttrs,
1887  withCheckOptionList, returningList,
1888  &retrieved_attrs);
1889  break;
1890  case CMD_DELETE:
1891  deparseDeleteSql(&sql, rte, resultRelation, rel,
1892  returningList,
1893  &retrieved_attrs);
1894  break;
1895  default:
1896  elog(ERROR, "unexpected operation: %d", (int) operation);
1897  break;
1898  }
1899 
1900  table_close(rel, NoLock);
1901 
1902  /*
1903  * Build the fdw_private list that will be available to the executor.
1904  * Items in the list must match enum FdwModifyPrivateIndex, above.
1905  */
1906  return list_make5(makeString(sql.data),
1907  targetAttrs,
1908  makeInteger(values_end_len),
1909  makeBoolean((retrieved_attrs != NIL)),
1910  retrieved_attrs);
1911 }
1912 
1913 /*
1914  * postgresBeginForeignModify
1915  * Begin an insert/update/delete operation on a foreign table
1916  */
1917 static void
1919  ResultRelInfo *resultRelInfo,
1920  List *fdw_private,
1921  int subplan_index,
1922  int eflags)
1923 {
1924  PgFdwModifyState *fmstate;
1925  char *query;
1926  List *target_attrs;
1927  bool has_returning;
1928  int values_end_len;
1929  List *retrieved_attrs;
1930  RangeTblEntry *rte;
1931 
1932  /*
1933  * Do nothing in EXPLAIN (no ANALYZE) case. resultRelInfo->ri_FdwState
1934  * stays NULL.
1935  */
1936  if (eflags & EXEC_FLAG_EXPLAIN_ONLY)
1937  return;
1938 
1939  /* Deconstruct fdw_private data. */
1940  query = strVal(list_nth(fdw_private,
1942  target_attrs = (List *) list_nth(fdw_private,
1944  values_end_len = intVal(list_nth(fdw_private,
1946  has_returning = boolVal(list_nth(fdw_private,
1948  retrieved_attrs = (List *) list_nth(fdw_private,
1950 
1951  /* Find RTE. */
1952  rte = exec_rt_fetch(resultRelInfo->ri_RangeTableIndex,
1953  mtstate->ps.state);
1954 
1955  /* Construct an execution state. */
1956  fmstate = create_foreign_modify(mtstate->ps.state,
1957  rte,
1958  resultRelInfo,
1959  mtstate->operation,
1960  outerPlanState(mtstate)->plan,
1961  query,
1962  target_attrs,
1963  values_end_len,
1964  has_returning,
1965  retrieved_attrs);
1966 
1967  resultRelInfo->ri_FdwState = fmstate;
1968 }
1969 
1970 /*
1971  * postgresExecForeignInsert
1972  * Insert one row into a foreign table
1973  */
1974 static TupleTableSlot *
1976  ResultRelInfo *resultRelInfo,
1977  TupleTableSlot *slot,
1978  TupleTableSlot *planSlot)
1979 {
1980  PgFdwModifyState *fmstate = (PgFdwModifyState *) resultRelInfo->ri_FdwState;
1981  TupleTableSlot **rslot;
1982  int numSlots = 1;
1983 
1984  /*
1985  * If the fmstate has aux_fmstate set, use the aux_fmstate (see
1986  * postgresBeginForeignInsert())
1987  */
1988  if (fmstate->aux_fmstate)
1989  resultRelInfo->ri_FdwState = fmstate->aux_fmstate;
1990  rslot = execute_foreign_modify(estate, resultRelInfo, CMD_INSERT,
1991  &slot, &planSlot, &numSlots);
1992  /* Revert that change */
1993  if (fmstate->aux_fmstate)
1994  resultRelInfo->ri_FdwState = fmstate;
1995 
1996  return rslot ? *rslot : NULL;
1997 }
1998 
1999 /*
2000  * postgresExecForeignBatchInsert
2001  * Insert multiple rows into a foreign table
2002  */
2003 static TupleTableSlot **
2005  ResultRelInfo *resultRelInfo,
2006  TupleTableSlot **slots,
2007  TupleTableSlot **planSlots,
2008  int *numSlots)
2009 {
2010  PgFdwModifyState *fmstate = (PgFdwModifyState *) resultRelInfo->ri_FdwState;
2011  TupleTableSlot **rslot;
2012 
2013  /*
2014  * If the fmstate has aux_fmstate set, use the aux_fmstate (see
2015  * postgresBeginForeignInsert())
2016  */
2017  if (fmstate->aux_fmstate)
2018  resultRelInfo->ri_FdwState = fmstate->aux_fmstate;
2019  rslot = execute_foreign_modify(estate, resultRelInfo, CMD_INSERT,
2020  slots, planSlots, numSlots);
2021  /* Revert that change */
2022  if (fmstate->aux_fmstate)
2023  resultRelInfo->ri_FdwState = fmstate;
2024 
2025  return rslot;
2026 }
2027 
2028 /*
2029  * postgresGetForeignModifyBatchSize
2030  * Determine the maximum number of tuples that can be inserted in bulk
2031  *
2032  * Returns the batch size specified for server or table. When batching is not
2033  * allowed (e.g. for tables with BEFORE/AFTER ROW triggers or with RETURNING
2034  * clause), returns 1.
2035  */
2036 static int
2038 {
2039  int batch_size;
2040  PgFdwModifyState *fmstate = (PgFdwModifyState *) resultRelInfo->ri_FdwState;
2041 
2042  /* should be called only once */
2043  Assert(resultRelInfo->ri_BatchSize == 0);
2044 
2045  /*
2046  * Should never get called when the insert is being performed on a table
2047  * that is also among the target relations of an UPDATE operation, because
2048  * postgresBeginForeignInsert() currently rejects such insert attempts.
2049  */
2050  Assert(fmstate == NULL || fmstate->aux_fmstate == NULL);
2051 
2052  /*
2053  * In EXPLAIN without ANALYZE, ri_FdwState is NULL, so we have to lookup
2054  * the option directly in server/table options. Otherwise just use the
2055  * value we determined earlier.
2056  */
2057  if (fmstate)
2058  batch_size = fmstate->batch_size;
2059  else
2060  batch_size = get_batch_size_option(resultRelInfo->ri_RelationDesc);
2061 
2062  /*
2063  * Disable batching when we have to use RETURNING, there are any
2064  * BEFORE/AFTER ROW INSERT triggers on the foreign table, or there are any
2065  * WITH CHECK OPTION constraints from parent views.
2066  *
2067  * When there are any BEFORE ROW INSERT triggers on the table, we can't
2068  * support it, because such triggers might query the table we're inserting
2069  * into and act differently if the tuples that have already been processed
2070  * and prepared for insertion are not there.
2071  */
2072  if (resultRelInfo->ri_projectReturning != NULL ||
2073  resultRelInfo->ri_WithCheckOptions != NIL ||
2074  (resultRelInfo->ri_TrigDesc &&
2075  (resultRelInfo->ri_TrigDesc->trig_insert_before_row ||
2076  resultRelInfo->ri_TrigDesc->trig_insert_after_row)))
2077  return 1;
2078 
2079  /*
2080  * If the foreign table has no columns, disable batching as the INSERT
2081  * syntax doesn't allow batching multiple empty rows into a zero-column
2082  * table in a single statement. This is needed for COPY FROM, in which
2083  * case fmstate must be non-NULL.
2084  */
2085  if (fmstate && list_length(fmstate->target_attrs) == 0)
2086  return 1;
2087 
2088  /*
2089  * Otherwise use the batch size specified for server/table. The number of
2090  * parameters in a batch is limited to 65535 (uint16), so make sure we
2091  * don't exceed this limit by using the maximum batch_size possible.
2092  */
2093  if (fmstate && fmstate->p_nums > 0)
2094  batch_size = Min(batch_size, PQ_QUERY_PARAM_MAX_LIMIT / fmstate->p_nums);
2095 
2096  return batch_size;
2097 }
2098 
2099 /*
2100  * postgresExecForeignUpdate
2101  * Update one row in a foreign table
2102  */
2103 static TupleTableSlot *
2105  ResultRelInfo *resultRelInfo,
2106  TupleTableSlot *slot,
2107  TupleTableSlot *planSlot)
2108 {
2109  TupleTableSlot **rslot;
2110  int numSlots = 1;
2111 
2112  rslot = execute_foreign_modify(estate, resultRelInfo, CMD_UPDATE,
2113  &slot, &planSlot, &numSlots);
2114 
2115  return rslot ? rslot[0] : NULL;
2116 }
2117 
2118 /*
2119  * postgresExecForeignDelete
2120  * Delete one row from a foreign table
2121  */
2122 static TupleTableSlot *
2124  ResultRelInfo *resultRelInfo,
2125  TupleTableSlot *slot,
2126  TupleTableSlot *planSlot)
2127 {
2128  TupleTableSlot **rslot;
2129  int numSlots = 1;
2130 
2131  rslot = execute_foreign_modify(estate, resultRelInfo, CMD_DELETE,
2132  &slot, &planSlot, &numSlots);
2133 
2134  return rslot ? rslot[0] : NULL;
2135 }
2136 
2137 /*
2138  * postgresEndForeignModify
2139  * Finish an insert/update/delete operation on a foreign table
2140  */
2141 static void
2143  ResultRelInfo *resultRelInfo)
2144 {
2145  PgFdwModifyState *fmstate = (PgFdwModifyState *) resultRelInfo->ri_FdwState;
2146 
2147  /* If fmstate is NULL, we are in EXPLAIN; nothing to do */
2148  if (fmstate == NULL)
2149  return;
2150 
2151  /* Destroy the execution state */
2152  finish_foreign_modify(fmstate);
2153 }
2154 
2155 /*
2156  * postgresBeginForeignInsert
2157  * Begin an insert operation on a foreign table
2158  */
2159 static void
2161  ResultRelInfo *resultRelInfo)
2162 {
2163  PgFdwModifyState *fmstate;
2164  ModifyTable *plan = castNode(ModifyTable, mtstate->ps.plan);
2165  EState *estate = mtstate->ps.state;
2166  Index resultRelation;
2167  Relation rel = resultRelInfo->ri_RelationDesc;
2168  RangeTblEntry *rte;
2169  TupleDesc tupdesc = RelationGetDescr(rel);
2170  int attnum;
2171  int values_end_len;
2172  StringInfoData sql;
2173  List *targetAttrs = NIL;
2174  List *retrieved_attrs = NIL;
2175  bool doNothing = false;
2176 
2177  /*
2178  * If the foreign table we are about to insert routed rows into is also an
2179  * UPDATE subplan result rel that will be updated later, proceeding with
2180  * the INSERT will result in the later UPDATE incorrectly modifying those
2181  * routed rows, so prevent the INSERT --- it would be nice if we could
2182  * handle this case; but for now, throw an error for safety.
2183  */
2184  if (plan && plan->operation == CMD_UPDATE &&
2185  (resultRelInfo->ri_usesFdwDirectModify ||
2186  resultRelInfo->ri_FdwState))
2187  ereport(ERROR,
2188  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2189  errmsg("cannot route tuples into foreign table to be updated \"%s\"",
2190  RelationGetRelationName(rel))));
2191 
2192  initStringInfo(&sql);
2193 
2194  /* We transmit all columns that are defined in the foreign table. */
2195  for (attnum = 1; attnum <= tupdesc->natts; attnum++)
2196  {
2197  Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1);
2198 
2199  if (!attr->attisdropped)
2200  targetAttrs = lappend_int(targetAttrs, attnum);
2201  }
2202 
2203  /* Check if we add the ON CONFLICT clause to the remote query. */
2204  if (plan)
2205  {
2206  OnConflictAction onConflictAction = plan->onConflictAction;
2207 
2208  /* We only support DO NOTHING without an inference specification. */
2209  if (onConflictAction == ONCONFLICT_NOTHING)
2210  doNothing = true;
2211  else if (onConflictAction != ONCONFLICT_NONE)
2212  elog(ERROR, "unexpected ON CONFLICT specification: %d",
2213  (int) onConflictAction);
2214  }
2215 
2216  /*
2217  * If the foreign table is a partition that doesn't have a corresponding
2218  * RTE entry, we need to create a new RTE describing the foreign table for
2219  * use by deparseInsertSql and create_foreign_modify() below, after first
2220  * copying the parent's RTE and modifying some fields to describe the
2221  * foreign partition to work on. However, if this is invoked by UPDATE,
2222  * the existing RTE may already correspond to this partition if it is one
2223  * of the UPDATE subplan target rels; in that case, we can just use the
2224  * existing RTE as-is.
2225  */
2226  if (resultRelInfo->ri_RangeTableIndex == 0)
2227  {
2228  ResultRelInfo *rootResultRelInfo = resultRelInfo->ri_RootResultRelInfo;
2229 
2230  rte = exec_rt_fetch(rootResultRelInfo->ri_RangeTableIndex, estate);
2231  rte = copyObject(rte);
2232  rte->relid = RelationGetRelid(rel);
2233  rte->relkind = RELKIND_FOREIGN_TABLE;
2234 
2235  /*
2236  * For UPDATE, we must use the RT index of the first subplan target
2237  * rel's RTE, because the core code would have built expressions for
2238  * the partition, such as RETURNING, using that RT index as varno of
2239  * Vars contained in those expressions.
2240  */
2241  if (plan && plan->operation == CMD_UPDATE &&
2242  rootResultRelInfo->ri_RangeTableIndex == plan->rootRelation)
2243  resultRelation = mtstate->resultRelInfo[0].ri_RangeTableIndex;
2244  else
2245  resultRelation = rootResultRelInfo->ri_RangeTableIndex;
2246  }
2247  else
2248  {
2249  resultRelation = resultRelInfo->ri_RangeTableIndex;
2250  rte = exec_rt_fetch(resultRelation, estate);
2251  }
2252 
2253  /* Construct the SQL command string. */
2254  deparseInsertSql(&sql, rte, resultRelation, rel, targetAttrs, doNothing,
2255  resultRelInfo->ri_WithCheckOptions,
2256  resultRelInfo->ri_returningList,
2257  &retrieved_attrs, &values_end_len);
2258 
2259  /* Construct an execution state. */
2260  fmstate = create_foreign_modify(mtstate->ps.state,
2261  rte,
2262  resultRelInfo,
2263  CMD_INSERT,
2264  NULL,
2265  sql.data,
2266  targetAttrs,
2267  values_end_len,
2268  retrieved_attrs != NIL,
2269  retrieved_attrs);
2270 
2271  /*
2272  * If the given resultRelInfo already has PgFdwModifyState set, it means
2273  * the foreign table is an UPDATE subplan result rel; in which case, store
2274  * the resulting state into the aux_fmstate of the PgFdwModifyState.
2275  */
2276  if (resultRelInfo->ri_FdwState)
2277  {
2278  Assert(plan && plan->operation == CMD_UPDATE);
2279  Assert(resultRelInfo->ri_usesFdwDirectModify == false);
2280  ((PgFdwModifyState *) resultRelInfo->ri_FdwState)->aux_fmstate = fmstate;
2281  }
2282  else
2283  resultRelInfo->ri_FdwState = fmstate;
2284 }
2285 
2286 /*
2287  * postgresEndForeignInsert
2288  * Finish an insert operation on a foreign table
2289  */
2290 static void
2292  ResultRelInfo *resultRelInfo)
2293 {
2294  PgFdwModifyState *fmstate = (PgFdwModifyState *) resultRelInfo->ri_FdwState;
2295 
2296  Assert(fmstate != NULL);
2297 
2298  /*
2299  * If the fmstate has aux_fmstate set, get the aux_fmstate (see
2300  * postgresBeginForeignInsert())
2301  */
2302  if (fmstate->aux_fmstate)
2303  fmstate = fmstate->aux_fmstate;
2304 
2305  /* Destroy the execution state */
2306  finish_foreign_modify(fmstate);
2307 }
2308 
2309 /*
2310  * postgresIsForeignRelUpdatable
2311  * Determine whether a foreign table supports INSERT, UPDATE and/or
2312  * DELETE.
2313  */
2314 static int
2316 {
2317  bool updatable;
2318  ForeignTable *table;
2319  ForeignServer *server;
2320  ListCell *lc;
2321 
2322  /*
2323  * By default, all postgres_fdw foreign tables are assumed updatable. This
2324  * can be overridden by a per-server setting, which in turn can be
2325  * overridden by a per-table setting.
2326  */
2327  updatable = true;
2328 
2329  table = GetForeignTable(RelationGetRelid(rel));
2330  server = GetForeignServer(table->serverid);
2331 
2332  foreach(lc, server->options)
2333  {
2334  DefElem *def = (DefElem *) lfirst(lc);
2335 
2336  if (strcmp(def->defname, "updatable") == 0)
2337  updatable = defGetBoolean(def);
2338  }
2339  foreach(lc, table->options)
2340  {
2341  DefElem *def = (DefElem *) lfirst(lc);
2342 
2343  if (strcmp(def->defname, "updatable") == 0)
2344  updatable = defGetBoolean(def);
2345  }
2346 
2347  /*
2348  * Currently "updatable" means support for INSERT, UPDATE and DELETE.
2349  */
2350  return updatable ?
2351  (1 << CMD_INSERT) | (1 << CMD_UPDATE) | (1 << CMD_DELETE) : 0;
2352 }
2353 
2354 /*
2355  * postgresRecheckForeignScan
2356  * Execute a local join execution plan for a foreign join
2357  */
2358 static bool
2360 {
2361  Index scanrelid = ((Scan *) node->ss.ps.plan)->scanrelid;
2363  TupleTableSlot *result;
2364 
2365  /* For base foreign relations, it suffices to set fdw_recheck_quals */
2366  if (scanrelid > 0)
2367  return true;
2368 
2369  Assert(outerPlan != NULL);
2370 
2371  /* Execute a local join execution plan */
2372  result = ExecProcNode(outerPlan);
2373  if (TupIsNull(result))
2374  return false;
2375 
2376  /* Store result in the given slot */
2377  ExecCopySlot(slot, result);
2378 
2379  return true;
2380 }
2381 
2382 /*
2383  * find_modifytable_subplan
2384  * Helper routine for postgresPlanDirectModify to find the
2385  * ModifyTable subplan node that scans the specified RTI.
2386  *
2387  * Returns NULL if the subplan couldn't be identified. That's not a fatal
2388  * error condition, we just abandon trying to do the update directly.
2389  */
2390 static ForeignScan *
2392  ModifyTable *plan,
2393  Index rtindex,
2394  int subplan_index)
2395 {
2396  Plan *subplan = outerPlan(plan);
2397 
2398  /*
2399  * The cases we support are (1) the desired ForeignScan is the immediate
2400  * child of ModifyTable, or (2) it is the subplan_index'th child of an
2401  * Append node that is the immediate child of ModifyTable. There is no
2402  * point in looking further down, as that would mean that local joins are
2403  * involved, so we can't do the update directly.
2404  *
2405  * There could be a Result atop the Append too, acting to compute the
2406  * UPDATE targetlist values. We ignore that here; the tlist will be
2407  * checked by our caller.
2408  *
2409  * In principle we could examine all the children of the Append, but it's
2410  * currently unlikely that the core planner would generate such a plan
2411  * with the children out-of-order. Moreover, such a search risks costing
2412  * O(N^2) time when there are a lot of children.
2413  */
2414  if (IsA(subplan, Append))
2415  {
2416  Append *appendplan = (Append *) subplan;
2417 
2418  if (subplan_index < list_length(appendplan->appendplans))
2419  subplan = (Plan *) list_nth(appendplan->appendplans, subplan_index);
2420  }
2421  else if (IsA(subplan, Result) &&
2422  outerPlan(subplan) != NULL &&
2423  IsA(outerPlan(subplan), Append))
2424  {
2425  Append *appendplan = (Append *) outerPlan(subplan);
2426 
2427  if (subplan_index < list_length(appendplan->appendplans))
2428  subplan = (Plan *) list_nth(appendplan->appendplans, subplan_index);
2429  }
2430 
2431  /* Now, have we got a ForeignScan on the desired rel? */
2432  if (IsA(subplan, ForeignScan))
2433  {
2434  ForeignScan *fscan = (ForeignScan *) subplan;
2435 
2436  if (bms_is_member(rtindex, fscan->fs_base_relids))
2437  return fscan;
2438  }
2439 
2440  return NULL;
2441 }
2442 
2443 /*
2444  * postgresPlanDirectModify
2445  * Consider a direct foreign table modification
2446  *
2447  * Decide whether it is safe to modify a foreign table directly, and if so,
2448  * rewrite subplan accordingly.
2449  */
2450 static bool
2452  ModifyTable *plan,
2453  Index resultRelation,
2454  int subplan_index)
2455 {
2456  CmdType operation = plan->operation;
2457  RelOptInfo *foreignrel;
2458  RangeTblEntry *rte;
2459  PgFdwRelationInfo *fpinfo;
2460  Relation rel;
2461  StringInfoData sql;
2462  ForeignScan *fscan;
2463  List *processed_tlist = NIL;
2464  List *targetAttrs = NIL;
2465  List *remote_exprs;
2466  List *params_list = NIL;
2467  List *returningList = NIL;
2468  List *retrieved_attrs = NIL;
2469 
2470  /*
2471  * Decide whether it is safe to modify a foreign table directly.
2472  */
2473 
2474  /*
2475  * The table modification must be an UPDATE or DELETE.
2476  */
2477  if (operation != CMD_UPDATE && operation != CMD_DELETE)
2478  return false;
2479 
2480  /*
2481  * Try to locate the ForeignScan subplan that's scanning resultRelation.
2482  */
2483  fscan = find_modifytable_subplan(root, plan, resultRelation, subplan_index);
2484  if (!fscan)
2485  return false;
2486 
2487  /*
2488  * It's unsafe to modify a foreign table directly if there are any quals
2489  * that should be evaluated locally.
2490  */
2491  if (fscan->scan.plan.qual != NIL)
2492  return false;
2493 
2494  /* Safe to fetch data about the target foreign rel */
2495  if (fscan->scan.scanrelid == 0)
2496  {
2497  foreignrel = find_join_rel(root, fscan->fs_relids);
2498  /* We should have a rel for this foreign join. */
2499  Assert(foreignrel);
2500  }
2501  else
2502  foreignrel = root->simple_rel_array[resultRelation];
2503  rte = root->simple_rte_array[resultRelation];
2504  fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
2505 
2506  /*
2507  * It's unsafe to update a foreign table directly, if any expressions to
2508  * assign to the target columns are unsafe to evaluate remotely.
2509  */
2510  if (operation == CMD_UPDATE)
2511  {
2512  ListCell *lc,
2513  *lc2;
2514 
2515  /*
2516  * The expressions of concern are the first N columns of the processed
2517  * targetlist, where N is the length of the rel's update_colnos.
2518  */
2519  get_translated_update_targetlist(root, resultRelation,
2520  &processed_tlist, &targetAttrs);
2521  forboth(lc, processed_tlist, lc2, targetAttrs)
2522  {
2523  TargetEntry *tle = lfirst_node(TargetEntry, lc);
2524  AttrNumber attno = lfirst_int(lc2);
2525 
2526  /* update's new-value expressions shouldn't be resjunk */
2527  Assert(!tle->resjunk);
2528 
2529  if (attno <= InvalidAttrNumber) /* shouldn't happen */
2530  elog(ERROR, "system-column update is not supported");
2531 
2532  if (!is_foreign_expr(root, foreignrel, (Expr *) tle->expr))
2533  return false;
2534  }
2535  }
2536 
2537  /*
2538  * Ok, rewrite subplan so as to modify the foreign table directly.
2539  */
2540  initStringInfo(&sql);
2541 
2542  /*
2543  * Core code already has some lock on each rel being planned, so we can
2544  * use NoLock here.
2545  */
2546  rel = table_open(rte->relid, NoLock);
2547 
2548  /*
2549  * Recall the qual clauses that must be evaluated remotely. (These are
2550  * bare clauses not RestrictInfos, but deparse.c's appendConditions()
2551  * doesn't care.)
2552  */
2553  remote_exprs = fpinfo->final_remote_exprs;
2554 
2555  /*
2556  * Extract the relevant RETURNING list if any.
2557  */
2558  if (plan->returningLists)
2559  {
2560  returningList = (List *) list_nth(plan->returningLists, subplan_index);
2561 
2562  /*
2563  * When performing an UPDATE/DELETE .. RETURNING on a join directly,
2564  * we fetch from the foreign server any Vars specified in RETURNING
2565  * that refer not only to the target relation but to non-target
2566  * relations. So we'll deparse them into the RETURNING clause of the
2567  * remote query; use a targetlist consisting of them instead, which
2568  * will be adjusted to be new fdw_scan_tlist of the foreign-scan plan
2569  * node below.
2570  */
2571  if (fscan->scan.scanrelid == 0)
2572  returningList = build_remote_returning(resultRelation, rel,
2573  returningList);
2574  }
2575 
2576  /*
2577  * Construct the SQL command string.
2578  */
2579  switch (operation)
2580  {
2581  case CMD_UPDATE:
2582  deparseDirectUpdateSql(&sql, root, resultRelation, rel,
2583  foreignrel,
2584  processed_tlist,
2585  targetAttrs,
2586  remote_exprs, &params_list,
2587  returningList, &retrieved_attrs);
2588  break;
2589  case CMD_DELETE:
2590  deparseDirectDeleteSql(&sql, root, resultRelation, rel,
2591  foreignrel,
2592  remote_exprs, &params_list,
2593  returningList, &retrieved_attrs);
2594  break;
2595  default:
2596  elog(ERROR, "unexpected operation: %d", (int) operation);
2597  break;
2598  }
2599 
2600  /*
2601  * Update the operation and target relation info.
2602  */
2603  fscan->operation = operation;
2604  fscan->resultRelation = resultRelation;
2605 
2606  /*
2607  * Update the fdw_exprs list that will be available to the executor.
2608  */
2609  fscan->fdw_exprs = params_list;
2610 
2611  /*
2612  * Update the fdw_private list that will be available to the executor.
2613  * Items in the list must match enum FdwDirectModifyPrivateIndex, above.
2614  */
2615  fscan->fdw_private = list_make4(makeString(sql.data),
2616  makeBoolean((retrieved_attrs != NIL)),
2617  retrieved_attrs,
2618  makeBoolean(plan->canSetTag));
2619 
2620  /*
2621  * Update the foreign-join-related fields.
2622  */
2623  if (fscan->scan.scanrelid == 0)
2624  {
2625  /* No need for the outer subplan. */
2626  fscan->scan.plan.lefttree = NULL;
2627 
2628  /* Build new fdw_scan_tlist if UPDATE/DELETE .. RETURNING. */
2629  if (returningList)
2630  rebuild_fdw_scan_tlist(fscan, returningList);
2631  }
2632 
2633  /*
2634  * Finally, unset the async-capable flag if it is set, as we currently
2635  * don't support asynchronous execution of direct modifications.
2636  */
2637  if (fscan->scan.plan.async_capable)
2638  fscan->scan.plan.async_capable = false;
2639 
2640  table_close(rel, NoLock);
2641  return true;
2642 }
2643 
2644 /*
2645  * postgresBeginDirectModify
2646  * Prepare a direct foreign table modification
2647  */
2648 static void
2650 {
2651  ForeignScan *fsplan = (ForeignScan *) node->ss.ps.plan;
2652  EState *estate = node->ss.ps.state;
2653  PgFdwDirectModifyState *dmstate;
2654  Index rtindex;
2655  Oid userid;
2656  ForeignTable *table;
2657  UserMapping *user;
2658  int numParams;
2659 
2660  /*
2661  * Do nothing in EXPLAIN (no ANALYZE) case. node->fdw_state stays NULL.
2662  */
2663  if (eflags & EXEC_FLAG_EXPLAIN_ONLY)
2664  return;
2665 
2666  /*
2667  * We'll save private state in node->fdw_state.
2668  */
2669  dmstate = (PgFdwDirectModifyState *) palloc0(sizeof(PgFdwDirectModifyState));
2670  node->fdw_state = (void *) dmstate;
2671 
2672  /*
2673  * Identify which user to do the remote access as. This should match what
2674  * ExecCheckPermissions() does.
2675  */
2676  userid = OidIsValid(fsplan->checkAsUser) ? fsplan->checkAsUser : GetUserId();
2677 
2678  /* Get info about foreign table. */
2679  rtindex = node->resultRelInfo->ri_RangeTableIndex;
2680  if (fsplan->scan.scanrelid == 0)
2681  dmstate->rel = ExecOpenScanRelation(estate, rtindex, eflags);
2682  else
2683  dmstate->rel = node->ss.ss_currentRelation;
2684  table = GetForeignTable(RelationGetRelid(dmstate->rel));
2685  user = GetUserMapping(userid, table->serverid);
2686 
2687  /*
2688  * Get connection to the foreign server. Connection manager will
2689  * establish new connection if necessary.
2690  */
2691  dmstate->conn = GetConnection(user, false, &dmstate->conn_state);
2692 
2693  /* Update the foreign-join-related fields. */
2694  if (fsplan->scan.scanrelid == 0)
2695  {
2696  /* Save info about foreign table. */
2697  dmstate->resultRel = dmstate->rel;
2698 
2699  /*
2700  * Set dmstate->rel to NULL to teach get_returning_data() and
2701  * make_tuple_from_result_row() that columns fetched from the remote
2702  * server are described by fdw_scan_tlist of the foreign-scan plan
2703  * node, not the tuple descriptor for the target relation.
2704  */
2705  dmstate->rel = NULL;
2706  }
2707 
2708  /* Initialize state variable */
2709  dmstate->num_tuples = -1; /* -1 means not set yet */
2710 
2711  /* Get private info created by planner functions. */
2712  dmstate->query = strVal(list_nth(fsplan->fdw_private,
2714  dmstate->has_returning = boolVal(list_nth(fsplan->fdw_private,
2716  dmstate->retrieved_attrs = (List *) list_nth(fsplan->fdw_private,
2718  dmstate->set_processed = boolVal(list_nth(fsplan->fdw_private,
2720 
2721  /* Create context for per-tuple temp workspace. */
2722  dmstate->temp_cxt = AllocSetContextCreate(estate->es_query_cxt,
2723  "postgres_fdw temporary data",
2725 
2726  /* Prepare for input conversion of RETURNING results. */
2727  if (dmstate->has_returning)
2728  {
2729  TupleDesc tupdesc;
2730 
2731  if (fsplan->scan.scanrelid == 0)
2732  tupdesc = get_tupdesc_for_join_scan_tuples(node);
2733  else
2734  tupdesc = RelationGetDescr(dmstate->rel);
2735 
2736  dmstate->attinmeta = TupleDescGetAttInMetadata(tupdesc);
2737 
2738  /*
2739  * When performing an UPDATE/DELETE .. RETURNING on a join directly,
2740  * initialize a filter to extract an updated/deleted tuple from a scan
2741  * tuple.
2742  */
2743  if (fsplan->scan.scanrelid == 0)
2744  init_returning_filter(dmstate, fsplan->fdw_scan_tlist, rtindex);
2745  }
2746 
2747  /*
2748  * Prepare for processing of parameters used in remote query, if any.
2749  */
2750  numParams = list_length(fsplan->fdw_exprs);
2751  dmstate->numParams = numParams;
2752  if (numParams > 0)
2754  fsplan->fdw_exprs,
2755  numParams,
2756  &dmstate->param_flinfo,
2757  &dmstate->param_exprs,
2758  &dmstate->param_values);
2759 }
2760 
2761 /*
2762  * postgresIterateDirectModify
2763  * Execute a direct foreign table modification
2764  */
2765 static TupleTableSlot *
2767 {
2769  EState *estate = node->ss.ps.state;
2770  ResultRelInfo *resultRelInfo = node->resultRelInfo;
2771 
2772  /*
2773  * If this is the first call after Begin, execute the statement.
2774  */
2775  if (dmstate->num_tuples == -1)
2776  execute_dml_stmt(node);
2777 
2778  /*
2779  * If the local query doesn't specify RETURNING, just clear tuple slot.
2780  */
2781  if (!resultRelInfo->ri_projectReturning)
2782  {
2783  TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
2784  Instrumentation *instr = node->ss.ps.instrument;
2785 
2786  Assert(!dmstate->has_returning);
2787 
2788  /* Increment the command es_processed count if necessary. */
2789  if (dmstate->set_processed)
2790  estate->es_processed += dmstate->num_tuples;
2791 
2792  /* Increment the tuple count for EXPLAIN ANALYZE if necessary. */
2793  if (instr)
2794  instr->tuplecount += dmstate->num_tuples;
2795 
2796  return ExecClearTuple(slot);
2797  }
2798 
2799  /*
2800  * Get the next RETURNING tuple.
2801  */
2802  return get_returning_data(node);
2803 }
2804 
2805 /*
2806  * postgresEndDirectModify
2807  * Finish a direct foreign table modification
2808  */
2809 static void
2811 {
2813 
2814  /* if dmstate is NULL, we are in EXPLAIN; nothing to do */
2815  if (dmstate == NULL)
2816  return;
2817 
2818  /* Release PGresult */
2819  PQclear(dmstate->result);
2820 
2821  /* Release remote connection */
2822  ReleaseConnection(dmstate->conn);
2823  dmstate->conn = NULL;
2824 
2825  /* MemoryContext will be deleted automatically. */
2826 }
2827 
2828 /*
2829  * postgresExplainForeignScan
2830  * Produce extra output for EXPLAIN of a ForeignScan on a foreign table
2831  */
2832 static void
2834 {
2836  List *fdw_private = plan->fdw_private;
2837 
2838  /*
2839  * Identify foreign scans that are really joins or upper relations. The
2840  * input looks something like "(1) LEFT JOIN (2)", and we must replace the
2841  * digit string(s), which are RT indexes, with the correct relation names.
2842  * We do that here, not when the plan is created, because we can't know
2843  * what aliases ruleutils.c will assign at plan creation time.
2844  */
2845  if (list_length(fdw_private) > FdwScanPrivateRelations)
2846  {
2847  StringInfo relations;
2848  char *rawrelations;
2849  char *ptr;
2850  int minrti,
2851  rtoffset;
2852 
2853  rawrelations = strVal(list_nth(fdw_private, FdwScanPrivateRelations));
2854 
2855  /*
2856  * A difficulty with using a string representation of RT indexes is
2857  * that setrefs.c won't update the string when flattening the
2858  * rangetable. To find out what rtoffset was applied, identify the
2859  * minimum RT index appearing in the string and compare it to the
2860  * minimum member of plan->fs_base_relids. (We expect all the relids
2861  * in the join will have been offset by the same amount; the Asserts
2862  * below should catch it if that ever changes.)
2863  */
2864  minrti = INT_MAX;
2865  ptr = rawrelations;
2866  while (*ptr)
2867  {
2868  if (isdigit((unsigned char) *ptr))
2869  {
2870  int rti = strtol(ptr, &ptr, 10);
2871 
2872  if (rti < minrti)
2873  minrti = rti;
2874  }
2875  else
2876  ptr++;
2877  }
2878  rtoffset = bms_next_member(plan->fs_base_relids, -1) - minrti;
2879 
2880  /* Now we can translate the string */
2881  relations = makeStringInfo();
2882  ptr = rawrelations;
2883  while (*ptr)
2884  {
2885  if (isdigit((unsigned char) *ptr))
2886  {
2887  int rti = strtol(ptr, &ptr, 10);
2888  RangeTblEntry *rte;
2889  char *relname;
2890  char *refname;
2891 
2892  rti += rtoffset;
2893  Assert(bms_is_member(rti, plan->fs_base_relids));
2894  rte = rt_fetch(rti, es->rtable);
2895  Assert(rte->rtekind == RTE_RELATION);
2896  /* This logic should agree with explain.c's ExplainTargetRel */
2897  relname = get_rel_name(rte->relid);
2898  if (es->verbose)
2899  {
2900  char *namespace;
2901 
2902  namespace = get_namespace_name_or_temp(get_rel_namespace(rte->relid));
2903  appendStringInfo(relations, "%s.%s",
2904  quote_identifier(namespace),
2906  }
2907  else
2908  appendStringInfoString(relations,
2910  refname = (char *) list_nth(es->rtable_names, rti - 1);
2911  if (refname == NULL)
2912  refname = rte->eref->aliasname;
2913  if (strcmp(refname, relname) != 0)
2914  appendStringInfo(relations, " %s",
2915  quote_identifier(refname));
2916  }
2917  else
2918  appendStringInfoChar(relations, *ptr++);
2919  }
2920  ExplainPropertyText("Relations", relations->data, es);
2921  }
2922 
2923  /*
2924  * Add remote query, when VERBOSE option is specified.
2925  */
2926  if (es->verbose)
2927  {
2928  char *sql;
2929 
2930  sql = strVal(list_nth(fdw_private, FdwScanPrivateSelectSql));
2931  ExplainPropertyText("Remote SQL", sql, es);
2932  }
2933 }
2934 
2935 /*
2936  * postgresExplainForeignModify
2937  * Produce extra output for EXPLAIN of a ModifyTable on a foreign table
2938  */
2939 static void
2941  ResultRelInfo *rinfo,
2942  List *fdw_private,
2943  int subplan_index,
2944  ExplainState *es)
2945 {
2946  if (es->verbose)
2947  {
2948  char *sql = strVal(list_nth(fdw_private,
2950 
2951  ExplainPropertyText("Remote SQL", sql, es);
2952 
2953  /*
2954  * For INSERT we should always have batch size >= 1, but UPDATE and
2955  * DELETE don't support batching so don't show the property.
2956  */
2957  if (rinfo->ri_BatchSize > 0)
2958  ExplainPropertyInteger("Batch Size", NULL, rinfo->ri_BatchSize, es);
2959  }
2960 }
2961 
2962 /*
2963  * postgresExplainDirectModify
2964  * Produce extra output for EXPLAIN of a ForeignScan that modifies a
2965  * foreign table directly
2966  */
2967 static void
2969 {
2970  List *fdw_private;
2971  char *sql;
2972 
2973  if (es->verbose)
2974  {
2975  fdw_private = ((ForeignScan *) node->ss.ps.plan)->fdw_private;
2976  sql = strVal(list_nth(fdw_private, FdwDirectModifyPrivateUpdateSql));
2977  ExplainPropertyText("Remote SQL", sql, es);
2978  }
2979 }
2980 
2981 /*
2982  * postgresExecForeignTruncate
2983  * Truncate one or more foreign tables
2984  */
2985 static void
2987  DropBehavior behavior,
2988  bool restart_seqs)
2989 {
2990  Oid serverid = InvalidOid;
2991  UserMapping *user = NULL;
2992  PGconn *conn = NULL;
2993  StringInfoData sql;
2994  ListCell *lc;
2995  bool server_truncatable = true;
2996 
2997  /*
2998  * By default, all postgres_fdw foreign tables are assumed truncatable.
2999  * This can be overridden by a per-server setting, which in turn can be
3000  * overridden by a per-table setting.
3001  */
3002  foreach(lc, rels)
3003  {
3004  ForeignServer *server = NULL;
3005  Relation rel = lfirst(lc);
3007  ListCell *cell;
3008  bool truncatable;
3009 
3010  /*
3011  * First time through, determine whether the foreign server allows
3012  * truncates. Since all specified foreign tables are assumed to belong
3013  * to the same foreign server, this result can be used for other
3014  * foreign tables.
3015  */
3016  if (!OidIsValid(serverid))
3017  {
3018  serverid = table->serverid;
3019  server = GetForeignServer(serverid);
3020 
3021  foreach(cell, server->options)
3022  {
3023  DefElem *defel = (DefElem *) lfirst(cell);
3024 
3025  if (strcmp(defel->defname, "truncatable") == 0)
3026  {
3027  server_truncatable = defGetBoolean(defel);
3028  break;
3029  }
3030  }
3031  }
3032 
3033  /*
3034  * Confirm that all specified foreign tables belong to the same
3035  * foreign server.
3036  */
3037  Assert(table->serverid == serverid);
3038 
3039  /* Determine whether this foreign table allows truncations */
3040  truncatable = server_truncatable;
3041  foreach(cell, table->options)
3042  {
3043  DefElem *defel = (DefElem *) lfirst(cell);
3044 
3045  if (strcmp(defel->defname, "truncatable") == 0)
3046  {
3047  truncatable = defGetBoolean(defel);
3048  break;
3049  }
3050  }
3051 
3052  if (!truncatable)
3053  ereport(ERROR,
3054  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3055  errmsg("foreign table \"%s\" does not allow truncates",
3056  RelationGetRelationName(rel))));
3057  }
3058  Assert(OidIsValid(serverid));
3059 
3060  /*
3061  * Get connection to the foreign server. Connection manager will
3062  * establish new connection if necessary.
3063  */
3064  user = GetUserMapping(GetUserId(), serverid);
3065  conn = GetConnection(user, false, NULL);
3066 
3067  /* Construct the TRUNCATE command string */
3068  initStringInfo(&sql);
3069  deparseTruncateSql(&sql, rels, behavior, restart_seqs);
3070 
3071  /* Issue the TRUNCATE command to remote server */
3072  do_sql_command(conn, sql.data);
3073 
3074  pfree(sql.data);
3075 }
3076 
3077 /*
3078  * estimate_path_cost_size
3079  * Get cost and size estimates for a foreign scan on given foreign relation
3080  * either a base relation or a join between foreign relations or an upper
3081  * relation containing foreign relations.
3082  *
3083  * param_join_conds are the parameterization clauses with outer relations.
3084  * pathkeys specify the expected sort order if any for given path being costed.
3085  * fpextra specifies additional post-scan/join-processing steps such as the
3086  * final sort and the LIMIT restriction.
3087  *
3088  * The function returns the cost and size estimates in p_rows, p_width,
3089  * p_disabled_nodes, p_startup_cost and p_total_cost variables.
3090  */
3091 static void
3093  RelOptInfo *foreignrel,
3094  List *param_join_conds,
3095  List *pathkeys,
3096  PgFdwPathExtraData *fpextra,
3097  double *p_rows, int *p_width,
3098  int *p_disabled_nodes,
3099  Cost *p_startup_cost, Cost *p_total_cost)
3100 {
3101  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
3102  double rows;
3103  double retrieved_rows;
3104  int width;
3105  int disabled_nodes = 0;
3106  Cost startup_cost;
3107  Cost total_cost;
3108 
3109  /* Make sure the core code has set up the relation's reltarget */
3110  Assert(foreignrel->reltarget);
3111 
3112  /*
3113  * If the table or the server is configured to use remote estimates,
3114  * connect to the foreign server and execute EXPLAIN to estimate the
3115  * number of rows selected by the restriction+join clauses. Otherwise,
3116  * estimate rows using whatever statistics we have locally, in a way
3117  * similar to ordinary tables.
3118  */
3119  if (fpinfo->use_remote_estimate)
3120  {
3121  List *remote_param_join_conds;
3122  List *local_param_join_conds;
3123  StringInfoData sql;
3124  PGconn *conn;
3125  Selectivity local_sel;
3126  QualCost local_cost;
3127  List *fdw_scan_tlist = NIL;
3128  List *remote_conds;
3129 
3130  /* Required only to be passed to deparseSelectStmtForRel */
3131  List *retrieved_attrs;
3132 
3133  /*
3134  * param_join_conds might contain both clauses that are safe to send
3135  * across, and clauses that aren't.
3136  */
3137  classifyConditions(root, foreignrel, param_join_conds,
3138  &remote_param_join_conds, &local_param_join_conds);
3139 
3140  /* Build the list of columns to be fetched from the foreign server. */
3141  if (IS_JOIN_REL(foreignrel) || IS_UPPER_REL(foreignrel))
3142  fdw_scan_tlist = build_tlist_to_deparse(foreignrel);
3143  else
3144  fdw_scan_tlist = NIL;
3145 
3146  /*
3147  * The complete list of remote conditions includes everything from
3148  * baserestrictinfo plus any extra join_conds relevant to this
3149  * particular path.
3150  */
3151  remote_conds = list_concat(remote_param_join_conds,
3152  fpinfo->remote_conds);
3153 
3154  /*
3155  * Construct EXPLAIN query including the desired SELECT, FROM, and
3156  * WHERE clauses. Params and other-relation Vars are replaced by dummy
3157  * values, so don't request params_list.
3158  */
3159  initStringInfo(&sql);
3160  appendStringInfoString(&sql, "EXPLAIN ");
3161  deparseSelectStmtForRel(&sql, root, foreignrel, fdw_scan_tlist,
3162  remote_conds, pathkeys,
3163  fpextra ? fpextra->has_final_sort : false,
3164  fpextra ? fpextra->has_limit : false,
3165  false, &retrieved_attrs, NULL);
3166 
3167  /* Get the remote estimate */
3168  conn = GetConnection(fpinfo->user, false, NULL);
3169  get_remote_estimate(sql.data, conn, &rows, &width,
3170  &startup_cost, &total_cost);
3172 
3173  retrieved_rows = rows;
3174 
3175  /* Factor in the selectivity of the locally-checked quals */
3176  local_sel = clauselist_selectivity(root,
3177  local_param_join_conds,
3178  foreignrel->relid,
3179  JOIN_INNER,
3180  NULL);
3181  local_sel *= fpinfo->local_conds_sel;
3182 
3183  rows = clamp_row_est(rows * local_sel);
3184 
3185  /* Add in the eval cost of the locally-checked quals */
3186  startup_cost += fpinfo->local_conds_cost.startup;
3187  total_cost += fpinfo->local_conds_cost.per_tuple * retrieved_rows;
3188  cost_qual_eval(&local_cost, local_param_join_conds, root);
3189  startup_cost += local_cost.startup;
3190  total_cost += local_cost.per_tuple * retrieved_rows;
3191 
3192  /*
3193  * Add in tlist eval cost for each output row. In case of an
3194  * aggregate, some of the tlist expressions such as grouping
3195  * expressions will be evaluated remotely, so adjust the costs.
3196  */
3197  startup_cost += foreignrel->reltarget->cost.startup;
3198  total_cost += foreignrel->reltarget->cost.startup;
3199  total_cost += foreignrel->reltarget->cost.per_tuple * rows;
3200  if (IS_UPPER_REL(foreignrel))
3201  {
3202  QualCost tlist_cost;
3203 
3204  cost_qual_eval(&tlist_cost, fdw_scan_tlist, root);
3205  startup_cost -= tlist_cost.startup;
3206  total_cost -= tlist_cost.startup;
3207  total_cost -= tlist_cost.per_tuple * rows;
3208  }
3209  }
3210  else
3211  {
3212  Cost run_cost = 0;
3213 
3214  /*
3215  * We don't support join conditions in this mode (hence, no
3216  * parameterized paths can be made).
3217  */
3218  Assert(param_join_conds == NIL);
3219 
3220  /*
3221  * We will come here again and again with different set of pathkeys or
3222  * additional post-scan/join-processing steps that caller wants to
3223  * cost. We don't need to calculate the cost/size estimates for the
3224  * underlying scan, join, or grouping each time. Instead, use those
3225  * estimates if we have cached them already.
3226  */
3227  if (fpinfo->rel_startup_cost >= 0 && fpinfo->rel_total_cost >= 0)
3228  {
3229  Assert(fpinfo->retrieved_rows >= 0);
3230 
3231  rows = fpinfo->rows;
3232  retrieved_rows = fpinfo->retrieved_rows;
3233  width = fpinfo->width;
3234  startup_cost = fpinfo->rel_startup_cost;
3235  run_cost = fpinfo->rel_total_cost - fpinfo->rel_startup_cost;
3236 
3237  /*
3238  * If we estimate the costs of a foreign scan or a foreign join
3239  * with additional post-scan/join-processing steps, the scan or
3240  * join costs obtained from the cache wouldn't yet contain the
3241  * eval costs for the final scan/join target, which would've been
3242  * updated by apply_scanjoin_target_to_paths(); add the eval costs
3243  * now.
3244  */
3245  if (fpextra && !IS_UPPER_REL(foreignrel))
3246  {
3247  /* Shouldn't get here unless we have LIMIT */
3248  Assert(fpextra->has_limit);
3249  Assert(foreignrel->reloptkind == RELOPT_BASEREL ||
3250  foreignrel->reloptkind == RELOPT_JOINREL);
3251  startup_cost += foreignrel->reltarget->cost.startup;
3252  run_cost += foreignrel->reltarget->cost.per_tuple * rows;
3253  }
3254  }
3255  else if (IS_JOIN_REL(foreignrel))
3256  {
3257  PgFdwRelationInfo *fpinfo_i;
3258  PgFdwRelationInfo *fpinfo_o;
3259  QualCost join_cost;
3260  QualCost remote_conds_cost;
3261  double nrows;
3262 
3263  /* Use rows/width estimates made by the core code. */
3264  rows = foreignrel->rows;
3265  width = foreignrel->reltarget->width;
3266 
3267  /* For join we expect inner and outer relations set */
3268  Assert(fpinfo->innerrel && fpinfo->outerrel);
3269 
3270  fpinfo_i = (PgFdwRelationInfo *) fpinfo->innerrel->fdw_private;
3271  fpinfo_o = (PgFdwRelationInfo *) fpinfo->outerrel->fdw_private;
3272 
3273  /* Estimate of number of rows in cross product */
3274  nrows = fpinfo_i->rows * fpinfo_o->rows;
3275 
3276  /*
3277  * Back into an estimate of the number of retrieved rows. Just in
3278  * case this is nuts, clamp to at most nrows.
3279  */
3280  retrieved_rows = clamp_row_est(rows / fpinfo->local_conds_sel);
3281  retrieved_rows = Min(retrieved_rows, nrows);
3282 
3283  /*
3284  * The cost of foreign join is estimated as cost of generating
3285  * rows for the joining relations + cost for applying quals on the
3286  * rows.
3287  */
3288 
3289  /*
3290  * Calculate the cost of clauses pushed down to the foreign server
3291  */
3292  cost_qual_eval(&remote_conds_cost, fpinfo->remote_conds, root);
3293  /* Calculate the cost of applying join clauses */
3294  cost_qual_eval(&join_cost, fpinfo->joinclauses, root);
3295 
3296  /*
3297  * Startup cost includes startup cost of joining relations and the
3298  * startup cost for join and other clauses. We do not include the
3299  * startup cost specific to join strategy (e.g. setting up hash
3300  * tables) since we do not know what strategy the foreign server
3301  * is going to use.
3302  */
3303  startup_cost = fpinfo_i->rel_startup_cost + fpinfo_o->rel_startup_cost;
3304  startup_cost += join_cost.startup;
3305  startup_cost += remote_conds_cost.startup;
3306  startup_cost += fpinfo->local_conds_cost.startup;
3307 
3308  /*
3309  * Run time cost includes:
3310  *
3311  * 1. Run time cost (total_cost - startup_cost) of relations being
3312  * joined
3313  *
3314  * 2. Run time cost of applying join clauses on the cross product
3315  * of the joining relations.
3316  *
3317  * 3. Run time cost of applying pushed down other clauses on the
3318  * result of join
3319  *
3320  * 4. Run time cost of applying nonpushable other clauses locally
3321  * on the result fetched from the foreign server.
3322  */
3323  run_cost = fpinfo_i->rel_total_cost - fpinfo_i->rel_startup_cost;
3324  run_cost += fpinfo_o->rel_total_cost - fpinfo_o->rel_startup_cost;
3325  run_cost += nrows * join_cost.per_tuple;
3326  nrows = clamp_row_est(nrows * fpinfo->joinclause_sel);
3327  run_cost += nrows * remote_conds_cost.per_tuple;
3328  run_cost += fpinfo->local_conds_cost.per_tuple * retrieved_rows;
3329 
3330  /* Add in tlist eval cost for each output row */
3331  startup_cost += foreignrel->reltarget->cost.startup;
3332  run_cost += foreignrel->reltarget->cost.per_tuple * rows;
3333  }
3334  else if (IS_UPPER_REL(foreignrel))
3335  {
3336  RelOptInfo *outerrel = fpinfo->outerrel;
3337  PgFdwRelationInfo *ofpinfo;
3338  AggClauseCosts aggcosts;
3339  double input_rows;
3340  int numGroupCols;
3341  double numGroups = 1;
3342 
3343  /* The upper relation should have its outer relation set */
3344  Assert(outerrel);
3345  /* and that outer relation should have its reltarget set */
3346  Assert(outerrel->reltarget);
3347 
3348  /*
3349  * This cost model is mixture of costing done for sorted and
3350  * hashed aggregates in cost_agg(). We are not sure which
3351  * strategy will be considered at remote side, thus for
3352  * simplicity, we put all startup related costs in startup_cost
3353  * and all finalization and run cost are added in total_cost.
3354  */
3355 
3356  ofpinfo = (PgFdwRelationInfo *) outerrel->fdw_private;
3357 
3358  /* Get rows from input rel */
3359  input_rows = ofpinfo->rows;
3360 
3361  /* Collect statistics about aggregates for estimating costs. */
3362  MemSet(&aggcosts, 0, sizeof(AggClauseCosts));
3363  if (root->parse->hasAggs)
3364  {
3366  }
3367 
3368  /* Get number of grouping columns and possible number of groups */
3369  numGroupCols = list_length(root->processed_groupClause);
3370  numGroups = estimate_num_groups(root,
3371  get_sortgrouplist_exprs(root->processed_groupClause,
3372  fpinfo->grouped_tlist),
3373  input_rows, NULL, NULL);
3374 
3375  /*
3376  * Get the retrieved_rows and rows estimates. If there are HAVING
3377  * quals, account for their selectivity.
3378  */
3379  if (root->hasHavingQual)
3380  {
3381  /* Factor in the selectivity of the remotely-checked quals */
3382  retrieved_rows =
3383  clamp_row_est(numGroups *
3385  fpinfo->remote_conds,
3386  0,
3387  JOIN_INNER,
3388  NULL));
3389  /* Factor in the selectivity of the locally-checked quals */
3390  rows = clamp_row_est(retrieved_rows * fpinfo->local_conds_sel);
3391  }
3392  else
3393  {
3394  rows = retrieved_rows = numGroups;
3395  }
3396 
3397  /* Use width estimate made by the core code. */
3398  width = foreignrel->reltarget->width;
3399 
3400  /*-----
3401  * Startup cost includes:
3402  * 1. Startup cost for underneath input relation, adjusted for
3403  * tlist replacement by apply_scanjoin_target_to_paths()
3404  * 2. Cost of performing aggregation, per cost_agg()
3405  *-----
3406  */
3407  startup_cost = ofpinfo->rel_startup_cost;
3408  startup_cost += outerrel->reltarget->cost.startup;
3409  startup_cost += aggcosts.transCost.startup;
3410  startup_cost += aggcosts.transCost.per_tuple * input_rows;
3411  startup_cost += aggcosts.finalCost.startup;
3412  startup_cost += (cpu_operator_cost * numGroupCols) * input_rows;
3413 
3414  /*-----
3415  * Run time cost includes:
3416  * 1. Run time cost of underneath input relation, adjusted for
3417  * tlist replacement by apply_scanjoin_target_to_paths()
3418  * 2. Run time cost of performing aggregation, per cost_agg()
3419  *-----
3420  */
3421  run_cost = ofpinfo->rel_total_cost - ofpinfo->rel_startup_cost;
3422  run_cost += outerrel->reltarget->cost.per_tuple * input_rows;
3423  run_cost += aggcosts.finalCost.per_tuple * numGroups;
3424  run_cost += cpu_tuple_cost * numGroups;
3425 
3426  /* Account for the eval cost of HAVING quals, if any */
3427  if (root->hasHavingQual)
3428  {
3429  QualCost remote_cost;
3430 
3431  /* Add in the eval cost of the remotely-checked quals */
3432  cost_qual_eval(&remote_cost, fpinfo->remote_conds, root);
3433  startup_cost += remote_cost.startup;
3434  run_cost += remote_cost.per_tuple * numGroups;
3435  /* Add in the eval cost of the locally-checked quals */
3436  startup_cost += fpinfo->local_conds_cost.startup;
3437  run_cost += fpinfo->local_conds_cost.per_tuple * retrieved_rows;
3438  }
3439 
3440  /* Add in tlist eval cost for each output row */
3441  startup_cost += foreignrel->reltarget->cost.startup;
3442  run_cost += foreignrel->reltarget->cost.per_tuple * rows;
3443  }
3444  else
3445  {
3446  Cost cpu_per_tuple;
3447 
3448  /* Use rows/width estimates made by set_baserel_size_estimates. */
3449  rows = foreignrel->rows;
3450  width = foreignrel->reltarget->width;
3451 
3452  /*
3453  * Back into an estimate of the number of retrieved rows. Just in
3454  * case this is nuts, clamp to at most foreignrel->tuples.
3455  */
3456  retrieved_rows = clamp_row_est(rows / fpinfo->local_conds_sel);
3457  retrieved_rows = Min(retrieved_rows, foreignrel->tuples);
3458 
3459  /*
3460  * Cost as though this were a seqscan, which is pessimistic. We
3461  * effectively imagine the local_conds are being evaluated
3462  * remotely, too.
3463  */
3464  startup_cost = 0;
3465  run_cost = 0;
3466  run_cost += seq_page_cost * foreignrel->pages;
3467 
3468  startup_cost += foreignrel->baserestrictcost.startup;
3469  cpu_per_tuple = cpu_tuple_cost + foreignrel->baserestrictcost.per_tuple;
3470  run_cost += cpu_per_tuple * foreignrel->tuples;
3471 
3472  /* Add in tlist eval cost for each output row */
3473  startup_cost += foreignrel->reltarget->cost.startup;
3474  run_cost += foreignrel->reltarget->cost.per_tuple * rows;
3475  }
3476 
3477  /*
3478  * Without remote estimates, we have no real way to estimate the cost
3479  * of generating sorted output. It could be free if the query plan
3480  * the remote side would have chosen generates properly-sorted output
3481  * anyway, but in most cases it will cost something. Estimate a value
3482  * high enough that we won't pick the sorted path when the ordering
3483  * isn't locally useful, but low enough that we'll err on the side of
3484  * pushing down the ORDER BY clause when it's useful to do so.
3485  */
3486  if (pathkeys != NIL)
3487  {
3488  if (IS_UPPER_REL(foreignrel))
3489  {
3490  Assert(foreignrel->reloptkind == RELOPT_UPPER_REL &&
3491  fpinfo->stage == UPPERREL_GROUP_AGG);
3493  retrieved_rows, width,
3494  fpextra->limit_tuples,
3495  &disabled_nodes,
3496  &startup_cost, &run_cost);
3497  }
3498  else
3499  {
3500  startup_cost *= DEFAULT_FDW_SORT_MULTIPLIER;
3501  run_cost *= DEFAULT_FDW_SORT_MULTIPLIER;
3502  }
3503  }
3504 
3505  total_cost = startup_cost + run_cost;
3506 
3507  /* Adjust the cost estimates if we have LIMIT */
3508  if (fpextra && fpextra->has_limit)
3509  {
3510  adjust_limit_rows_costs(&rows, &startup_cost, &total_cost,
3511  fpextra->offset_est, fpextra->count_est);
3512  retrieved_rows = rows;
3513  }
3514  }
3515 
3516  /*
3517  * If this includes the final sort step, the given target, which will be
3518  * applied to the resulting path, might have different expressions from
3519  * the foreignrel's reltarget (see make_sort_input_target()); adjust tlist
3520  * eval costs.
3521  */
3522  if (fpextra && fpextra->has_final_sort &&
3523  fpextra->target != foreignrel->reltarget)
3524  {
3525  QualCost oldcost = foreignrel->reltarget->cost;
3526  QualCost newcost = fpextra->target->cost;
3527 
3528  startup_cost += newcost.startup - oldcost.startup;
3529  total_cost += newcost.startup - oldcost.startup;
3530  total_cost += (newcost.per_tuple - oldcost.per_tuple) * rows;
3531  }
3532 
3533  /*
3534  * Cache the retrieved rows and cost estimates for scans, joins, or
3535  * groupings without any parameterization, pathkeys, or additional
3536  * post-scan/join-processing steps, before adding the costs for
3537  * transferring data from the foreign server. These estimates are useful
3538  * for costing remote joins involving this relation or costing other
3539  * remote operations on this relation such as remote sorts and remote
3540  * LIMIT restrictions, when the costs can not be obtained from the foreign
3541  * server. This function will be called at least once for every foreign
3542  * relation without any parameterization, pathkeys, or additional
3543  * post-scan/join-processing steps.
3544  */
3545  if (pathkeys == NIL && param_join_conds == NIL && fpextra == NULL)
3546  {
3547  fpinfo->retrieved_rows = retrieved_rows;
3548  fpinfo->rel_startup_cost = startup_cost;
3549  fpinfo->rel_total_cost = total_cost;
3550  }
3551 
3552  /*
3553  * Add some additional cost factors to account for connection overhead
3554  * (fdw_startup_cost), transferring data across the network
3555  * (fdw_tuple_cost per retrieved row), and local manipulation of the data
3556  * (cpu_tuple_cost per retrieved row).
3557  */
3558  startup_cost += fpinfo->fdw_startup_cost;
3559  total_cost += fpinfo->fdw_startup_cost;
3560  total_cost += fpinfo->fdw_tuple_cost * retrieved_rows;
3561  total_cost += cpu_tuple_cost * retrieved_rows;
3562 
3563  /*
3564  * If we have LIMIT, we should prefer performing the restriction remotely
3565  * rather than locally, as the former avoids extra row fetches from the
3566  * remote that the latter might cause. But since the core code doesn't
3567  * account for such fetches when estimating the costs of the local
3568  * restriction (see create_limit_path()), there would be no difference
3569  * between the costs of the local restriction and the costs of the remote
3570  * restriction estimated above if we don't use remote estimates (except
3571  * for the case where the foreignrel is a grouping relation, the given
3572  * pathkeys is not NIL, and the effects of a bounded sort for that rel is
3573  * accounted for in costing the remote restriction). Tweak the costs of
3574  * the remote restriction to ensure we'll prefer it if LIMIT is a useful
3575  * one.
3576  */
3577  if (!fpinfo->use_remote_estimate &&
3578  fpextra && fpextra->has_limit &&
3579  fpextra->limit_tuples > 0 &&
3580  fpextra->limit_tuples < fpinfo->rows)
3581  {
3582  Assert(fpinfo->rows > 0);
3583  total_cost -= (total_cost - startup_cost) * 0.05 *
3584  (fpinfo->rows - fpextra->limit_tuples) / fpinfo->rows;
3585  }
3586 
3587  /* Return results. */
3588  *p_rows = rows;
3589  *p_width = width;
3590  *p_disabled_nodes = disabled_nodes;
3591  *p_startup_cost = startup_cost;
3592  *p_total_cost = total_cost;
3593 }
3594 
3595 /*
3596  * Estimate costs of executing a SQL statement remotely.
3597  * The given "sql" must be an EXPLAIN command.
3598  */
3599 static void
3600 get_remote_estimate(const char *sql, PGconn *conn,
3601  double *rows, int *width,
3602  Cost *startup_cost, Cost *total_cost)
3603 {
3604  PGresult *volatile res = NULL;
3605 
3606  /* PGresult must be released before leaving this function. */
3607  PG_TRY();
3608  {
3609  char *line;
3610  char *p;
3611  int n;
3612 
3613  /*
3614  * Execute EXPLAIN remotely.
3615  */
3616  res = pgfdw_exec_query(conn, sql, NULL);
3618  pgfdw_report_error(ERROR, res, conn, false, sql);
3619 
3620  /*
3621  * Extract cost numbers for topmost plan node. Note we search for a
3622  * left paren from the end of the line to avoid being confused by
3623  * other uses of parentheses.
3624  */
3625  line = PQgetvalue(res, 0, 0);
3626  p = strrchr(line, '(');
3627  if (p == NULL)
3628  elog(ERROR, "could not interpret EXPLAIN output: \"%s\"", line);
3629  n = sscanf(p, "(cost=%lf..%lf rows=%lf width=%d)",
3630  startup_cost, total_cost, rows, width);
3631  if (n != 4)
3632  elog(ERROR, "could not interpret EXPLAIN output: \"%s\"", line);
3633  }
3634  PG_FINALLY();
3635  {
3636  PQclear(res);
3637  }
3638  PG_END_TRY();
3639 }
3640 
3641 /*
3642  * Adjust the cost estimates of a foreign grouping path to include the cost of
3643  * generating properly-sorted output.
3644  */
3645 static void
3647  List *pathkeys,
3648  double retrieved_rows,
3649  double width,
3650  double limit_tuples,
3651  int *p_disabled_nodes,
3652  Cost *p_startup_cost,
3653  Cost *p_run_cost)
3654 {
3655  /*
3656  * If the GROUP BY clause isn't sort-able, the plan chosen by the remote
3657  * side is unlikely to generate properly-sorted output, so it would need
3658  * an explicit sort; adjust the given costs with cost_sort(). Likewise,
3659  * if the GROUP BY clause is sort-able but isn't a superset of the given
3660  * pathkeys, adjust the costs with that function. Otherwise, adjust the
3661  * costs by applying the same heuristic as for the scan or join case.
3662  */
3663  if (!grouping_is_sortable(root->processed_groupClause) ||
3664  !pathkeys_contained_in(pathkeys, root->group_pathkeys))
3665  {
3666  Path sort_path; /* dummy for result of cost_sort */
3667 
3668  cost_sort(&sort_path,
3669  root,
3670  pathkeys,
3671  0,
3672  *p_startup_cost + *p_run_cost,
3673  retrieved_rows,
3674  width,
3675  0.0,
3676  work_mem,
3677  limit_tuples);
3678 
3679  *p_startup_cost = sort_path.startup_cost;
3680  *p_run_cost = sort_path.total_cost - sort_path.startup_cost;
3681  }
3682  else
3683  {
3684  /*
3685  * The default extra cost seems too large for foreign-grouping cases;
3686  * add 1/4th of that default.
3687  */
3688  double sort_multiplier = 1.0 + (DEFAULT_FDW_SORT_MULTIPLIER
3689  - 1.0) * 0.25;
3690 
3691  *p_startup_cost *= sort_multiplier;
3692  *p_run_cost *= sort_multiplier;
3693  }
3694 }
3695 
3696 /*
3697  * Detect whether we want to process an EquivalenceClass member.
3698  *
3699  * This is a callback for use by generate_implied_equalities_for_column.
3700  */
3701 static bool
3704  void *arg)
3705 {
3707  Expr *expr = em->em_expr;
3708 
3709  /*
3710  * If we've identified what we're processing in the current scan, we only
3711  * want to match that expression.
3712  */
3713  if (state->current != NULL)
3714  return equal(expr, state->current);
3715 
3716  /*
3717  * Otherwise, ignore anything we've already processed.
3718  */
3719  if (list_member(state->already_used, expr))
3720  return false;
3721 
3722  /* This is the new target to process. */
3723  state->current = expr;
3724  return true;
3725 }
3726 
3727 /*
3728  * Create cursor for node's query with current parameter values.
3729  */
3730 static void
3732 {
3733  PgFdwScanState *fsstate = (PgFdwScanState *) node->fdw_state;
3734  ExprContext *econtext = node->ss.ps.ps_ExprContext;
3735  int numParams = fsstate->numParams;
3736  const char **values = fsstate->param_values;
3737  PGconn *conn = fsstate->conn;
3739  PGresult *res;
3740 
3741  /* First, process a pending asynchronous request, if any. */
3742  if (fsstate->conn_state->pendingAreq)
3744 
3745  /*
3746  * Construct array of query parameter values in text format. We do the
3747  * conversions in the short-lived per-tuple context, so as not to cause a
3748  * memory leak over repeated scans.
3749  */
3750  if (numParams > 0)
3751  {
3752  MemoryContext oldcontext;
3753 
3754  oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
3755 
3756  process_query_params(econtext,
3757  fsstate->param_flinfo,
3758  fsstate->param_exprs,
3759  values);
3760 
3761  MemoryContextSwitchTo(oldcontext);
3762  }
3763 
3764  /* Construct the DECLARE CURSOR command */
3765  initStringInfo(&buf);
3766  appendStringInfo(&buf, "DECLARE c%u CURSOR FOR\n%s",
3767  fsstate->cursor_number, fsstate->query);
3768 
3769  /*
3770  * Notice that we pass NULL for paramTypes, thus forcing the remote server
3771  * to infer types for all parameters. Since we explicitly cast every
3772  * parameter (see deparse.c), the "inference" is trivial and will produce
3773  * the desired result. This allows us to avoid assuming that the remote
3774  * server has the same OIDs we do for the parameters' types.
3775  */
3776  if (!PQsendQueryParams(conn, buf.data, numParams,
3777  NULL, values, NULL, NULL, 0))
3778  pgfdw_report_error(ERROR, NULL, conn, false, buf.data);
3779 
3780  /*
3781  * Get the result, and check for success.
3782  *
3783  * We don't use a PG_TRY block here, so be careful not to throw error
3784  * without releasing the PGresult.
3785  */
3788  pgfdw_report_error(ERROR, res, conn, true, fsstate->query);
3789  PQclear(res);
3790 
3791  /* Mark the cursor as created, and show no tuples have been retrieved */
3792  fsstate->cursor_exists = true;
3793  fsstate->tuples = NULL;
3794  fsstate->num_tuples = 0;
3795  fsstate->next_tuple = 0;
3796  fsstate->fetch_ct_2 = 0;
3797  fsstate->eof_reached = false;
3798 
3799  /* Clean up */
3800  pfree(buf.data);
3801 }
3802 
3803 /*
3804  * Fetch some more rows from the node's cursor.
3805  */
3806 static void
3808 {
3809  PgFdwScanState *fsstate = (PgFdwScanState *) node->fdw_state;
3810  PGresult *volatile res = NULL;
3811  MemoryContext oldcontext;
3812 
3813  /*
3814  * We'll store the tuples in the batch_cxt. First, flush the previous
3815  * batch.
3816  */
3817  fsstate->tuples = NULL;
3818  MemoryContextReset(fsstate->batch_cxt);
3819  oldcontext = MemoryContextSwitchTo(fsstate->batch_cxt);
3820 
3821  /* PGresult must be released before leaving this function. */
3822  PG_TRY();
3823  {
3824  PGconn *conn = fsstate->conn;
3825  int numrows;
3826  int i;
3827 
3828  if (fsstate->async_capable)
3829  {
3830  Assert(fsstate->conn_state->pendingAreq);
3831 
3832  /*
3833  * The query was already sent by an earlier call to
3834  * fetch_more_data_begin. So now we just fetch the result.
3835  */
3837  /* On error, report the original query, not the FETCH. */
3839  pgfdw_report_error(ERROR, res, conn, false, fsstate->query);
3840 
3841  /* Reset per-connection state */
3842  fsstate->conn_state->pendingAreq = NULL;
3843  }
3844  else
3845  {
3846  char sql[64];
3847 
3848  /* This is a regular synchronous fetch. */
3849  snprintf(sql, sizeof(sql), "FETCH %d FROM c%u",
3850  fsstate->fetch_size, fsstate->cursor_number);
3851 
3852  res = pgfdw_exec_query(conn, sql, fsstate->conn_state);
3853  /* On error, report the original query, not the FETCH. */
3855  pgfdw_report_error(ERROR, res, conn, false, fsstate->query);
3856  }
3857 
3858  /* Convert the data into HeapTuples */
3859  numrows = PQntuples(res);
3860  fsstate->tuples = (HeapTuple *) palloc0(numrows * sizeof(HeapTuple));
3861  fsstate->num_tuples = numrows;
3862  fsstate->next_tuple = 0;
3863 
3864  for (i = 0; i < numrows; i++)
3865  {
3866  Assert(IsA(node->ss.ps.plan, ForeignScan));
3867 
3868  fsstate->tuples[i] =
3870  fsstate->rel,
3871  fsstate->attinmeta,
3872  fsstate->retrieved_attrs,
3873  node,
3874  fsstate->temp_cxt);
3875  }
3876 
3877  /* Update fetch_ct_2 */
3878  if (fsstate->fetch_ct_2 < 2)
3879  fsstate->fetch_ct_2++;
3880 
3881  /* Must be EOF if we didn't get as many tuples as we asked for. */
3882  fsstate->eof_reached = (numrows < fsstate->fetch_size);
3883  }
3884  PG_FINALLY();
3885  {
3886  PQclear(res);
3887  }
3888  PG_END_TRY();
3889 
3890  MemoryContextSwitchTo(oldcontext);
3891 }
3892 
3893 /*
3894  * Force assorted GUC parameters to settings that ensure that we'll output
3895  * data values in a form that is unambiguous to the remote server.
3896  *
3897  * This is rather expensive and annoying to do once per row, but there's
3898  * little choice if we want to be sure values are transmitted accurately;
3899  * we can't leave the settings in place between rows for fear of affecting
3900  * user-visible computations.
3901  *
3902  * We use the equivalent of a function SET option to allow the settings to
3903  * persist only until the caller calls reset_transmission_modes(). If an
3904  * error is thrown in between, guc.c will take care of undoing the settings.
3905  *
3906  * The return value is the nestlevel that must be passed to
3907  * reset_transmission_modes() to undo things.
3908  */
3909 int
3911 {
3912  int nestlevel = NewGUCNestLevel();
3913 
3914  /*
3915  * The values set here should match what pg_dump does. See also
3916  * configure_remote_session in connection.c.
3917  */
3918  if (DateStyle != USE_ISO_DATES)
3919  (void) set_config_option("datestyle", "ISO",
3921  GUC_ACTION_SAVE, true, 0, false);
3923  (void) set_config_option("intervalstyle", "postgres",
3925  GUC_ACTION_SAVE, true, 0, false);
3926  if (extra_float_digits < 3)
3927  (void) set_config_option("extra_float_digits", "3",
3929  GUC_ACTION_SAVE, true, 0, false);
3930 
3931  /*
3932  * In addition force restrictive search_path, in case there are any
3933  * regproc or similar constants to be printed.
3934  */
3935  (void) set_config_option("search_path", "pg_catalog",
3937  GUC_ACTION_SAVE, true, 0, false);
3938 
3939  return nestlevel;
3940 }
3941 
3942 /*
3943  * Undo the effects of set_transmission_modes().
3944  */
3945 void
3947 {
3948  AtEOXact_GUC(true, nestlevel);
3949 }
3950 
3951 /*
3952  * Utility routine to close a cursor.
3953  */
3954 static void
3956  PgFdwConnState *conn_state)
3957 {
3958  char sql[64];
3959  PGresult *res;
3960 
3961  snprintf(sql, sizeof(sql), "CLOSE c%u", cursor_number);
3962 
3963  /*
3964  * We don't use a PG_TRY block here, so be careful not to throw error
3965  * without releasing the PGresult.
3966  */
3967  res = pgfdw_exec_query(conn, sql, conn_state);
3969  pgfdw_report_error(ERROR, res, conn, true, sql);
3970  PQclear(res);
3971 }
3972 
3973 /*
3974  * create_foreign_modify
3975  * Construct an execution state of a foreign insert/update/delete
3976  * operation
3977  */
3978 static PgFdwModifyState *
3980  RangeTblEntry *rte,
3981  ResultRelInfo *resultRelInfo,
3982  CmdType operation,
3983  Plan *subplan,
3984  char *query,
3985  List *target_attrs,
3986  int values_end,
3987  bool has_returning,
3988  List *retrieved_attrs)
3989 {
3990  PgFdwModifyState *fmstate;
3991  Relation rel = resultRelInfo->ri_RelationDesc;
3992  TupleDesc tupdesc = RelationGetDescr(rel);
3993  Oid userid;
3994  ForeignTable *table;
3995  UserMapping *user;
3996  AttrNumber n_params;
3997  Oid typefnoid;
3998  bool isvarlena;
3999  ListCell *lc;
4000 
4001  /* Begin constructing PgFdwModifyState. */
4002  fmstate = (PgFdwModifyState *) palloc0(sizeof(PgFdwModifyState));
4003  fmstate->rel = rel;
4004 
4005  /* Identify which user to do the remote access as. */
4006  userid = ExecGetResultRelCheckAsUser(resultRelInfo, estate);
4007 
4008  /* Get info about foreign table. */
4009  table = GetForeignTable(RelationGetRelid(rel));
4010  user = GetUserMapping(userid, table->serverid);
4011 
4012  /* Open connection; report that we'll create a prepared statement. */
4013  fmstate->conn = GetConnection(user, true, &fmstate->conn_state);
4014  fmstate->p_name = NULL; /* prepared statement not made yet */
4015 
4016  /* Set up remote query information. */
4017  fmstate->query = query;
4018  if (operation == CMD_INSERT)
4019  {
4020  fmstate->query = pstrdup(fmstate->query);
4021  fmstate->orig_query = pstrdup(fmstate->query);
4022  }
4023  fmstate->target_attrs = target_attrs;
4024  fmstate->values_end = values_end;
4025  fmstate->has_returning = has_returning;
4026  fmstate->retrieved_attrs = retrieved_attrs;
4027 
4028  /* Create context for per-tuple temp workspace. */
4029  fmstate->temp_cxt = AllocSetContextCreate(estate->es_query_cxt,
4030  "postgres_fdw temporary data",
4032 
4033  /* Prepare for input conversion of RETURNING results. */
4034  if (fmstate->has_returning)
4035  fmstate->attinmeta = TupleDescGetAttInMetadata(tupdesc);
4036 
4037  /* Prepare for output conversion of parameters used in prepared stmt. */
4038  n_params = list_length(fmstate->target_attrs) + 1;
4039  fmstate->p_flinfo = (FmgrInfo *) palloc0(sizeof(FmgrInfo) * n_params);
4040  fmstate->p_nums = 0;
4041 
4042  if (operation == CMD_UPDATE || operation == CMD_DELETE)
4043  {
4044  Assert(subplan != NULL);
4045 
4046  /* Find the ctid resjunk column in the subplan's result */
4048  "ctid");
4049  if (!AttributeNumberIsValid(fmstate->ctidAttno))
4050  elog(ERROR, "could not find junk ctid column");
4051 
4052  /* First transmittable parameter will be ctid */
4053  getTypeOutputInfo(TIDOID, &typefnoid, &isvarlena);
4054  fmgr_info(typefnoid, &fmstate->p_flinfo[fmstate->p_nums]);
4055  fmstate->p_nums++;
4056  }
4057 
4058  if (operation == CMD_INSERT || operation == CMD_UPDATE)
4059  {
4060  /* Set up for remaining transmittable parameters */
4061  foreach(lc, fmstate->target_attrs)
4062  {
4063  int attnum = lfirst_int(lc);
4064  Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1);
4065 
4066  Assert(!attr->attisdropped);
4067 
4068  /* Ignore generated columns; they are set to DEFAULT */
4069  if (attr->attgenerated)
4070  continue;
4071  getTypeOutputInfo(attr->atttypid, &typefnoid, &isvarlena);
4072  fmgr_info(typefnoid, &fmstate->p_flinfo[fmstate->p_nums]);
4073  fmstate->p_nums++;
4074  }
4075  }
4076 
4077  Assert(fmstate->p_nums <= n_params);
4078 
4079  /* Set batch_size from foreign server/table options. */
4080  if (operation == CMD_INSERT)
4081  fmstate->batch_size = get_batch_size_option(rel);
4082 
4083  fmstate->num_slots = 1;
4084 
4085  /* Initialize auxiliary state */
4086  fmstate->aux_fmstate = NULL;
4087 
4088  return fmstate;
4089 }
4090 
4091 /*
4092  * execute_foreign_modify
4093  * Perform foreign-table modification as required, and fetch RETURNING
4094  * result if any. (This is the shared guts of postgresExecForeignInsert,
4095  * postgresExecForeignBatchInsert, postgresExecForeignUpdate, and
4096  * postgresExecForeignDelete.)
4097  */
4098 static TupleTableSlot **
4100  ResultRelInfo *resultRelInfo,
4101  CmdType operation,
4102  TupleTableSlot **slots,
4103  TupleTableSlot **planSlots,
4104  int *numSlots)
4105 {
4106  PgFdwModifyState *fmstate = (PgFdwModifyState *) resultRelInfo->ri_FdwState;
4107  ItemPointer ctid = NULL;
4108  const char **p_values;
4109  PGresult *res;
4110  int n_rows;
4111  StringInfoData sql;
4112 
4113  /* The operation should be INSERT, UPDATE, or DELETE */
4114  Assert(operation == CMD_INSERT ||
4115  operation == CMD_UPDATE ||
4116  operation == CMD_DELETE);
4117 
4118  /* First, process a pending asynchronous request, if any. */
4119  if (fmstate->conn_state->pendingAreq)
4121 
4122  /*
4123  * If the existing query was deparsed and prepared for a different number
4124  * of rows, rebuild it for the proper number.
4125  */
4126  if (operation == CMD_INSERT && fmstate->num_slots != *numSlots)
4127  {
4128  /* Destroy the prepared statement created previously */
4129  if (fmstate->p_name)
4130  deallocate_query(fmstate);
4131 
4132  /* Build INSERT string with numSlots records in its VALUES clause. */
4133  initStringInfo(&sql);
4134  rebuildInsertSql(&sql, fmstate->rel,
4135  fmstate->orig_query, fmstate->target_attrs,
4136  fmstate->values_end, fmstate->p_nums,
4137  *numSlots - 1);
4138  pfree(fmstate->query);
4139  fmstate->query = sql.data;
4140  fmstate->num_slots = *numSlots;
4141  }
4142 
4143  /* Set up the prepared statement on the remote server, if we didn't yet */
4144  if (!fmstate->p_name)
4145  prepare_foreign_modify(fmstate);
4146 
4147  /*
4148  * For UPDATE/DELETE, get the ctid that was passed up as a resjunk column
4149  */
4150  if (operation == CMD_UPDATE || operation == CMD_DELETE)
4151  {
4152  Datum datum;
4153  bool isNull;
4154 
4155  datum = ExecGetJunkAttribute(planSlots[0],
4156  fmstate->ctidAttno,
4157  &isNull);
4158  /* shouldn't ever get a null result... */
4159  if (isNull)
4160  elog(ERROR, "ctid is NULL");
4161  ctid = (ItemPointer) DatumGetPointer(datum);
4162  }
4163 
4164  /* Convert parameters needed by prepared statement to text form */
4165  p_values = convert_prep_stmt_params(fmstate, ctid, slots, *numSlots);
4166 
4167  /*
4168  * Execute the prepared statement.
4169  */
4170  if (!PQsendQueryPrepared(fmstate->conn,
4171  fmstate->p_name,
4172  fmstate->p_nums * (*numSlots),
4173  p_values,
4174  NULL,
4175  NULL,
4176  0))
4177  pgfdw_report_error(ERROR, NULL, fmstate->conn, false, fmstate->query);
4178 
4179  /*
4180  * Get the result, and check for success.
4181  *
4182  * We don't use a PG_TRY block here, so be careful not to throw error
4183  * without releasing the PGresult.
4184  */
4185  res = pgfdw_get_result(fmstate->conn);
4186  if (PQresultStatus(res) !=
4188  pgfdw_report_error(ERROR, res, fmstate->conn, true, fmstate->query);
4189 
4190  /* Check number of rows affected, and fetch RETURNING tuple if any */
4191  if (fmstate->has_returning)
4192  {
4193  Assert(*numSlots == 1);
4194  n_rows = PQntuples(res);
4195  if (n_rows > 0)
4196  store_returning_result(fmstate, slots[0], res);
4197  }
4198  else
4199  n_rows = atoi(PQcmdTuples(res));
4200 
4201  /* And clean up */
4202  PQclear(res);
4203 
4204  MemoryContextReset(fmstate->temp_cxt);
4205 
4206  *numSlots = n_rows;
4207 
4208  /*
4209  * Return NULL if nothing was inserted/updated/deleted on the remote end
4210  */
4211  return (n_rows > 0) ? slots : NULL;
4212 }
4213 
4214 /*
4215  * prepare_foreign_modify
4216  * Establish a prepared statement for execution of INSERT/UPDATE/DELETE
4217  */
4218 static void
4220 {
4221  char prep_name[NAMEDATALEN];
4222  char *p_name;
4223  PGresult *res;
4224 
4225  /*
4226  * The caller would already have processed a pending asynchronous request
4227  * if any, so no need to do it here.
4228  */
4229 
4230  /* Construct name we'll use for the prepared statement. */
4231  snprintf(prep_name, sizeof(prep_name), "pgsql_fdw_prep_%u",
4232  GetPrepStmtNumber(fmstate->conn));
4233  p_name = pstrdup(prep_name);
4234 
4235  /*
4236  * We intentionally do not specify parameter types here, but leave the
4237  * remote server to derive them by default. This avoids possible problems
4238  * with the remote server using different type OIDs than we do. All of
4239  * the prepared statements we use in this module are simple enough that
4240  * the remote server will make the right choices.
4241  */
4242  if (!PQsendPrepare(fmstate->conn,
4243  p_name,
4244  fmstate->query,
4245  0,
4246  NULL))
4247  pgfdw_report_error(ERROR, NULL, fmstate->conn, false, fmstate->query);
4248 
4249  /*
4250  * Get the result, and check for success.
4251  *
4252  * We don't use a PG_TRY block here, so be careful not to throw error
4253  * without releasing the PGresult.
4254  */
4255  res = pgfdw_get_result(fmstate->conn);
4257  pgfdw_report_error(ERROR, res, fmstate->conn, true, fmstate->query);
4258  PQclear(res);
4259 
4260  /* This action shows that the prepare has been done. */
4261  fmstate->p_name = p_name;
4262 }
4263 
4264 /*
4265  * convert_prep_stmt_params
4266  * Create array of text strings representing parameter values
4267  *
4268  * tupleid is ctid to send, or NULL if none
4269  * slot is slot to get remaining parameters from, or NULL if none
4270  *
4271  * Data is constructed in temp_cxt; caller should reset that after use.
4272  */
4273 static const char **
4275  ItemPointer tupleid,
4276  TupleTableSlot **slots,
4277  int numSlots)
4278 {
4279  const char **p_values;
4280  int i;
4281  int j;
4282  int pindex = 0;
4283  MemoryContext oldcontext;
4284 
4285  oldcontext = MemoryContextSwitchTo(fmstate->temp_cxt);
4286 
4287  p_values = (const char **) palloc(sizeof(char *) * fmstate->p_nums * numSlots);
4288 
4289  /* ctid is provided only for UPDATE/DELETE, which don't allow batching */
4290  Assert(!(tupleid != NULL && numSlots > 1));
4291 
4292  /* 1st parameter should be ctid, if it's in use */
4293  if (tupleid != NULL)
4294  {
4295  Assert(numSlots == 1);
4296  /* don't need set_transmission_modes for TID output */
4297  p_values[pindex] = OutputFunctionCall(&fmstate->p_flinfo[pindex],
4298  PointerGetDatum(tupleid));
4299  pindex++;
4300  }
4301 
4302  /* get following parameters from slots */
4303  if (slots != NULL && fmstate->target_attrs != NIL)
4304  {
4305  TupleDesc tupdesc = RelationGetDescr(fmstate->rel);
4306  int nestlevel;
4307  ListCell *lc;
4308 
4309  nestlevel = set_transmission_modes();
4310 
4311  for (i = 0; i < numSlots; i++)
4312  {
4313  j = (tupleid != NULL) ? 1 : 0;
4314  foreach(lc, fmstate->target_attrs)
4315  {
4316  int attnum = lfirst_int(lc);
4317  Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1);
4318  Datum value;
4319  bool isnull;
4320 
4321  /* Ignore generated columns; they are set to DEFAULT */
4322  if (attr->attgenerated)
4323  continue;
4324  value = slot_getattr(slots[i], attnum, &isnull);
4325  if (isnull)
4326  p_values[pindex] = NULL;
4327  else
4328  p_values[pindex] = OutputFunctionCall(&fmstate->p_flinfo[j],
4329  value);
4330  pindex++;
4331  j++;
4332  }
4333  }
4334 
4335  reset_transmission_modes(nestlevel);
4336  }
4337 
4338  Assert(pindex == fmstate->p_nums * numSlots);
4339 
4340  MemoryContextSwitchTo(oldcontext);
4341 
4342  return p_values;
4343 }
4344 
4345 /*
4346  * store_returning_result
4347  * Store the result of a RETURNING clause
4348  *
4349  * On error, be sure to release the PGresult on the way out. Callers do not
4350  * have PG_TRY blocks to ensure this happens.
4351  */
4352 static void
4354  TupleTableSlot *slot, PGresult *res)
4355 {
4356  PG_TRY();
4357  {
4358  HeapTuple newtup;
4359 
4360  newtup = make_tuple_from_result_row(res, 0,
4361  fmstate->rel,
4362  fmstate->attinmeta,
4363  fmstate->retrieved_attrs,
4364  NULL,
4365  fmstate->temp_cxt);
4366 
4367  /*
4368  * The returning slot will not necessarily be suitable to store
4369  * heaptuples directly, so allow for conversion.
4370  */
4371  ExecForceStoreHeapTuple(newtup, slot, true);
4372  }
4373  PG_CATCH();
4374  {
4375  PQclear(res);
4376  PG_RE_THROW();
4377  }
4378  PG_END_TRY();
4379 }
4380 
4381 /*
4382  * finish_foreign_modify
4383  * Release resources for a foreign insert/update/delete operation
4384  */
4385 static void
4387 {
4388  Assert(fmstate != NULL);
4389 
4390  /* If we created a prepared statement, destroy it */
4391  deallocate_query(fmstate);
4392 
4393  /* Release remote connection */
4394  ReleaseConnection(fmstate->conn);
4395  fmstate->conn = NULL;
4396 }
4397 
4398 /*
4399  * deallocate_query
4400  * Deallocate a prepared statement for a foreign insert/update/delete
4401  * operation
4402  */
4403 static void
4405 {
4406  char sql[64];
4407  PGresult *res;
4408 
4409  /* do nothing if the query is not allocated */
4410  if (!fmstate->p_name)
4411  return;
4412 
4413  snprintf(sql, sizeof(sql), "DEALLOCATE %s", fmstate->p_name);
4414 
4415  /*
4416  * We don't use a PG_TRY block here, so be careful not to throw error
4417  * without releasing the PGresult.
4418  */
4419  res = pgfdw_exec_query(fmstate->conn, sql, fmstate->conn_state);
4421  pgfdw_report_error(ERROR, res, fmstate->conn, true, sql);
4422  PQclear(res);
4423  pfree(fmstate->p_name);
4424  fmstate->p_name = NULL;
4425 }
4426 
4427 /*
4428  * build_remote_returning
4429  * Build a RETURNING targetlist of a remote query for performing an
4430  * UPDATE/DELETE .. RETURNING on a join directly
4431  */
4432 static List *
4433 build_remote_returning(Index rtindex, Relation rel, List *returningList)
4434 {
4435  bool have_wholerow = false;
4436  List *tlist = NIL;
4437  List *vars;
4438  ListCell *lc;
4439 
4440  Assert(returningList);
4441 
4442  vars = pull_var_clause((Node *) returningList, PVC_INCLUDE_PLACEHOLDERS);
4443 
4444  /*
4445  * If there's a whole-row reference to the target relation, then we'll
4446  * need all the columns of the relation.
4447  */
4448  foreach(lc, vars)
4449  {
4450  Var *var = (Var *) lfirst(lc);
4451 
4452  if (IsA(var, Var) &&
4453  var->varno == rtindex &&
4454  var->varattno == InvalidAttrNumber)
4455  {
4456  have_wholerow = true;
4457  break;
4458  }
4459  }
4460 
4461  if (have_wholerow)
4462  {
4463  TupleDesc tupdesc = RelationGetDescr(rel);
4464  int i;
4465 
4466  for (i = 1; i <= tupdesc->natts; i++)
4467  {
4468  Form_pg_attribute attr = TupleDescAttr(tupdesc, i - 1);
4469  Var *var;
4470 
4471  /* Ignore dropped attributes. */
4472  if (attr->attisdropped)
4473  continue;
4474 
4475  var = makeVar(rtindex,
4476  i,
4477  attr->atttypid,
4478  attr->atttypmod,
4479  attr->attcollation,
4480  0);
4481 
4482  tlist = lappend(tlist,
4483  makeTargetEntry((Expr *) var,
4484  list_length(tlist) + 1,
4485  NULL,
4486  false));
4487  }
4488  }
4489 
4490  /* Now add any remaining columns to tlist. */
4491  foreach(lc, vars)
4492  {
4493  Var *var = (Var *) lfirst(lc);
4494 
4495  /*
4496  * No need for whole-row references to the target relation. We don't
4497  * need system columns other than ctid and oid either, since those are
4498  * set locally.
4499  */
4500  if (IsA(var, Var) &&
4501  var->varno == rtindex &&
4502  var->varattno <= InvalidAttrNumber &&
4504  continue; /* don't need it */
4505 
4506  if (tlist_member((Expr *) var, tlist))
4507  continue; /* already got it */
4508 
4509  tlist = lappend(tlist,
4510  makeTargetEntry((Expr *) var,
4511  list_length(tlist) + 1,
4512  NULL,
4513  false));
4514  }
4515 
4516  list_free(vars);
4517 
4518  return tlist;
4519 }
4520 
4521 /*
4522  * rebuild_fdw_scan_tlist
4523  * Build new fdw_scan_tlist of given foreign-scan plan node from given
4524  * tlist
4525  *
4526  * There might be columns that the fdw_scan_tlist of the given foreign-scan
4527  * plan node contains that the given tlist doesn't. The fdw_scan_tlist would
4528  * have contained resjunk columns such as 'ctid' of the target relation and
4529  * 'wholerow' of non-target relations, but the tlist might not contain them,
4530  * for example. So, adjust the tlist so it contains all the columns specified
4531  * in the fdw_scan_tlist; else setrefs.c will get confused.
4532  */
4533 static void
4535 {
4536  List *new_tlist = tlist;
4537  List *old_tlist = fscan->fdw_scan_tlist;
4538  ListCell *lc;
4539 
4540  foreach(lc, old_tlist)
4541  {
4542  TargetEntry *tle = (TargetEntry *) lfirst(lc);
4543 
4544  if (tlist_member(tle->expr, new_tlist))
4545  continue; /* already got it */
4546 
4547  new_tlist = lappend(new_tlist,
4548  makeTargetEntry(tle->expr,
4549  list_length(new_tlist) + 1,
4550  NULL,
4551  false));
4552  }
4553  fscan->fdw_scan_tlist = new_tlist;
4554 }
4555 
4556 /*
4557  * Execute a direct UPDATE/DELETE statement.
4558  */
4559 static void
4561 {
4563  ExprContext *econtext = node->ss.ps.ps_ExprContext;
4564  int numParams = dmstate->numParams;
4565  const char **values = dmstate->param_values;
4566 
4567  /* First, process a pending asynchronous request, if any. */
4568  if (dmstate->conn_state->pendingAreq)
4570 
4571  /*
4572  * Construct array of query parameter values in text format.
4573  */
4574  if (numParams > 0)
4575  process_query_params(econtext,
4576  dmstate->param_flinfo,
4577  dmstate->param_exprs,
4578  values);
4579 
4580  /*
4581  * Notice that we pass NULL for paramTypes, thus forcing the remote server
4582  * to infer types for all parameters. Since we explicitly cast every
4583  * parameter (see deparse.c), the "inference" is trivial and will produce
4584  * the desired result. This allows us to avoid assuming that the remote
4585  * server has the same OIDs we do for the parameters' types.
4586  */
4587  if (!PQsendQueryParams(dmstate->conn, dmstate->query, numParams,
4588  NULL, values, NULL, NULL, 0))
4589  pgfdw_report_error(ERROR, NULL, dmstate->conn, false, dmstate->query);
4590 
4591  /*
4592  * Get the result, and check for success.
4593  *
4594  * We don't use a PG_TRY block here, so be careful not to throw error
4595  * without releasing the PGresult.
4596  */
4597  dmstate->result = pgfdw_get_result(dmstate->conn);
4598  if (PQresultStatus(dmstate->result) !=
4600  pgfdw_report_error(ERROR, dmstate->result, dmstate->conn, true,
4601  dmstate->query);
4602 
4603  /* Get the number of rows affected. */
4604  if (dmstate->has_returning)
4605  dmstate->num_tuples = PQntuples(dmstate->result);
4606  else
4607  dmstate->num_tuples = atoi(PQcmdTuples(dmstate->result));
4608 }
4609 
4610 /*
4611  * Get the result of a RETURNING clause.
4612  */
4613 static TupleTableSlot *
4615 {
4617  EState *estate = node->ss.ps.state;
4618  ResultRelInfo *resultRelInfo = node->resultRelInfo;
4619  TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
4620  TupleTableSlot *resultSlot;
4621 
4622  Assert(resultRelInfo->ri_projectReturning);
4623 
4624  /* If we didn't get any tuples, must be end of data. */
4625  if (dmstate->next_tuple >= dmstate->num_tuples)
4626  return ExecClearTuple(slot);
4627 
4628  /* Increment the command es_processed count if necessary. */
4629  if (dmstate->set_processed)
4630  estate->es_processed += 1;
4631 
4632  /*
4633  * Store a RETURNING tuple. If has_returning is false, just emit a dummy
4634  * tuple. (has_returning is false when the local query is of the form
4635  * "UPDATE/DELETE .. RETURNING 1" for example.)
4636  */
4637  if (!dmstate->has_returning)
4638  {
4639  ExecStoreAllNullTuple(slot);
4640  resultSlot = slot;
4641  }
4642  else
4643  {
4644  /*
4645  * On error, be sure to release the PGresult on the way out. Callers
4646  * do not have PG_TRY blocks to ensure this happens.
4647  */
4648  PG_TRY();
4649  {
4650  HeapTuple newtup;
4651 
4652  newtup = make_tuple_from_result_row(dmstate->result,
4653  dmstate->next_tuple,
4654  dmstate->rel,
4655  dmstate->attinmeta,
4656  dmstate->retrieved_attrs,
4657  node,
4658  dmstate->temp_cxt);
4659  ExecStoreHeapTuple(newtup, slot, false);
4660  }
4661  PG_CATCH();
4662  {
4663  PQclear(dmstate->result);
4664  PG_RE_THROW();
4665  }
4666  PG_END_TRY();
4667 
4668  /* Get the updated/deleted tuple. */
4669  if (dmstate->rel)
4670  resultSlot = slot;
4671  else
4672  resultSlot = apply_returning_filter(dmstate, resultRelInfo, slot, estate);
4673  }
4674  dmstate->next_tuple++;
4675 
4676  /* Make slot available for evaluation of the local query RETURNING list. */
4677  resultRelInfo->ri_projectReturning->pi_exprContext->ecxt_scantuple =
4678  resultSlot;
4679 
4680  return slot;
4681 }
4682 
4683 /*
4684  * Initialize a filter to extract an updated/deleted tuple from a scan tuple.
4685  */
4686 static void
4688  List *fdw_scan_tlist,
4689  Index rtindex)
4690 {
4691  TupleDesc resultTupType = RelationGetDescr(dmstate->resultRel);
4692  ListCell *lc;
4693  int i;
4694 
4695  /*
4696  * Calculate the mapping between the fdw_scan_tlist's entries and the
4697  * result tuple's attributes.
4698  *
4699  * The "map" is an array of indexes of the result tuple's attributes in
4700  * fdw_scan_tlist, i.e., one entry for every attribute of the result
4701  * tuple. We store zero for any attributes that don't have the
4702  * corresponding entries in that list, marking that a NULL is needed in
4703  * the result tuple.
4704  *
4705  * Also get the indexes of the entries for ctid and oid if any.
4706  */
4707  dmstate->attnoMap = (AttrNumber *)
4708  palloc0(resultTupType->natts * sizeof(AttrNumber));
4709 
4710  dmstate->ctidAttno = dmstate->oidAttno = 0;
4711 
4712  i = 1;
4713  dmstate->hasSystemCols = false;
4714  foreach(lc, fdw_scan_tlist)
4715  {
4716  TargetEntry *tle = (TargetEntry *) lfirst(lc);
4717  Var *var = (Var *) tle->expr;
4718 
4719  Assert(IsA(var, Var));
4720 
4721  /*
4722  * If the Var is a column of the target relation to be retrieved from
4723  * the foreign server, get the index of the entry.
4724  */
4725  if (var->varno == rtindex &&
4726  list_member_int(dmstate->retrieved_attrs, i))
4727  {
4728  int attrno = var->varattno;
4729 
4730  if (attrno < 0)
4731  {
4732  /*
4733  * We don't retrieve system columns other than ctid and oid.
4734  */
4735  if (attrno == SelfItemPointerAttributeNumber)
4736  dmstate->ctidAttno = i;
4737  else
4738  Assert(false);
4739  dmstate->hasSystemCols = true;
4740  }
4741  else
4742  {
4743  /*
4744  * We don't retrieve whole-row references to the target
4745  * relation either.
4746  */
4747  Assert(attrno > 0);
4748 
4749  dmstate->attnoMap[attrno - 1] = i;
4750  }
4751  }
4752  i++;
4753  }
4754 }
4755 
4756 /*
4757  * Extract and return an updated/deleted tuple from a scan tuple.
4758  */
4759 static TupleTableSlot *
4761  ResultRelInfo *resultRelInfo,
4762  TupleTableSlot *slot,
4763  EState *estate)
4764 {
4765  TupleDesc resultTupType = RelationGetDescr(dmstate->resultRel);
4766  TupleTableSlot *resultSlot;
4767  Datum *values;
4768  bool *isnull;
4769  Datum *old_values;
4770  bool *old_isnull;
4771  int i;
4772 
4773  /*
4774  * Use the return tuple slot as a place to store the result tuple.
4775  */
4776  resultSlot = ExecGetReturningSlot(estate, resultRelInfo);
4777 
4778  /*
4779  * Extract all the values of the scan tuple.
4780  */
4781  slot_getallattrs(slot);
4782  old_values = slot->tts_values;
4783  old_isnull = slot->tts_isnull;
4784 
4785  /*
4786  * Prepare to build the result tuple.
4787  */
4788  ExecClearTuple(resultSlot);
4789  values = resultSlot->tts_values;
4790  isnull = resultSlot->tts_isnull;
4791 
4792  /*
4793  * Transpose data into proper fields of the result tuple.
4794  */
4795  for (i = 0; i < resultTupType->natts; i++)
4796  {
4797  int j = dmstate->attnoMap[i];
4798 
4799  if (j == 0)
4800  {
4801  values[i] = (Datum) 0;
4802  isnull[i] = true;
4803  }
4804  else
4805  {
4806  values[i] = old_values[j - 1];
4807  isnull[i] = old_isnull[j - 1];
4808  }
4809  }
4810 
4811  /*
4812  * Build the virtual tuple.
4813  */
4814  ExecStoreVirtualTuple(resultSlot);
4815 
4816  /*
4817  * If we have any system columns to return, materialize a heap tuple in
4818  * the slot from column values set above and install system columns in
4819  * that tuple.
4820  */
4821  if (dmstate->hasSystemCols)
4822  {
4823  HeapTuple resultTup = ExecFetchSlotHeapTuple(resultSlot, true, NULL);
4824 
4825  /* ctid */
4826  if (dmstate->ctidAttno)
4827  {
4828  ItemPointer ctid = NULL;
4829 
4830  ctid = (ItemPointer) DatumGetPointer(old_values[dmstate->ctidAttno - 1]);
4831  resultTup->t_self = *ctid;
4832  }
4833 
4834  /*
4835  * And remaining columns
4836  *
4837  * Note: since we currently don't allow the target relation to appear
4838  * on the nullable side of an outer join, any system columns wouldn't
4839  * go to NULL.
4840  *
4841  * Note: no need to care about tableoid here because it will be
4842  * initialized in ExecProcessReturning().
4843  */
4847  }
4848 
4849  /*
4850  * And return the result tuple.
4851  */
4852  return resultSlot;
4853 }
4854 
4855 /*
4856  * Prepare for processing of parameters used in remote query.
4857  */
4858 static void
4860  List *fdw_exprs,
4861  int numParams,
4862  FmgrInfo **param_flinfo,
4863  List **param_exprs,
4864  const char ***param_values)
4865 {
4866  int i;
4867  ListCell *lc;
4868 
4869  Assert(numParams > 0);
4870 
4871  /* Prepare for output conversion of parameters used in remote query. */
4872  *param_flinfo = (FmgrInfo *) palloc0(sizeof(FmgrInfo) * numParams);
4873 
4874  i = 0;
4875  foreach(lc, fdw_exprs)
4876  {
4877  Node *param_expr = (Node *) lfirst(lc);
4878  Oid typefnoid;
4879  bool isvarlena;
4880 
4881  getTypeOutputInfo(exprType(param_expr), &typefnoid, &isvarlena);
4882  fmgr_info(typefnoid, &(*param_flinfo)[i]);
4883  i++;
4884  }
4885 
4886  /*
4887  * Prepare remote-parameter expressions for evaluation. (Note: in
4888  * practice, we expect that all these expressions will be just Params, so
4889  * we could possibly do something more efficient than using the full
4890  * expression-eval machinery for this. But probably there would be little
4891  * benefit, and it'd require postgres_fdw to know more than is desirable
4892  * about Param evaluation.)
4893  */
4894  *param_exprs = ExecInitExprList(fdw_exprs, node);
4895 
4896  /* Allocate buffer for text form of query parameters. */
4897  *param_values = (const char **) palloc0(numParams * sizeof(char *));
4898 }
4899 
4900 /*
4901  * Construct array of query parameter values in text format.
4902  */
4903 static void
4905  FmgrInfo *param_flinfo,
4906  List *param_exprs,
4907  const char **param_values)
4908 {
4909  int nestlevel;
4910  int i;
4911  ListCell *lc;
4912 
4913  nestlevel = set_transmission_modes();
4914 
4915  i = 0;
4916  foreach(lc, param_exprs)
4917  {
4918  ExprState *expr_state = (ExprState *) lfirst(lc);
4919  Datum expr_value;
4920  bool isNull;
4921 
4922  /* Evaluate the parameter expression */
4923  expr_value = ExecEvalExpr(expr_state, econtext, &isNull);
4924 
4925  /*
4926  * Get string representation of each parameter value by invoking
4927  * type-specific output function, unless the value is null.
4928  */
4929  if (isNull)
4930  param_values[i] = NULL;
4931  else
4932  param_values[i] = OutputFunctionCall(&param_flinfo[i], expr_value);
4933 
4934  i++;
4935  }
4936 
4937  reset_transmission_modes(nestlevel);
4938 }
4939 
4940 /*
4941  * postgresAnalyzeForeignTable
4942  * Test whether analyzing this foreign table is supported
4943  */
4944 static bool
4946  AcquireSampleRowsFunc *func,
4947  BlockNumber *totalpages)
4948 {
4949  ForeignTable *table;
4950  UserMapping *user;
4951  PGconn *conn;
4952  StringInfoData sql;
4953  PGresult *volatile res = NULL;
4954 
4955  /* Return the row-analysis function pointer */
4957 
4958  /*
4959  * Now we have to get the number of pages. It's annoying that the ANALYZE
4960  * API requires us to return that now, because it forces some duplication
4961  * of effort between this routine and postgresAcquireSampleRowsFunc. But
4962  * it's probably not worth redefining that API at this point.
4963  */
4964 
4965  /*
4966  * Get the connection to use. We do the remote access as the table's
4967  * owner, even if the ANALYZE was started by some other user.
4968  */
4969  table = GetForeignTable(RelationGetRelid(relation));
4970  user = GetUserMapping(relation->rd_rel->relowner, table->serverid);
4971  conn = GetConnection(user, false, NULL);
4972 
4973  /*
4974  * Construct command to get page count for relation.
4975  */
4976  initStringInfo(&sql);
4977  deparseAnalyzeSizeSql(&sql, relation);
4978 
4979  /* In what follows, do not risk leaking any PGresults. */
4980  PG_TRY();
4981  {
4982  res = pgfdw_exec_query(conn, sql.data, NULL);
4984  pgfdw_report_error(ERROR, res, conn, false, sql.data);
4985 
4986  if (PQntuples(res) != 1 || PQnfields(res) != 1)
4987  elog(ERROR, "unexpected result from deparseAnalyzeSizeSql query");
4988  *totalpages = strtoul(PQgetvalue(res, 0, 0), NULL, 10);
4989  }
4990  PG_FINALLY();
4991  {
4992  PQclear(res);
4993  }
4994  PG_END_TRY();
4995 
4997 
4998  return true;
4999 }
5000 
5001 /*
5002  * postgresGetAnalyzeInfoForForeignTable
5003  * Count tuples in foreign table (just get pg_class.reltuples).
5004  *
5005  * can_tablesample determines if the remote relation supports acquiring the
5006  * sample using TABLESAMPLE.
5007  */
5008 static double
5009 postgresGetAnalyzeInfoForForeignTable(Relation relation, bool *can_tablesample)
5010 {
5011  ForeignTable *table;
5012  UserMapping *user;
5013  PGconn *conn;
5014  StringInfoData sql;
5015  PGresult *volatile res = NULL;
5016  volatile double reltuples = -1;
5017  volatile char relkind = 0;
5018 
5019  /* assume the remote relation does not support TABLESAMPLE */
5020  *can_tablesample = false;
5021 
5022  /*
5023  * Get the connection to use. We do the remote access as the table's
5024  * owner, even if the ANALYZE was started by some other user.
5025  */
5026  table = GetForeignTable(RelationGetRelid(relation));
5027  user = GetUserMapping(relation->rd_rel->relowner, table->serverid);
5028  conn = GetConnection(user, false, NULL);
5029 
5030  /*
5031  * Construct command to get page count for relation.
5032  */
5033  initStringInfo(&sql);
5034  deparseAnalyzeInfoSql(&sql, relation);
5035 
5036  /* In what follows, do not risk leaking any PGresults. */
5037  PG_TRY();
5038  {
5039  res = pgfdw_exec_query(conn, sql.data, NULL);
5041  pgfdw_report_error(ERROR, res, conn, false, sql.data);
5042 
5043  if (PQntuples(res) != 1 || PQnfields(res) != 2)
5044  elog(ERROR, "unexpected result from deparseAnalyzeInfoSql query");
5045  reltuples = strtod(PQgetvalue(res, 0, 0), NULL);
5046  relkind = *(PQgetvalue(res, 0, 1));
5047  }
5048  PG_FINALLY();
5049  {
5050  if (res)
5051  PQclear(res);
5052  }
5053  PG_END_TRY();
5054 
5056 
5057  /* TABLESAMPLE is supported only for regular tables and matviews */
5058  *can_tablesample = (relkind == RELKIND_RELATION ||
5059  relkind == RELKIND_MATVIEW ||
5060  relkind == RELKIND_PARTITIONED_TABLE);
5061 
5062  return reltuples;
5063 }
5064 
5065 /*
5066  * Acquire a random sample of rows from foreign table managed by postgres_fdw.
5067  *
5068  * Selected rows are returned in the caller-allocated array rows[],
5069  * which must have at least targrows entries.
5070  * The actual number of rows selected is returned as the function result.
5071  * We also count the total number of rows in the table and return it into
5072  * *totalrows. Note that *totaldeadrows is always set to 0.
5073  *
5074  * Note that the returned list of rows is not always in order by physical
5075  * position in the table. Therefore, correlation estimates derived later
5076  * may be meaningless, but it's OK because we don't use the estimates
5077  * currently (the planner only pays attention to correlation for indexscans).
5078  */
5079 static int
5081  HeapTuple *rows, int targrows,
5082  double *totalrows,
5083  double *totaldeadrows)
5084 {
5085  PgFdwAnalyzeState astate;
5086  ForeignTable *table;
5087  ForeignServer *server;
5088  UserMapping *user;
5089  PGconn *conn;
5090  int server_version_num;
5091  PgFdwSamplingMethod method = ANALYZE_SAMPLE_AUTO; /* auto is default */
5092  double sample_frac = -1.0;
5093  double reltuples;
5094  unsigned int cursor_number;
5095  StringInfoData sql;
5096  PGresult *volatile res = NULL;
5097  ListCell *lc;
5098 
5099  /* Initialize workspace state */
5100  astate.rel = relation;
5102 
5103  astate.rows = rows;
5104  astate.targrows = targrows;
5105  astate.numrows = 0;
5106  astate.samplerows = 0;
5107  astate.rowstoskip = -1; /* -1 means not set yet */
5108  reservoir_init_selection_state(&astate.rstate, targrows);
5109 
5110  /* Remember ANALYZE context, and create a per-tuple temp context */
5111  astate.anl_cxt = CurrentMemoryContext;
5113  "postgres_fdw temporary data",
5115 
5116  /*
5117  * Get the connection to use. We do the remote access as the table's
5118  * owner, even if the ANALYZE was started by some other user.
5119  */
5120  table = GetForeignTable(RelationGetRelid(relation));
5121  server = GetForeignServer(table->serverid);
5122  user = GetUserMapping(relation->rd_rel->relowner, table->serverid);
5123  conn = GetConnection(user, false, NULL);
5124 
5125  /* We'll need server version, so fetch it now. */
5127 
5128  /*
5129  * What sampling method should we use?
5130  */
5131  foreach(lc, server->options)
5132  {
5133  DefElem *def = (DefElem *) lfirst(lc);
5134 
5135  if (strcmp(def->defname, "analyze_sampling") == 0)
5136  {
5137  char *value = defGetString(def);
5138 
5139  if (strcmp(value, "off") == 0)
5140  method = ANALYZE_SAMPLE_OFF;
5141  else if (strcmp(value, "auto") == 0)
5142  method = ANALYZE_SAMPLE_AUTO;
5143  else if (strcmp(value, "random") == 0)
5144  method = ANALYZE_SAMPLE_RANDOM;
5145  else if (strcmp(value, "system") == 0)
5146  method = ANALYZE_SAMPLE_SYSTEM;
5147  else if (strcmp(value, "bernoulli") == 0)
5148  method = ANALYZE_SAMPLE_BERNOULLI;
5149 
5150  break;
5151  }
5152  }
5153 
5154  foreach(lc, table->options)
5155  {
5156  DefElem *def = (DefElem *) lfirst(lc);
5157 
5158  if (strcmp(def->defname, "analyze_sampling") == 0)
5159  {
5160  char *value = defGetString(def);
5161 
5162  if (strcmp(value, "off") == 0)
5163  method = ANALYZE_SAMPLE_OFF;
5164  else if (strcmp(value, "auto") == 0)
5165  method = ANALYZE_SAMPLE_AUTO;
5166  else if (strcmp(value, "random") == 0)
5167  method = ANALYZE_SAMPLE_RANDOM;
5168  else if (strcmp(value, "system") == 0)
5169  method = ANALYZE_SAMPLE_SYSTEM;
5170  else if (strcmp(value, "bernoulli") == 0)
5171  method = ANALYZE_SAMPLE_BERNOULLI;
5172 
5173  break;
5174  }
5175  }
5176 
5177  /*
5178  * Error-out if explicitly required one of the TABLESAMPLE methods, but
5179  * the server does not support it.
5180  */
5181  if ((server_version_num < 95000) &&
5182  (method == ANALYZE_SAMPLE_SYSTEM ||
5183  method == ANALYZE_SAMPLE_BERNOULLI))
5184  ereport(ERROR,
5185  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5186  errmsg("remote server does not support TABLESAMPLE feature")));
5187 
5188  /*
5189  * If we've decided to do remote sampling, calculate the sampling rate. We
5190  * need to get the number of tuples from the remote server, but skip that
5191  * network round-trip if not needed.
5192  */
5193  if (method != ANALYZE_SAMPLE_OFF)
5194  {
5195  bool can_tablesample;
5196 
5197  reltuples = postgresGetAnalyzeInfoForForeignTable(relation,
5198  &can_tablesample);
5199 
5200  /*
5201  * Make sure we're not choosing TABLESAMPLE when the remote relation
5202  * does not support that. But only do this for "auto" - if the user
5203  * explicitly requested BERNOULLI/SYSTEM, it's better to fail.
5204  */
5205  if (!can_tablesample && (method == ANALYZE_SAMPLE_AUTO))
5206  method = ANALYZE_SAMPLE_RANDOM;
5207 
5208  /*
5209  * Remote's reltuples could be 0 or -1 if the table has never been
5210  * vacuumed/analyzed. In that case, disable sampling after all.
5211  */
5212  if ((reltuples <= 0) || (targrows >= reltuples))
5213  method = ANALYZE_SAMPLE_OFF;
5214  else
5215  {
5216  /*
5217  * All supported sampling methods require sampling rate, not
5218  * target rows directly, so we calculate that using the remote
5219  * reltuples value. That's imperfect, because it might be off a
5220  * good deal, but that's not something we can (or should) address
5221  * here.
5222  *
5223  * If reltuples is too low (i.e. when table grew), we'll end up
5224  * sampling more rows - but then we'll apply the local sampling,
5225  * so we get the expected sample size. This is the same outcome as
5226  * without remote sampling.
5227  *
5228  * If reltuples is too high (e.g. after bulk DELETE), we will end
5229  * up sampling too few rows.
5230  *
5231  * We can't really do much better here - we could try sampling a
5232  * bit more rows, but we don't know how off the reltuples value is
5233  * so how much is "a bit more"?
5234  *
5235  * Furthermore, the targrows value for partitions is determined
5236  * based on table size (relpages), which can be off in different
5237  * ways too. Adjusting the sampling rate here might make the issue
5238  * worse.
5239  */
5240  sample_frac = targrows / reltuples;
5241 
5242  /*
5243  * We should never get sampling rate outside the valid range
5244  * (between 0.0 and 1.0), because those cases should be covered by
5245  * the previous branch that sets ANALYZE_SAMPLE_OFF.
5246  */
5247  Assert(sample_frac >= 0.0 && sample_frac <= 1.0);
5248  }
5249  }
5250 
5251  /*
5252  * For "auto" method, pick the one we believe is best. For servers with
5253  * TABLESAMPLE support we pick BERNOULLI, for old servers we fall-back to
5254  * random() to at least reduce network transfer.
5255  */
5256  if (method == ANALYZE_SAMPLE_AUTO)
5257  {
5258  if (server_version_num < 95000)
5259  method = ANALYZE_SAMPLE_RANDOM;
5260  else
5261  method = ANALYZE_SAMPLE_BERNOULLI;
5262  }
5263 
5264  /*
5265  * Construct cursor that retrieves whole rows from remote.
5266  */
5268  initStringInfo(&sql);
5269  appendStringInfo(&sql, "DECLARE c%u CURSOR FOR ", cursor_number);
5270 
5271  deparseAnalyzeSql(&sql, relation, method, sample_frac, &astate.retrieved_attrs);
5272 
5273  /* In what follows, do not risk leaking any PGresults. */
5274  PG_TRY();
5275  {
5276  char fetch_sql[64];
5277  int fetch_size;
5278 
5279  res = pgfdw_exec_query(conn, sql.data, NULL);
5281  pgfdw_report_error(ERROR, res, conn, false, sql.data);
5282  PQclear(res);
5283  res = NULL;
5284 
5285  /*
5286  * Determine the fetch size. The default is arbitrary, but shouldn't
5287  * be enormous.
5288  */
5289  fetch_size = 100;
5290  foreach(lc, server->options)
5291  {
5292  DefElem *def = (DefElem *) lfirst(lc);
5293 
5294  if (strcmp(def->defname, "fetch_size") == 0)
5295  {
5296  (void) parse_int(defGetString(def), &fetch_size, 0, NULL);
5297  break;
5298  }
5299  }
5300  foreach(lc, table->options)
5301  {
5302  DefElem *def = (DefElem *) lfirst(lc);
5303 
5304  if (strcmp(def->defname, "fetch_size") == 0)
5305  {
5306  (void) parse_int(defGetString(def), &fetch_size, 0, NULL);
5307  break;
5308  }
5309  }
5310 
5311  /* Construct command to fetch rows from remote. */
5312  snprintf(fetch_sql, sizeof(fetch_sql), "FETCH %d FROM c%u",
5314 
5315  /* Retrieve and process rows a batch at a time. */
5316  for (;;)
5317  {
5318  int numrows;
5319  int i;
5320 
5321  /* Allow users to cancel long query */
5323 
5324  /*
5325  * XXX possible future improvement: if rowstoskip is large, we
5326  * could issue a MOVE rather than physically fetching the rows,
5327  * then just adjust rowstoskip and samplerows appropriately.
5328  */
5329 
5330  /* Fetch some rows */
5331  res = pgfdw_exec_query(conn, fetch_sql, NULL);
5332  /* On error, report the original query, not the FETCH. */
5334  pgfdw_report_error(ERROR, res, conn, false, sql.data);
5335 
5336  /* Process whatever we got. */
5337  numrows = PQntuples(res);
5338  for (i = 0; i < numrows; i++)
5339  analyze_row_processor(res, i, &astate);
5340 
5341  PQclear(res);
5342  res = NULL;
5343 
5344  /* Must be EOF if we didn't get all the rows requested. */
5345  if (numrows < fetch_size)
5346  break;
5347  }
5348 
5349  /* Close the cursor, just to be tidy. */
5351  }
5352  PG_CATCH();
5353  {
5354  PQclear(res);
5355  PG_RE_THROW();
5356  }
5357  PG_END_TRY();
5358 
5360 
5361  /* We assume that we have no dead tuple. */
5362  *totaldeadrows = 0.0;
5363 
5364  /*
5365  * Without sampling, we've retrieved all living tuples from foreign
5366  * server, so report that as totalrows. Otherwise use the reltuples
5367  * estimate we got from the remote side.
5368  */
5369  if (method == ANALYZE_SAMPLE_OFF)
5370  *totalrows = astate.samplerows;
5371  else
5372  *totalrows = reltuples;
5373 
5374  /*
5375  * Emit some interesting relation info
5376  */
5377  ereport(elevel,
5378  (errmsg("\"%s\": table contains %.0f rows, %d rows in sample",
5379  RelationGetRelationName(relation),
5380  *totalrows, astate.numrows)));
5381 
5382  return astate.numrows;
5383 }
5384 
5385 /*
5386  * Collect sample rows from the result of query.
5387  * - Use all tuples in sample until target # of samples are collected.
5388  * - Subsequently, replace already-sampled tuples randomly.
5389  */
5390 static void
5392 {
5393  int targrows = astate->targrows;
5394  int pos; /* array index to store tuple in */
5395  MemoryContext oldcontext;
5396 
5397  /* Always increment sample row counter. */
5398  astate->samplerows += 1;
5399 
5400  /*
5401  * Determine the slot where this sample row should be stored. Set pos to
5402  * negative value to indicate the row should be skipped.
5403  */
5404  if (astate->numrows < targrows)
5405  {
5406  /* First targrows rows are always included into the sample */
5407  pos = astate->numrows++;
5408  }
5409  else
5410  {
5411  /*
5412  * Now we start replacing tuples in the sample until we reach the end
5413  * of the relation. Same algorithm as in acquire_sample_rows in
5414  * analyze.c; see Jeff Vitter's paper.
5415  */
5416  if (astate->rowstoskip < 0)
5417  astate->rowstoskip = reservoir_get_next_S(&astate->rstate, astate->samplerows, targrows);
5418 
5419  if (astate->rowstoskip <= 0)
5420  {
5421  /* Choose a random reservoir element to replace. */
5422  pos = (int) (targrows * sampler_random_fract(&astate->rstate.randstate));
5423  Assert(pos >= 0 && pos < targrows);
5424  heap_freetuple(astate->rows[pos]);
5425  }
5426  else
5427  {
5428  /* Skip this tuple. */
5429  pos = -1;
5430  }
5431 
5432  astate->rowstoskip -= 1;
5433  }
5434 
5435  if (pos >= 0)
5436  {
5437  /*
5438  * Create sample tuple from current result row, and store it in the
5439  * position determined above. The tuple has to be created in anl_cxt.
5440  */
5441  oldcontext = MemoryContextSwitchTo(astate->anl_cxt);
5442 
5443  astate->rows[pos] = make_tuple_from_result_row(res, row,
5444  astate->rel,
5445  astate->attinmeta,
5446  astate->retrieved_attrs,
5447  NULL,
5448  astate->temp_cxt);
5449 
5450  MemoryContextSwitchTo(oldcontext);
5451  }
5452 }
5453 
5454 /*
5455  * Import a foreign schema
5456  */
5457 static List *
5459 {
5460  List *commands = NIL;
5461  bool import_collate = true;
5462  bool import_default = false;
5463  bool import_generated = true;
5464  bool import_not_null = true;
5465  ForeignServer *server;
5466  UserMapping *mapping;
5467  PGconn *conn;
5469  PGresult *volatile res = NULL;
5470  int numrows,
5471  i;
5472  ListCell *lc;
5473 
5474  /* Parse statement options */
5475  foreach(lc, stmt->options)
5476  {
5477  DefElem *def = (DefElem *) lfirst(lc);
5478 
5479  if (strcmp(def->defname, "import_collate") == 0)
5480  import_collate = defGetBoolean(def);
5481  else if (strcmp(def->defname, "import_default") == 0)
5482  import_default = defGetBoolean(def);
5483  else if (strcmp(def->defname, "import_generated") == 0)
5484  import_generated = defGetBoolean(def);
5485  else if (strcmp(def->defname, "import_not_null") == 0)
5486  import_not_null = defGetBoolean(def);
5487  else
5488  ereport(ERROR,
5489  (errcode(ERRCODE_FDW_INVALID_OPTION_NAME),
5490  errmsg("invalid option \"%s\"", def->defname)));
5491  }
5492 
5493  /*
5494  * Get connection to the foreign server. Connection manager will
5495  * establish new connection if necessary.
5496  */
5497  server = GetForeignServer(serverOid);
5498  mapping = GetUserMapping(GetUserId(), server->serverid);
5499  conn = GetConnection(mapping, false, NULL);
5500 
5501  /* Don't attempt to import collation if remote server hasn't got it */
5502  if (PQserverVersion(conn) < 90100)
5503  import_collate = false;
5504 
5505  /* Create workspace for strings */
5506  initStringInfo(&buf);
5507 
5508  /* In what follows, do not risk leaking any PGresults. */
5509  PG_TRY();
5510  {
5511  /* Check that the schema really exists */
5512  appendStringInfoString(&buf, "SELECT 1 FROM pg_catalog.pg_namespace WHERE nspname = ");
5513  deparseStringLiteral(&buf, stmt->remote_schema);
5514 
5515  res = pgfdw_exec_query(conn, buf.data, NULL);
5517  pgfdw_report_error(ERROR, res, conn, false, buf.data);
5518 
5519  if (PQntuples(res) != 1)
5520  ereport(ERROR,
5521  (errcode(ERRCODE_FDW_SCHEMA_NOT_FOUND),
5522  errmsg("schema \"%s\" is not present on foreign server \"%s\"",
5523  stmt->remote_schema, server->servername)));
5524 
5525  PQclear(res);
5526  res = NULL;
5527  resetStringInfo(&buf);
5528 
5529  /*
5530  * Fetch all table data from this schema, possibly restricted by
5531  * EXCEPT or LIMIT TO. (We don't actually need to pay any attention
5532  * to EXCEPT/LIMIT TO here, because the core code will filter the
5533  * statements we return according to those lists anyway. But it
5534  * should save a few cycles to not process excluded tables in the
5535  * first place.)
5536  *
5537  * Import table data for partitions only when they are explicitly
5538  * specified in LIMIT TO clause. Otherwise ignore them and only
5539  * include the definitions of the root partitioned tables to allow
5540  * access to the complete remote data set locally in the schema
5541  * imported.
5542  *
5543  * Note: because we run the connection with search_path restricted to
5544  * pg_catalog, the format_type() and pg_get_expr() outputs will always
5545  * include a schema name for types/functions in other schemas, which
5546  * is what we want.
5547  */
5549  "SELECT relname, "
5550  " attname, "
5551  " format_type(atttypid, atttypmod), "
5552  " attnotnull, "
5553  " pg_get_expr(adbin, adrelid), ");
5554 
5555  /* Generated columns are supported since Postgres 12 */
5556  if (PQserverVersion(conn) >= 120000)
5558  " attgenerated, ");
5559  else
5561  " NULL, ");
5562 
5563  if (import_collate)
5565  " collname, "
5566  " collnsp.nspname ");
5567  else
5569  " NULL, NULL ");
5570 
5572  "FROM pg_class c "
5573  " JOIN pg_namespace n ON "
5574  " relnamespace = n.oid "
5575  " LEFT JOIN pg_attribute a ON "
5576  " attrelid = c.oid AND attnum > 0 "
5577  " AND NOT attisdropped "
5578  " LEFT JOIN pg_attrdef ad ON "
5579  " adrelid = c.oid AND adnum = attnum ");
5580 
5581  if (import_collate)
5583  " LEFT JOIN pg_collation coll ON "
5584  " coll.oid = attcollation "
5585  " LEFT JOIN pg_namespace collnsp ON "
5586  " collnsp.oid = collnamespace ");
5587 
5589  "WHERE c.relkind IN ("
5590  CppAsString2(RELKIND_RELATION) ","
5591  CppAsString2(RELKIND_VIEW) ","
5592  CppAsString2(RELKIND_FOREIGN_TABLE) ","
5593  CppAsString2(RELKIND_MATVIEW) ","
5594  CppAsString2(RELKIND_PARTITIONED_TABLE) ") "
5595  " AND n.nspname = ");
5596  deparseStringLiteral(&buf, stmt->remote_schema);
5597 
5598  /* Partitions are supported since Postgres 10 */
5599  if (PQserverVersion(conn) >= 100000 &&
5600  stmt->list_type != FDW_IMPORT_SCHEMA_LIMIT_TO)
5601  appendStringInfoString(&buf, " AND NOT c.relispartition ");
5602 
5603  /* Apply restrictions for LIMIT TO and EXCEPT */
5604  if (stmt->list_type == FDW_IMPORT_SCHEMA_LIMIT_TO ||
5605  stmt->list_type == FDW_IMPORT_SCHEMA_EXCEPT)
5606  {
5607  bool first_item = true;
5608 
5609  appendStringInfoString(&buf, " AND c.relname ");
5610  if (stmt->list_type == FDW_IMPORT_SCHEMA_EXCEPT)
5611  appendStringInfoString(&buf, "NOT ");
5612  appendStringInfoString(&buf, "IN (");
5613 
5614  /* Append list of table names within IN clause */
5615  foreach(lc, stmt->table_list)
5616  {
5617  RangeVar *rv = (RangeVar *) lfirst(lc);
5618 
5619  if (first_item)
5620  first_item = false;
5621  else
5622  appendStringInfoString(&buf, ", ");
5624  }
5625  appendStringInfoChar(&buf, ')');
5626  }
5627 
5628  /* Append ORDER BY at the end of query to ensure output ordering */
5629  appendStringInfoString(&buf, " ORDER BY c.relname, a.attnum");
5630 
5631  /* Fetch the data */
5632  res = pgfdw_exec_query(conn, buf.data, NULL);
5634  pgfdw_report_error(ERROR, res, conn, false, buf.data);
5635 
5636  /* Process results */
5637  numrows = PQntuples(res);
5638  /* note: incrementation of i happens in inner loop's while() test */
5639  for (i = 0; i < numrows;)
5640  {
5641  char *tablename = PQgetvalue(res, i, 0);
5642  bool first_item = true;
5643 
5644  resetStringInfo(&buf);
5645  appendStringInfo(&buf, "CREATE FOREIGN TABLE %s (\n",
5646  quote_identifier(tablename));
5647 
5648  /* Scan all rows for this table */
5649  do
5650  {
5651  char *attname;
5652  char *typename;
5653  char *attnotnull;
5654  char *attgenerated;
5655  char *attdefault;
5656  char *collname;
5657  char *collnamespace;
5658 
5659  /* If table has no columns, we'll see nulls here */
5660  if (PQgetisnull(res, i, 1))
5661  continue;
5662 
5663  attname = PQgetvalue(res, i, 1);
5664  typename = PQgetvalue(res, i, 2);
5665  attnotnull = PQgetvalue(res, i, 3);
5666  attdefault = PQgetisnull(res, i, 4) ? (char *) NULL :
5667  PQgetvalue(res, i, 4);
5668  attgenerated = PQgetisnull(res, i, 5) ? (char *) NULL :
5669  PQgetvalue(res, i, 5);
5670  collname = PQgetisnull(res, i, 6) ? (char *) NULL :
5671  PQgetvalue(res, i, 6);
5672  collnamespace = PQgetisnull(res, i, 7) ? (char *) NULL :
5673  PQgetvalue(res, i, 7);
5674 
5675  if (first_item)
5676  first_item = false;
5677  else
5678  appendStringInfoString(&buf, ",\n");
5679 
5680  /* Print column name and type */
5681  appendStringInfo(&buf, " %s %s",
5683  typename);
5684 
5685  /*
5686  * Add column_name option so that renaming the foreign table's
5687  * column doesn't break the association to the underlying
5688  * column.
5689  */
5690  appendStringInfoString(&buf, " OPTIONS (column_name ");
5692  appendStringInfoChar(&buf, ')');
5693 
5694  /* Add COLLATE if needed */
5695  if (import_collate && collname != NULL && collnamespace != NULL)
5696  appendStringInfo(&buf, " COLLATE %s.%s",
5697  quote_identifier(collnamespace),
5698  quote_identifier(collname));
5699 
5700  /* Add DEFAULT if needed */
5701  if (import_default && attdefault != NULL &&
5702  (!attgenerated || !attgenerated[0]))
5703  appendStringInfo(&buf, " DEFAULT %s", attdefault);
5704 
5705  /* Add GENERATED if needed */
5706  if (import_generated && attgenerated != NULL &&
5707  attgenerated[0] == ATTRIBUTE_GENERATED_STORED)
5708  {
5709  Assert(attdefault != NULL);
5711  " GENERATED ALWAYS AS (%s) STORED",
5712  attdefault);
5713  }
5714 
5715  /* Add NOT NULL if needed */
5716  if (import_not_null && attnotnull[0] == 't')
5717  appendStringInfoString(&buf, " NOT NULL");
5718  }
5719  while (++i < numrows &&
5720  strcmp(PQgetvalue(res, i, 0), tablename) == 0);
5721 
5722  /*
5723  * Add server name and table-level options. We specify remote
5724  * schema and table name as options (the latter to ensure that
5725  * renaming the foreign table doesn't break the association).
5726  */
5727  appendStringInfo(&buf, "\n) SERVER %s\nOPTIONS (",
5728  quote_identifier(server->servername));
5729 
5730  appendStringInfoString(&buf, "schema_name ");
5731  deparseStringLiteral(&buf, stmt->remote_schema);
5732  appendStringInfoString(&buf, ", table_name ");
5733  deparseStringLiteral(&buf, tablename);
5734 
5735  appendStringInfoString(&buf, ");");
5736 
5737  commands = lappend(commands, pstrdup(buf.data));
5738  }
5739  }
5740  PG_FINALLY();
5741  {
5742  PQclear(res);
5743  }
5744  PG_END_TRY();
5745 
5747 
5748  return commands;
5749 }
5750 
5751 /*
5752  * Check if reltarget is safe enough to push down semi-join. Reltarget is not
5753  * safe, if it contains references to inner rel relids, which do not belong to
5754  * outer rel.
5755  */
5756 static bool
5758 {
5759  List *vars;
5760  ListCell *lc;
5761  bool ok = true;
5762 
5763  Assert(joinrel->reltarget);
5764 
5766 
5767  foreach(lc, vars)
5768  {
5769  Var *var = (Var *) lfirst(lc);
5770 
5771  if (!IsA(var, Var))
5772  continue;
5773 
5774  if (bms_is_member(var->varno, innerrel->relids) &&
5775  !bms_is_member(var->varno, outerrel->relids))
5776  {
5777  /*
5778  * The planner can create semi-join, which refers to inner rel
5779  * vars in its target list. However, we deparse semi-join as an
5780  * exists() subquery, so can't handle references to inner rel in
5781  * the target list.
5782  */
5783  ok = false;
5784  break;
5785  }
5786  }
5787  return ok;
5788 }
5789 
5790 /*
5791  * Assess whether the join between inner and outer relations can be pushed down
5792  * to the foreign server. As a side effect, save information we obtain in this
5793  * function to PgFdwRelationInfo passed in.
5794  */
5795 static bool
5797  RelOptInfo *outerrel, RelOptInfo *innerrel,
5798  JoinPathExtraData *extra)
5799 {
5800  PgFdwRelationInfo *fpinfo;
5801  PgFdwRelationInfo *fpinfo_o;
5802  PgFdwRelationInfo *fpinfo_i;
5803  ListCell *lc;
5804  List *joinclauses;
5805 
5806  /*
5807  * We support pushing down INNER, LEFT, RIGHT, FULL OUTER and SEMI joins.
5808  * Constructing queries representing ANTI joins is hard, hence not
5809  * considered right now.
5810  */
5811  if (jointype != JOIN_INNER && jointype != JOIN_LEFT &&
5812  jointype != JOIN_RIGHT && jointype != JOIN_FULL &&
5813  jointype != JOIN_SEMI)
5814  return false;
5815 
5816  /*
5817  * We can't push down semi-join if its reltarget is not safe
5818  */
5819  if ((jointype == JOIN_SEMI) && !semijoin_target_ok(root, joinrel, outerrel, innerrel))
5820  return false;
5821 
5822  /*
5823  * If either of the joining relations is marked as unsafe to pushdown, the
5824  * join can not be pushed down.
5825  */
5826  fpinfo = (PgFdwRelationInfo *) joinrel->fdw_private;
5827  fpinfo_o = (PgFdwRelationInfo *) outerrel->fdw_private;
5828  fpinfo_i = (PgFdwRelationInfo *) innerrel->fdw_private;
5829  if (!fpinfo_o || !fpinfo_o->pushdown_safe ||
5830  !fpinfo_i || !fpinfo_i->pushdown_safe)
5831  return false;
5832 
5833  /*
5834  * If joining relations have local conditions, those conditions are
5835  * required to be applied before joining the relations. Hence the join can
5836  * not be pushed down.
5837  */
5838  if (fpinfo_o->local_conds || fpinfo_i->local_conds)
5839  return false;
5840 
5841  /*
5842  * Merge FDW options. We might be tempted to do this after we have deemed
5843  * the foreign join to be OK. But we must do this beforehand so that we
5844  * know which quals can be evaluated on the foreign server, which might
5845  * depend on shippable_extensions.
5846  */
5847  fpinfo->server = fpinfo_o->server;
5848  merge_fdw_options(fpinfo, fpinfo_o, fpinfo_i);
5849 
5850  /*
5851  * Separate restrict list into join quals and pushed-down (other) quals.
5852  *
5853  * Join quals belonging to an outer join must all be shippable, else we
5854  * cannot execute the join remotely. Add such quals to 'joinclauses'.
5855  *
5856  * Add other quals to fpinfo->remote_conds if they are shippable, else to
5857  * fpinfo->local_conds. In an inner join it's okay to execute conditions
5858  * either locally or remotely; the same is true for pushed-down conditions
5859  * at an outer join.
5860  *
5861  * Note we might return failure after having already scribbled on
5862  * fpinfo->remote_conds and fpinfo->local_conds. That's okay because we
5863  * won't consult those lists again if we deem the join unshippable.
5864  */
5865  joinclauses = NIL;
5866  foreach(lc, extra->restrictlist)
5867  {
5868  RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
5869  bool is_remote_clause = is_foreign_expr(root, joinrel,
5870  rinfo->clause);
5871 
5872  if (IS_OUTER_JOIN(jointype) &&
5873  !RINFO_IS_PUSHED_DOWN(rinfo, joinrel->relids))
5874  {
5875  if (!is_remote_clause)
5876  return false;
5877  joinclauses = lappend(joinclauses, rinfo);
5878  }
5879  else
5880  {
5881  if (is_remote_clause)
5882  fpinfo->remote_conds = lappend(fpinfo->remote_conds, rinfo);
5883  else
5884  fpinfo->local_conds = lappend(fpinfo->local_conds, rinfo);
5885  }
5886  }
5887 
5888  /*
5889  * deparseExplicitTargetList() isn't smart enough to handle anything other
5890  * than a Var. In particular, if there's some PlaceHolderVar that would
5891  * need to be evaluated within this join tree (because there's an upper
5892  * reference to a quantity that may go to NULL as a result of an outer
5893  * join), then we can't try to push the join down because we'll fail when
5894  * we get to deparseExplicitTargetList(). However, a PlaceHolderVar that
5895  * needs to be evaluated *at the top* of this join tree is OK, because we
5896  * can do that locally after fetching the results from the remote side.
5897  */
5898  foreach(lc, root->placeholder_list)
5899  {
5900  PlaceHolderInfo *phinfo = lfirst(lc);
5901  Relids relids;
5902 
5903  /* PlaceHolderInfo refers to parent relids, not child relids. */
5904  relids = IS_OTHER_REL(joinrel) ?
5905  joinrel->top_parent_relids : joinrel->relids;
5906 
5907  if (bms_is_subset(phinfo->ph_eval_at, relids) &&
5908  bms_nonempty_difference(relids, phinfo->ph_eval_at))
5909  return false;
5910  }
5911 
5912  /* Save the join clauses, for later use. */
5913  fpinfo->joinclauses = joinclauses;
5914 
5915  fpinfo->outerrel = outerrel;
5916  fpinfo->innerrel = innerrel;
5917  fpinfo->jointype = jointype;
5918 
5919  /*
5920  * By default, both the input relations are not required to be deparsed as
5921  * subqueries, but there might be some relations covered by the input
5922  * relations that are required to be deparsed as subqueries, so save the
5923  * relids of those relations for later use by the deparser.
5924  */
5925  fpinfo->make_outerrel_subquery = false;
5926  fpinfo->make_innerrel_subquery = false;
5927  Assert(bms_is_subset(fpinfo_o->lower_subquery_rels, outerrel->relids));
5928  Assert(bms_is_subset(fpinfo_i->lower_subquery_rels, innerrel->relids));
5930  fpinfo_i->lower_subquery_rels);
5932  fpinfo_i->hidden_subquery_rels);
5933 
5934  /*
5935  * Pull the other remote conditions from the joining relations into join
5936  * clauses or other remote clauses (remote_conds) of this relation
5937  * wherever possible. This avoids building subqueries at every join step.
5938  *
5939  * For an inner join, clauses from both the relations are added to the
5940  * other remote clauses. For LEFT and RIGHT OUTER join, the clauses from
5941  * the outer side are added to remote_conds since those can be evaluated
5942  * after the join is evaluated. The clauses from inner side are added to
5943  * the joinclauses, since they need to be evaluated while constructing the
5944  * join.
5945  *
5946  * For SEMI-JOIN clauses from inner relation can not be added to
5947  * remote_conds, but should be treated as join clauses (as they are
5948  * deparsed to EXISTS subquery, where inner relation can be referred). A
5949  * list of relation ids, which can't be referred to from higher levels, is
5950  * preserved as a hidden_subquery_rels list.
5951  *
5952  * For a FULL OUTER JOIN, the other clauses from either relation can not
5953  * be added to the joinclauses or remote_conds, since each relation acts
5954  * as an outer relation for the other.
5955  *
5956  * The joining sides can not have local conditions, thus no need to test
5957  * shippability of the clauses being pulled up.
5958  */
5959  switch (jointype)
5960  {
5961  case JOIN_INNER:
5962  fpinfo->remote_conds = list_concat(fpinfo->remote_conds,
5963  fpinfo_i->remote_conds);
5964  fpinfo->remote_conds = list_concat(fpinfo->remote_conds,
5965  fpinfo_o->remote_conds);
5966  break;
5967 
5968  case JOIN_LEFT:
5969  fpinfo->joinclauses = list_concat(fpinfo->joinclauses,
5970  fpinfo_i->remote_conds);
5971  fpinfo->remote_conds = list_concat(fpinfo->remote_conds,
5972  fpinfo_o->remote_conds);
5973  break;
5974 
5975  case JOIN_RIGHT:
5976  fpinfo->joinclauses = list_concat(fpinfo->joinclauses,
5977  fpinfo_o->remote_conds);
5978  fpinfo->remote_conds = list_concat(fpinfo->remote_conds,
5979  fpinfo_i->remote_conds);
5980  break;
5981 
5982  case JOIN_SEMI:
5983  fpinfo->joinclauses = list_concat(fpinfo->joinclauses,
5984  fpinfo_i->remote_conds);
5985  fpinfo->joinclauses = list_concat(fpinfo->joinclauses,
5986  fpinfo->remote_conds);
5987  fpinfo->remote_conds = list_copy(fpinfo_o->remote_conds);
5989  innerrel->relids);
5990  break;
5991 
5992  case JOIN_FULL:
5993 
5994  /*
5995  * In this case, if any of the input relations has conditions, we
5996  * need to deparse that relation as a subquery so that the
5997  * conditions can be evaluated before the join. Remember it in
5998  * the fpinfo of this relation so that the deparser can take
5999  * appropriate action. Also, save the relids of base relations
6000  * covered by that relation for later use by the deparser.
6001  */
6002  if (fpinfo_o->remote_conds)
6003  {
6004  fpinfo->make_outerrel_subquery = true;
6005  fpinfo->lower_subquery_rels =
6007  outerrel->relids);
6008  }
6009  if (fpinfo_i->remote_conds)
6010  {
6011  fpinfo->make_innerrel_subquery = true;
6012  fpinfo->lower_subquery_rels =
6014  innerrel->relids);
6015  }
6016  break;
6017 
6018  default:
6019  /* Should not happen, we have just checked this above */
6020  elog(ERROR, "unsupported join type %d", jointype);
6021  }
6022 
6023  /*
6024  * For an inner join, all restrictions can be treated alike. Treating the
6025  * pushed down conditions as join conditions allows a top level full outer
6026  * join to be deparsed without requiring subqueries.
6027  */
6028  if (jointype == JOIN_INNER)
6029  {
6030  Assert(!fpinfo->joinclauses);
6031  fpinfo->joinclauses = fpinfo->remote_conds;
6032  fpinfo->remote_conds = NIL;
6033  }
6034  else if (jointype == JOIN_LEFT || jointype == JOIN_RIGHT || jointype == JOIN_FULL)
6035  {
6036  /*
6037  * Conditions, generated from semi-joins, should be evaluated before
6038  * LEFT/RIGHT/FULL join.
6039  */
6040  if (!bms_is_empty(fpinfo_o->hidden_subquery_rels))
6041  {
6042  fpinfo->make_outerrel_subquery = true;
6043  fpinfo->lower_subquery_rels = bms_add_members(fpinfo->lower_subquery_rels, outerrel->relids);
6044  }
6045 
6046  if (!bms_is_empty(fpinfo_i->hidden_subquery_rels))
6047  {
6048  fpinfo->make_innerrel_subquery = true;
6049  fpinfo->lower_subquery_rels = bms_add_members(fpinfo->lower_subquery_rels, innerrel->relids);
6050  }
6051  }
6052 
6053  /* Mark that this join can be pushed down safely */
6054  fpinfo->pushdown_safe = true;
6055 
6056  /* Get user mapping */
6057  if (fpinfo->use_remote_estimate)
6058  {
6059  if (fpinfo_o->use_remote_estimate)
6060  fpinfo->user = fpinfo_o->user;
6061  else
6062  fpinfo->user = fpinfo_i->user;
6063  }
6064  else
6065  fpinfo->user = NULL;
6066 
6067  /*
6068  * Set # of retrieved rows and cached relation costs to some negative
6069  * value, so that we can detect when they are set to some sensible values,
6070  * during one (usually the first) of the calls to estimate_path_cost_size.
6071  */
6072  fpinfo->retrieved_rows = -1;
6073  fpinfo->rel_startup_cost = -1;
6074  fpinfo->rel_total_cost = -1;
6075 
6076  /*
6077  * Set the string describing this join relation to be used in EXPLAIN
6078  * output of corresponding ForeignScan. Note that the decoration we add
6079  * to the base relation names mustn't include any digits, or it'll confuse
6080  * postgresExplainForeignScan.
6081  */
6082  fpinfo->relation_name = psprintf("(%s) %s JOIN (%s)",
6083  fpinfo_o->relation_name,
6084  get_jointype_name(fpinfo->jointype),
6085  fpinfo_i->relation_name);
6086 
6087  /*
6088  * Set the relation index. This is defined as the position of this
6089  * joinrel in the join_rel_list list plus the length of the rtable list.
6090  * Note that since this joinrel is at the end of the join_rel_list list
6091  * when we are called, we can get the position by list_length.
6092  */
6093  Assert(fpinfo->relation_index == 0); /* shouldn't be set yet */
6094  fpinfo->relation_index =
6095  list_length(root->parse->rtable) + list_length(root->join_rel_list);
6096 
6097  return true;
6098 }
6099 
6100 static void
6102  Path *epq_path, List *restrictlist)
6103 {
6104  List *useful_pathkeys_list = NIL; /* List of all pathkeys */
6105  ListCell *lc;
6106 
6107  useful_pathkeys_list = get_useful_pathkeys_for_relation(root, rel);
6108 
6109  /*
6110  * Before creating sorted paths, arrange for the passed-in EPQ path, if
6111  * any, to return columns needed by the parent ForeignScan node so that
6112  * they will propagate up through Sort nodes injected below, if necessary.
6113  */
6114  if (epq_path != NULL && useful_pathkeys_list != NIL)
6115  {
6116  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) rel->fdw_private;
6117  PathTarget *target = copy_pathtarget(epq_path->pathtarget);
6118 
6119  /* Include columns required for evaluating PHVs in the tlist. */
6121  pull_var_clause((Node *) target->exprs,
6123 
6124  /* Include columns required for evaluating the local conditions. */
6125  foreach(lc, fpinfo->local_conds)
6126  {
6127  RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
6128 
6130  pull_var_clause((Node *) rinfo->clause,
6132  }
6133 
6134  /*
6135  * If we have added any new columns, adjust the tlist of the EPQ path.
6136  *
6137  * Note: the plan created using this path will only be used to execute
6138  * EPQ checks, where accuracy of the plan cost and width estimates
6139  * would not be important, so we do not do set_pathtarget_cost_width()
6140  * for the new pathtarget here. See also postgresGetForeignPlan().
6141  */
6142  if (list_length(target->exprs) > list_length(epq_path->pathtarget->exprs))
6143  {
6144  /* The EPQ path is a join path, so it is projection-capable. */
6146 
6147  /*
6148  * Use create_projection_path() here, so as to avoid modifying it
6149  * in place.
6150  */
6151  epq_path = (Path *) create_projection_path(root,
6152  rel,
6153  epq_path,
6154  target);
6155  }
6156  }
6157 
6158  /* Create one path for each set of pathkeys we found above. */
6159  foreach(lc, useful_pathkeys_list)
6160  {
6161  double rows;
6162  int width;
6163  int disabled_nodes;
6164  Cost startup_cost;
6165  Cost total_cost;
6166  List *useful_pathkeys = lfirst(lc);
6167  Path *sorted_epq_path;
6168 
6169  estimate_path_cost_size(root, rel, NIL, useful_pathkeys, NULL,
6170  &rows, &width, &disabled_nodes,
6171  &startup_cost, &total_cost);
6172 
6173  /*
6174  * The EPQ path must be at least as well sorted as the path itself, in
6175  * case it gets used as input to a mergejoin.
6176  */
6177  sorted_epq_path = epq_path;
6178  if (sorted_epq_path != NULL &&
6179  !pathkeys_contained_in(useful_pathkeys,
6180  sorted_epq_path->pathkeys))
6181  sorted_epq_path = (Path *)
6183  rel,
6184  sorted_epq_path,
6185  useful_pathkeys,
6186  -1.0);
6187 
6188  if (IS_SIMPLE_REL(rel))
6189  add_path(rel, (Path *)
6191  NULL,
6192  rows,
6193  disabled_nodes,
6194  startup_cost,
6195  total_cost,
6196  useful_pathkeys,
6197  rel->lateral_relids,
6198  sorted_epq_path,
6199  NIL, /* no fdw_restrictinfo
6200  * list */
6201  NIL));
6202  else
6203  add_path(rel, (Path *)
6205  NULL,
6206  rows,
6207  disabled_nodes,
6208  startup_cost,
6209  total_cost,
6210  useful_pathkeys,
6211  rel->lateral_relids,
6212  sorted_epq_path,
6213  restrictlist,
6214  NIL));
6215  }
6216 }
6217 
6218 /*
6219  * Parse options from foreign server and apply them to fpinfo.
6220  *
6221  * New options might also require tweaking merge_fdw_options().
6222  */
6223 static void
6225 {
6226  ListCell *lc;
6227 
6228  foreach(lc, fpinfo->server->options)
6229  {
6230  DefElem *def = (DefElem *) lfirst(lc);
6231 
6232  if (strcmp(def->defname, "use_remote_estimate") == 0)
6233  fpinfo->use_remote_estimate = defGetBoolean(def);
6234  else if (strcmp(def->defname, "fdw_startup_cost") == 0)
6235  (void) parse_real(defGetString(def), &fpinfo->fdw_startup_cost, 0,
6236  NULL);
6237  else if (strcmp(def->defname, "fdw_tuple_cost") == 0)
6238  (void) parse_real(defGetString(def), &fpinfo->fdw_tuple_cost, 0,
6239  NULL);
6240  else if (strcmp(def->defname, "extensions") == 0)
6241  fpinfo->shippable_extensions =
6242  ExtractExtensionList(defGetString(def), false);
6243  else if (strcmp(def->defname, "fetch_size") == 0)
6244  (void) parse_int(defGetString(def), &fpinfo->fetch_size, 0, NULL);
6245  else if (strcmp(def->defname, "async_capable") == 0)
6246  fpinfo->async_capable = defGetBoolean(def);
6247  }
6248 }
6249 
6250 /*
6251  * Parse options from foreign table and apply them to fpinfo.
6252  *
6253  * New options might also require tweaking merge_fdw_options().
6254  */
6255 static void
6257 {
6258  ListCell *lc;
6259 
6260  foreach(lc, fpinfo->table->options)
6261  {
6262  DefElem *def = (DefElem *) lfirst(lc);
6263 
6264  if (strcmp(def->defname, "use_remote_estimate") == 0)
6265  fpinfo->use_remote_estimate = defGetBoolean(def);
6266  else if (strcmp(def->defname, "fetch_size") == 0)
6267  (void) parse_int(defGetString(def), &fpinfo->fetch_size, 0, NULL);
6268  else if (strcmp(def->defname, "async_capable") == 0)
6269  fpinfo->async_capable = defGetBoolean(def);
6270  }
6271 }
6272 
6273 /*
6274  * Merge FDW options from input relations into a new set of options for a join
6275  * or an upper rel.
6276  *
6277  * For a join relation, FDW-specific information about the inner and outer
6278  * relations is provided using fpinfo_i and fpinfo_o. For an upper relation,
6279  * fpinfo_o provides the information for the input relation; fpinfo_i is
6280  * expected to NULL.
6281  */
6282 static void
6284  const PgFdwRelationInfo *fpinfo_o,
6285  const PgFdwRelationInfo *fpinfo_i)
6286 {
6287  /* We must always have fpinfo_o. */
6288  Assert(fpinfo_o);
6289 
6290  /* fpinfo_i may be NULL, but if present the servers must both match. */
6291  Assert(!fpinfo_i ||
6292  fpinfo_i->server->serverid == fpinfo_o->server->serverid);
6293 
6294  /*
6295  * Copy the server specific FDW options. (For a join, both relations come
6296  * from the same server, so the server options should have the same value
6297  * for both relations.)
6298  */
6299  fpinfo->fdw_startup_cost = fpinfo_o->fdw_startup_cost;
6300  fpinfo->fdw_tuple_cost = fpinfo_o->fdw_tuple_cost;
6301  fpinfo->shippable_extensions = fpinfo_o->shippable_extensions;
6302  fpinfo->use_remote_estimate = fpinfo_o->use_remote_estimate;
6303  fpinfo->fetch_size = fpinfo_o->fetch_size;
6304  fpinfo->async_capable = fpinfo_o->async_capable;
6305 
6306  /* Merge the table level options from either side of the join. */
6307  if (fpinfo_i)
6308  {
6309  /*
6310  * We'll prefer to use remote estimates for this join if any table
6311  * from either side of the join is using remote estimates. This is
6312  * most likely going to be preferred since they're already willing to
6313  * pay the price of a round trip to get the remote EXPLAIN. In any
6314  * case it's not entirely clear how we might otherwise handle this
6315  * best.
6316  */
6317  fpinfo->use_remote_estimate = fpinfo_o->use_remote_estimate ||
6318  fpinfo_i->use_remote_estimate;
6319 
6320  /*
6321  * Set fetch size to maximum of the joining sides, since we are
6322  * expecting the rows returned by the join to be proportional to the
6323  * relation sizes.
6324  */
6325  fpinfo->fetch_size = Max(fpinfo_o->fetch_size, fpinfo_i->fetch_size);
6326 
6327  /*
6328  * We'll prefer to consider this join async-capable if any table from
6329  * either side of the join is considered async-capable. This would be
6330  * reasonable because in that case the foreign server would have its
6331  * own resources to scan that table asynchronously, and the join could
6332  * also be computed asynchronously using the resources.
6333  */
6334  fpinfo->async_capable = fpinfo_o->async_capable ||
6335  fpinfo_i->async_capable;
6336  }
6337 }
6338 
6339 /*
6340  * postgresGetForeignJoinPaths
6341  * Add possible ForeignPath to joinrel, if join is safe to push down.
6342  */
6343 static void
6345  RelOptInfo *joinrel,
6346  RelOptInfo *outerrel,
6347  RelOptInfo *innerrel,
6348  JoinType jointype,
6349  JoinPathExtraData *extra)
6350 {
6351  PgFdwRelationInfo *fpinfo;
6352  ForeignPath *joinpath;
6353  double rows;
6354  int width;
6355  int disabled_nodes;
6356  Cost startup_cost;
6357  Cost total_cost;
6358  Path *epq_path; /* Path to create plan to be executed when
6359  * EvalPlanQual gets triggered. */
6360 
6361  /*
6362  * Skip if this join combination has been considered already.
6363  */
6364  if (joinrel->fdw_private)
6365  return;
6366 
6367  /*
6368  * This code does not work for joins with lateral references, since those
6369  * must have parameterized paths, which we don't generate yet.
6370  */
6371  if (!bms_is_empty(joinrel->lateral_relids))
6372  return;
6373 
6374  /*
6375  * Create unfinished PgFdwRelationInfo entry which is used to indicate
6376  * that the join relation is already considered, so that we won't waste
6377  * time in judging safety of join pushdown and adding the same paths again
6378  * if found safe. Once we know that this join can be pushed down, we fill
6379  * the entry.
6380  */
6381  fpinfo = (PgFdwRelationInfo *) palloc0(sizeof(PgFdwRelationInfo));
6382  fpinfo->pushdown_safe = false;
6383  joinrel->fdw_private = fpinfo;
6384  /* attrs_used is only for base relations. */
6385  fpinfo->attrs_used = NULL;
6386 
6387  /*
6388  * If there is a possibility that EvalPlanQual will be executed, we need
6389  * to be able to reconstruct the row using scans of the base relations.
6390  * GetExistingLocalJoinPath will find a suitable path for this purpose in
6391  * the path list of the joinrel, if one exists. We must be careful to
6392  * call it before adding any ForeignPath, since the ForeignPath might
6393  * dominate the only suitable local path available. We also do it before
6394  * calling foreign_join_ok(), since that function updates fpinfo and marks
6395  * it as pushable if the join is found to be pushable.
6396  */
6397  if (root->parse->commandType == CMD_DELETE ||
6398  root->parse->commandType == CMD_UPDATE ||
6399  root->rowMarks)
6400  {
6401  epq_path = GetExistingLocalJoinPath(joinrel);
6402  if (!epq_path)
6403  {
6404  elog(DEBUG3, "could not push down foreign join because a local path suitable for EPQ checks was not found");
6405  return;
6406  }
6407  }
6408  else
6409  epq_path = NULL;
6410 
6411  if (!foreign_join_ok(root, joinrel, jointype, outerrel, innerrel, extra))
6412  {
6413  /* Free path required for EPQ if we copied one; we don't need it now */
6414  if (epq_path)
6415  pfree(epq_path);
6416  return;
6417  }
6418 
6419  /*
6420  * Compute the selectivity and cost of the local_conds, so we don't have
6421  * to do it over again for each path. The best we can do for these
6422  * conditions is to estimate selectivity on the basis of local statistics.
6423  * The local conditions are applied after the join has been computed on
6424  * the remote side like quals in WHERE clause, so pass jointype as
6425  * JOIN_INNER.
6426  */
6428  fpinfo->local_conds,
6429  0,
6430  JOIN_INNER,
6431  NULL);
6432  cost_qual_eval(&fpinfo->local_conds_cost, fpinfo->local_conds, root);
6433 
6434  /*
6435  * If we are going to estimate costs locally, estimate the join clause
6436  * selectivity here while we have special join info.
6437  */
6438  if (!fpinfo->use_remote_estimate)
6440  0, fpinfo->jointype,
6441  extra->sjinfo);
6442 
6443  /* Estimate costs for bare join relation */
6444  estimate_path_cost_size(root, joinrel, NIL, NIL, NULL,
6445  &rows, &width, &disabled_nodes,
6446  &startup_cost, &total_cost);
6447  /* Now update this information in the joinrel */
6448  joinrel->rows = rows;
6449  joinrel->reltarget->width = width;
6450  fpinfo->rows = rows;
6451  fpinfo->width = width;
6452  fpinfo->disabled_nodes = disabled_nodes;
6453  fpinfo->startup_cost = startup_cost;
6454  fpinfo->total_cost = total_cost;
6455 
6456  /*
6457  * Create a new join path and add it to the joinrel which represents a
6458  * join between foreign tables.
6459  */
6460  joinpath = create_foreign_join_path(root,
6461  joinrel,
6462  NULL, /* default pathtarget */
6463  rows,
6464  disabled_nodes,
6465  startup_cost,
6466  total_cost,
6467  NIL, /* no pathkeys */
6468  joinrel->lateral_relids,
6469  epq_path,
6470  extra->restrictlist,
6471  NIL); /* no fdw_private */
6472 
6473  /* Add generated path into joinrel by add_path(). */
6474  add_path(joinrel, (Path *) joinpath);
6475 
6476  /* Consider pathkeys for the join relation */
6477  add_paths_with_pathkeys_for_rel(root, joinrel, epq_path,
6478  extra->restrictlist);
6479 
6480  /* XXX Consider parameterized paths for the join relation */
6481 }
6482 
6483 /*
6484  * Assess whether the aggregation, grouping and having operations can be pushed
6485  * down to the foreign server. As a side effect, save information we obtain in
6486  * this function to PgFdwRelationInfo of the input relation.
6487  */
6488 static bool
6490  Node *havingQual)
6491 {
6492  Query *query = root->parse;
6493  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) grouped_rel->fdw_private;
6494  PathTarget *grouping_target = grouped_rel->reltarget;
6495  PgFdwRelationInfo *ofpinfo;
6496  ListCell *lc;
6497  int i;
6498  List *tlist = NIL;
6499 
6500  /* We currently don't support pushing Grouping Sets. */
6501  if (query->groupingSets)
6502  return false;
6503 
6504  /* Get the fpinfo of the underlying scan relation. */
6505  ofpinfo = (PgFdwRelationInfo *) fpinfo->outerrel->fdw_private;
6506 
6507  /*
6508  * If underlying scan relation has any local conditions, those conditions
6509  * are required to be applied before performing aggregation. Hence the
6510  * aggregate cannot be pushed down.
6511  */
6512  if (ofpinfo->local_conds)
6513  return false;
6514 
6515  /*
6516  * Examine grouping expressions, as well as other expressions we'd need to
6517  * compute, and check whether they are safe to push down to the foreign
6518  * server. All GROUP BY expressions will be part of the grouping target
6519  * and thus there is no need to search for them separately. Add grouping
6520  * expressions into target list which will be passed to foreign server.
6521  *
6522  * A tricky fine point is that we must not put any expression into the
6523  * target list that is just a foreign param (that is, something that
6524  * deparse.c would conclude has to be sent to the foreign server). If we
6525  * do, the expression will also appear in the fdw_exprs list of the plan
6526  * node, and setrefs.c will get confused and decide that the fdw_exprs
6527  * entry is actually a reference to the fdw_scan_tlist entry, resulting in
6528  * a broken plan. Somewhat oddly, it's OK if the expression contains such
6529  * a node, as long as it's not at top level; then no match is possible.
6530  */
6531  i = 0;
6532  foreach(lc, grouping_target->exprs)
6533  {
6534  Expr *expr = (Expr *) lfirst(lc);
6535  Index sgref = get_pathtarget_sortgroupref(grouping_target, i);
6536  ListCell *l;
6537 
6538  /*
6539  * Check whether this expression is part of GROUP BY clause. Note we
6540  * check the whole GROUP BY clause not just processed_groupClause,
6541  * because we will ship all of it, cf. appendGroupByClause.
6542  */
6543  if (sgref && get_sortgroupref_clause_noerr(sgref, query->groupClause))
6544  {
6545  TargetEntry *tle;
6546 
6547  /*
6548  * If any GROUP BY expression is not shippable, then we cannot
6549  * push down aggregation to the foreign server.
6550  */
6551  if (!is_foreign_expr(root, grouped_rel, expr))
6552  return false;
6553 
6554  /*
6555  * If it would be a foreign param, we can't put it into the tlist,
6556  * so we have to fail.
6557  */
6558  if (is_foreign_param(root, grouped_rel, expr))
6559  return false;
6560 
6561  /*
6562  * Pushable, so add to tlist. We need to create a TLE for this
6563  * expression and apply the sortgroupref to it. We cannot use
6564  * add_to_flat_tlist() here because that avoids making duplicate
6565  * entries in the tlist. If there are duplicate entries with
6566  * distinct sortgrouprefs, we have to duplicate that situation in
6567  * the output tlist.
6568  */
6569  tle = makeTargetEntry(expr, list_length(tlist) + 1, NULL, false);
6570  tle->ressortgroupref = sgref;
6571  tlist = lappend(tlist, tle);
6572  }
6573  else
6574  {
6575  /*
6576  * Non-grouping expression we need to compute. Can we ship it
6577  * as-is to the foreign server?
6578  */
6579  if (is_foreign_expr(root, grouped_rel, expr) &&
6580  !is_foreign_param(root, grouped_rel, expr))
6581  {
6582  /* Yes, so add to tlist as-is; OK to suppress duplicates */
6583  tlist = add_to_flat_tlist(tlist, list_make1(expr));
6584  }
6585  else
6586  {
6587  /* Not pushable as a whole; extract its Vars and aggregates */
6588  List *aggvars;
6589 
6590  aggvars = pull_var_clause((Node *) expr,
6592 
6593  /*
6594  * If any aggregate expression is not shippable, then we
6595  * cannot push down aggregation to the foreign server. (We
6596  * don't have to check is_foreign_param, since that certainly
6597  * won't return true for any such expression.)
6598  */
6599  if (!is_foreign_expr(root, grouped_rel, (Expr *) aggvars))
6600  return false;
6601 
6602  /*
6603  * Add aggregates, if any, into the targetlist. Plain Vars
6604  * outside an aggregate can be ignored, because they should be
6605  * either same as some GROUP BY column or part of some GROUP
6606  * BY expression. In either case, they are already part of
6607  * the targetlist and thus no need to add them again. In fact
6608  * including plain Vars in the tlist when they do not match a
6609  * GROUP BY column would cause the foreign server to complain
6610  * that the shipped query is invalid.
6611  */
6612  foreach(l, aggvars)
6613  {
6614  Expr *aggref = (Expr *) lfirst(l);
6615 
6616  if (IsA(aggref, Aggref))
6617  tlist = add_to_flat_tlist(tlist, list_make1(aggref));
6618  }
6619  }
6620  }
6621 
6622  i++;
6623  }
6624 
6625  /*
6626  * Classify the pushable and non-pushable HAVING clauses and save them in
6627  * remote_conds and local_conds of the grouped rel's fpinfo.
6628  */
6629  if (havingQual)
6630  {
6631  foreach(lc, (List *) havingQual)
6632  {
6633  Expr *expr = (Expr *) lfirst(lc);
6634  RestrictInfo *rinfo;
6635 
6636  /*
6637  * Currently, the core code doesn't wrap havingQuals in
6638  * RestrictInfos, so we must make our own.
6639  */
6640  Assert(!IsA(expr, RestrictInfo));
6641  rinfo = make_restrictinfo(root,
6642  expr,
6643  true,
6644  false,
6645  false,
6646  false,
6647  root->qual_security_level,
6648  grouped_rel->relids,
6649  NULL,
6650  NULL);
6651  if (is_foreign_expr(root, grouped_rel, expr))
6652  fpinfo->remote_conds = lappend(fpinfo->remote_conds, rinfo);
6653  else
6654  fpinfo->local_conds = lappend(fpinfo->local_conds, rinfo);
6655  }
6656  }
6657 
6658  /*
6659  * If there are any local conditions, pull Vars and aggregates from it and
6660  * check whether they are safe to pushdown or not.
6661  */
6662  if (fpinfo->local_conds)
6663  {
6664  List *aggvars = NIL;
6665 
6666  foreach(lc, fpinfo->local_conds)
6667  {
6668  RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
6669 
6670  aggvars = list_concat(aggvars,
6671  pull_var_clause((Node *) rinfo->clause,
6673  }
6674 
6675  foreach(lc, aggvars)
6676  {
6677  Expr *expr = (Expr *) lfirst(lc);
6678 
6679  /*
6680  * If aggregates within local conditions are not safe to push
6681  * down, then we cannot push down the query. Vars are already
6682  * part of GROUP BY clause which are checked above, so no need to
6683  * access them again here. Again, we need not check
6684  * is_foreign_param for a foreign aggregate.
6685  */
6686  if (IsA(expr, Aggref))
6687  {
6688  if (!is_foreign_expr(root, grouped_rel, expr))
6689  return false;
6690 
6691  tlist = add_to_flat_tlist(tlist, list_make1(expr));
6692  }
6693  }
6694  }
6695 
6696  /* Store generated targetlist */
6697  fpinfo->grouped_tlist = tlist;
6698 
6699  /* Safe to pushdown */
6700  fpinfo->pushdown_safe = true;
6701 
6702  /*
6703  * Set # of retrieved rows and cached relation costs to some negative
6704  * value, so that we can detect when they are set to some sensible values,
6705  * during one (usually the first) of the calls to estimate_path_cost_size.
6706  */
6707  fpinfo->retrieved_rows = -1;
6708  fpinfo->rel_startup_cost = -1;
6709  fpinfo->rel_total_cost = -1;
6710 
6711  /*
6712  * Set the string describing this grouped relation to be used in EXPLAIN
6713  * output of corresponding ForeignScan. Note that the decoration we add
6714  * to the base relation name mustn't include any digits, or it'll confuse
6715  * postgresExplainForeignScan.
6716  */
6717  fpinfo->relation_name = psprintf("Aggregate on (%s)",
6718  ofpinfo->relation_name);
6719 
6720  return true;
6721 }
6722 
6723 /*
6724  * postgresGetForeignUpperPaths
6725  * Add paths for post-join operations like aggregation, grouping etc. if
6726  * corresponding operations are safe to push down.
6727  */
6728 static void
6730  RelOptInfo *input_rel, RelOptInfo *output_rel,
6731  void *extra)
6732 {
6733  PgFdwRelationInfo *fpinfo;
6734 
6735  /*
6736  * If input rel is not safe to pushdown, then simply return as we cannot
6737  * perform any post-join operations on the foreign server.
6738  */
6739  if (!input_rel->fdw_private ||
6740  !((PgFdwRelationInfo *) input_rel->fdw_private)->pushdown_safe)
6741  return;
6742 
6743  /* Ignore stages we don't support; and skip any duplicate calls. */
6744  if ((stage != UPPERREL_GROUP_AGG &&
6745  stage != UPPERREL_ORDERED &&
6746  stage != UPPERREL_FINAL) ||
6747  output_rel->fdw_private)
6748  return;
6749 
6750  fpinfo = (PgFdwRelationInfo *) palloc0(sizeof(PgFdwRelationInfo));
6751  fpinfo->pushdown_safe = false;
6752  fpinfo->stage = stage;
6753  output_rel->fdw_private = fpinfo;
6754 
6755  switch (stage)
6756  {
6757  case UPPERREL_GROUP_AGG:
6758  add_foreign_grouping_paths(root, input_rel, output_rel,
6759  (GroupPathExtraData *) extra);
6760  break;
6761  case UPPERREL_ORDERED:
6762  add_foreign_ordered_paths(root, input_rel, output_rel);
6763  break;
6764  case UPPERREL_FINAL:
6765  add_foreign_final_paths(root, input_rel, output_rel,
6766  (FinalPathExtraData *) extra);
6767  break;
6768  default:
6769  elog(ERROR, "unexpected upper relation: %d", (int) stage);
6770  break;
6771  }
6772 }
6773 
6774 /*
6775  * add_foreign_grouping_paths
6776  * Add foreign path for grouping and/or aggregation.
6777  *
6778  * Given input_rel represents the underlying scan. The paths are added to the
6779  * given grouped_rel.
6780  */
6781 static void
6783  RelOptInfo *grouped_rel,
6784  GroupPathExtraData *extra)
6785 {
6786  Query *parse = root->parse;
6787  PgFdwRelationInfo *ifpinfo = input_rel->fdw_private;
6788  PgFdwRelationInfo *fpinfo = grouped_rel->fdw_private;
6789  ForeignPath *grouppath;
6790  double rows;
6791  int width;
6792  int disabled_nodes;
6793  Cost startup_cost;
6794  Cost total_cost;
6795 
6796  /* Nothing to be done, if there is no grouping or aggregation required. */
6797  if (!parse->groupClause && !parse->groupingSets && !parse->hasAggs &&
6798  !root->hasHavingQual)
6799  return;
6800 
6803 
6804  /* save the input_rel as outerrel in fpinfo */
6805  fpinfo->outerrel = input_rel;
6806 
6807  /*
6808  * Copy foreign table, foreign server, user mapping, FDW options etc.
6809  * details from the input relation's fpinfo.
6810  */
6811  fpinfo->table = ifpinfo->table;
6812  fpinfo->server = ifpinfo->server;
6813  fpinfo->user = ifpinfo->user;
6814  merge_fdw_options(fpinfo, ifpinfo, NULL);
6815 
6816  /*
6817  * Assess if it is safe to push down aggregation and grouping.
6818  *
6819  * Use HAVING qual from extra. In case of child partition, it will have
6820  * translated Vars.
6821  */
6822  if (!foreign_grouping_ok(root, grouped_rel, extra->havingQual))
6823  return;
6824 
6825  /*
6826  * Compute the selectivity and cost of the local_conds, so we don't have
6827  * to do it over again for each path. (Currently we create just a single
6828  * path here, but in future it would be possible that we build more paths
6829  * such as pre-sorted paths as in postgresGetForeignPaths and
6830  * postgresGetForeignJoinPaths.) The best we can do for these conditions
6831  * is to estimate selectivity on the basis of local statistics.
6832  */
6834  fpinfo->local_conds,
6835  0,
6836  JOIN_INNER,
6837  NULL);
6838 
6839  cost_qual_eval(&fpinfo->local_conds_cost, fpinfo->local_conds, root);
6840 
6841  /* Estimate the cost of push down */
6842  estimate_path_cost_size(root, grouped_rel, NIL, NIL, NULL,
6843  &rows, &width, &disabled_nodes,
6844  &startup_cost, &total_cost);
6845 
6846  /* Now update this information in the fpinfo */
6847  fpinfo->rows = rows;
6848  fpinfo->width = width;
6849  fpinfo->disabled_nodes = disabled_nodes;
6850  fpinfo->startup_cost = startup_cost;
6851  fpinfo->total_cost = total_cost;
6852 
6853  /* Create and add foreign path to the grouping relation. */
6854  grouppath = create_foreign_upper_path(root,
6855  grouped_rel,
6856  grouped_rel->reltarget,
6857  rows,
6858  disabled_nodes,
6859  startup_cost,
6860  total_cost,
6861  NIL, /* no pathkeys */
6862  NULL,
6863  NIL, /* no fdw_restrictinfo list */
6864  NIL); /* no fdw_private */
6865 
6866  /* Add generated path into grouped_rel by add_path(). */
6867  add_path(grouped_rel, (Path *) grouppath);
6868 }
6869 
6870 /*
6871  * add_foreign_ordered_paths
6872  * Add foreign paths for performing the final sort remotely.
6873  *
6874  * Given input_rel contains the source-data Paths. The paths are added to the
6875  * given ordered_rel.
6876  */
6877 static void
6879  RelOptInfo *ordered_rel)
6880 {
6881  Query *parse = root->parse;
6882  PgFdwRelationInfo *ifpinfo = input_rel->fdw_private;
6883  PgFdwRelationInfo *fpinfo = ordered_rel->fdw_private;
6884  PgFdwPathExtraData *fpextra;
6885  double rows;
6886  int width;
6887  int disabled_nodes;
6888  Cost startup_cost;
6889  Cost total_cost;
6890  List *fdw_private;
6891  ForeignPath *ordered_path;
6892  ListCell *lc;
6893 
6894  /* Shouldn't get here unless the query has ORDER BY */
6895  Assert(parse->sortClause);
6896 
6897  /* We don't support cases where there are any SRFs in the targetlist */
6898  if (parse->hasTargetSRFs)
6899  return;
6900 
6901  /* Save the input_rel as outerrel in fpinfo */
6902  fpinfo->outerrel = input_rel;
6903 
6904  /*
6905  * Copy foreign table, foreign server, user mapping, FDW options etc.
6906  * details from the input relation's fpinfo.
6907  */
6908  fpinfo->table = ifpinfo->table;
6909  fpinfo->server = ifpinfo->server;
6910  fpinfo->user = ifpinfo->user;
6911  merge_fdw_options(fpinfo, ifpinfo, NULL);
6912 
6913  /*
6914  * If the input_rel is a base or join relation, we would already have
6915  * considered pushing down the final sort to the remote server when
6916  * creating pre-sorted foreign paths for that relation, because the
6917  * query_pathkeys is set to the root->sort_pathkeys in that case (see
6918  * standard_qp_callback()).
6919  */
6920  if (input_rel->reloptkind == RELOPT_BASEREL ||
6921  input_rel->reloptkind == RELOPT_JOINREL)
6922  {
6923  Assert(root->query_pathkeys == root->sort_pathkeys);
6924 
6925  /* Safe to push down if the query_pathkeys is safe to push down */
6926  fpinfo->pushdown_safe = ifpinfo->qp_is_pushdown_safe;
6927 
6928  return;
6929  }
6930 
6931  /* The input_rel should be a grouping relation */
6932  Assert(input_rel->reloptkind == RELOPT_UPPER_REL &&
6933  ifpinfo->stage == UPPERREL_GROUP_AGG);
6934 
6935  /*
6936  * We try to create a path below by extending a simple foreign path for
6937  * the underlying grouping relation to perform the final sort remotely,
6938  * which is stored into the fdw_private list of the resulting path.
6939  */
6940 
6941  /* Assess if it is safe to push down the final sort */
6942  foreach(lc, root->sort_pathkeys)
6943  {
6944  PathKey *pathkey = (PathKey *) lfirst(lc);
6945  EquivalenceClass *pathkey_ec = pathkey->pk_eclass;
6946 
6947  /*
6948  * is_foreign_expr would detect volatile expressions as well, but
6949  * checking ec_has_volatile here saves some cycles.
6950  */
6951  if (pathkey_ec->ec_has_volatile)
6952  return;
6953 
6954  /*
6955  * Can't push down the sort if pathkey's opfamily is not shippable.
6956  */
6957  if (!is_shippable(pathkey->pk_opfamily, OperatorFamilyRelationId,
6958  fpinfo))
6959  return;
6960 
6961  /*
6962  * The EC must contain a shippable EM that is computed in input_rel's
6963  * reltarget, else we can't push down the sort.
6964  */
6966  pathkey_ec,
6967  input_rel) == NULL)
6968  return;
6969  }
6970 
6971  /* Safe to push down */
6972  fpinfo->pushdown_safe = true;
6973 
6974  /* Construct PgFdwPathExtraData */
6975  fpextra = (PgFdwPathExtraData *) palloc0(sizeof(PgFdwPathExtraData));
6976  fpextra->target = root->upper_targets[UPPERREL_ORDERED];
6977  fpextra->has_final_sort = true;
6978 
6979  /* Estimate the costs of performing the final sort remotely */
6980  estimate_path_cost_size(root, input_rel, NIL, root->sort_pathkeys, fpextra,
6981  &rows, &width, &disabled_nodes,
6982  &startup_cost, &total_cost);
6983 
6984  /*
6985  * Build the fdw_private list that will be used by postgresGetForeignPlan.
6986  * Items in the list must match order in enum FdwPathPrivateIndex.
6987  */
6988  fdw_private = list_make2(makeBoolean(true), makeBoolean(false));
6989 
6990  /* Create foreign ordering path */
6991  ordered_path = create_foreign_upper_path(root,
6992  input_rel,
6993  root->upper_targets[UPPERREL_ORDERED],
6994  rows,
6995  disabled_nodes,
6996  startup_cost,
6997  total_cost,
6998  root->sort_pathkeys,
6999  NULL, /* no extra plan */
7000  NIL, /* no fdw_restrictinfo
7001  * list */
7002  fdw_private);
7003 
7004  /* and add it to the ordered_rel */
7005  add_path(ordered_rel, (Path *) ordered_path);
7006 }
7007 
7008 /*
7009  * add_foreign_final_paths
7010  * Add foreign paths for performing the final processing remotely.
7011  *
7012  * Given input_rel contains the source-data Paths. The paths are added to the
7013  * given final_rel.
7014  */
7015 static void
7017  RelOptInfo *final_rel,
7018  FinalPathExtraData *extra)
7019 {
7020  Query *parse = root->parse;
7021  PgFdwRelationInfo *ifpinfo = (PgFdwRelationInfo *) input_rel->fdw_private;
7022  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) final_rel->fdw_private;
7023  bool has_final_sort = false;
7024  List *pathkeys = NIL;
7025  PgFdwPathExtraData *fpextra;
7026  bool save_use_remote_estimate = false;
7027  double rows;
7028  int width;
7029  int disabled_nodes;
7030  Cost startup_cost;
7031  Cost total_cost;
7032  List *fdw_private;
7033  ForeignPath *final_path;
7034 
7035  /*
7036  * Currently, we only support this for SELECT commands
7037  */
7038  if (parse->commandType != CMD_SELECT)
7039  return;
7040 
7041  /*
7042  * No work if there is no FOR UPDATE/SHARE clause and if there is no need
7043  * to add a LIMIT node
7044  */
7045  if (!parse->rowMarks && !extra->limit_needed)
7046  return;
7047 
7048  /* We don't support cases where there are any SRFs in the targetlist */
7049  if (parse->hasTargetSRFs)
7050  return;
7051 
7052  /* Save the input_rel as outerrel in fpinfo */
7053  fpinfo->outerrel = input_rel;
7054 
7055  /*
7056  * Copy foreign table, foreign server, user mapping, FDW options etc.
7057  * details from the input relation's fpinfo.
7058  */
7059  fpinfo->table = ifpinfo->table;
7060  fpinfo->server = ifpinfo->server;
7061  fpinfo->user = ifpinfo->user;
7062  merge_fdw_options(fpinfo, ifpinfo, NULL);
7063 
7064  /*
7065  * If there is no need to add a LIMIT node, there might be a ForeignPath
7066  * in the input_rel's pathlist that implements all behavior of the query.
7067  * Note: we would already have accounted for the query's FOR UPDATE/SHARE
7068  * (if any) before we get here.
7069  */
7070  if (!extra->limit_needed)
7071  {
7072  ListCell *lc;
7073 
7074  Assert(parse->rowMarks);
7075 
7076  /*
7077  * Grouping and aggregation are not supported with FOR UPDATE/SHARE,
7078  * so the input_rel should be a base, join, or ordered relation; and
7079  * if it's an ordered relation, its input relation should be a base or
7080  * join relation.
7081  */
7082  Assert(input_rel->reloptkind == RELOPT_BASEREL ||
7083  input_rel->reloptkind == RELOPT_JOINREL ||
7084  (input_rel->reloptkind == RELOPT_UPPER_REL &&
7085  ifpinfo->stage == UPPERREL_ORDERED &&
7086  (ifpinfo->outerrel->reloptkind == RELOPT_BASEREL ||
7087  ifpinfo->outerrel->reloptkind == RELOPT_JOINREL)));
7088 
7089  foreach(lc, input_rel->pathlist)
7090  {
7091  Path *path = (Path *) lfirst(lc);
7092 
7093  /*
7094  * apply_scanjoin_target_to_paths() uses create_projection_path()
7095  * to adjust each of its input paths if needed, whereas
7096  * create_ordered_paths() uses apply_projection_to_path() to do
7097  * that. So the former might have put a ProjectionPath on top of
7098  * the ForeignPath; look through ProjectionPath and see if the
7099  * path underneath it is ForeignPath.
7100  */
7101  if (IsA(path, ForeignPath) ||
7102  (IsA(path, ProjectionPath) &&
7103  IsA(((ProjectionPath *) path)->subpath, ForeignPath)))
7104  {
7105  /*
7106  * Create foreign final path; this gets rid of a
7107  * no-longer-needed outer plan (if any), which makes the
7108  * EXPLAIN output look cleaner
7109  */
7110  final_path = create_foreign_upper_path(root,
7111  path->parent,
7112  path->pathtarget,
7113  path->rows,
7114  path->disabled_nodes,
7115  path->startup_cost,
7116  path->total_cost,
7117  path->pathkeys,
7118  NULL, /* no extra plan */
7119  NIL, /* no fdw_restrictinfo
7120  * list */
7121  NIL); /* no fdw_private */
7122 
7123  /* and add it to the final_rel */
7124  add_path(final_rel, (Path *) final_path);
7125 
7126  /* Safe to push down */
7127  fpinfo->pushdown_safe = true;
7128 
7129  return;
7130  }
7131  }
7132 
7133  /*
7134  * If we get here it means no ForeignPaths; since we would already
7135  * have considered pushing down all operations for the query to the
7136  * remote server, give up on it.
7137  */
7138  return;
7139  }
7140 
7141  Assert(extra->limit_needed);
7142 
7143  /*
7144  * If the input_rel is an ordered relation, replace the input_rel with its
7145  * input relation
7146  */
7147  if (input_rel->reloptkind == RELOPT_UPPER_REL &&
7148  ifpinfo->stage == UPPERREL_ORDERED)
7149  {
7150  input_rel = ifpinfo->outerrel;
7151  ifpinfo = (PgFdwRelationInfo *) input_rel->fdw_private;
7152  has_final_sort = true;
7153  pathkeys = root->sort_pathkeys;
7154  }
7155 
7156  /* The input_rel should be a base, join, or grouping relation */
7157  Assert(input_rel->reloptkind == RELOPT_BASEREL ||
7158  input_rel->reloptkind == RELOPT_JOINREL ||
7159  (input_rel->reloptkind == RELOPT_UPPER_REL &&
7160  ifpinfo->stage == UPPERREL_GROUP_AGG));
7161 
7162  /*
7163  * We try to create a path below by extending a simple foreign path for
7164  * the underlying base, join, or grouping relation to perform the final
7165  * sort (if has_final_sort) and the LIMIT restriction remotely, which is
7166  * stored into the fdw_private list of the resulting path. (We
7167  * re-estimate the costs of sorting the underlying relation, if
7168  * has_final_sort.)
7169  */
7170 
7171  /*
7172  * Assess if it is safe to push down the LIMIT and OFFSET to the remote
7173  * server
7174  */
7175 
7176  /*
7177  * If the underlying relation has any local conditions, the LIMIT/OFFSET
7178  * cannot be pushed down.
7179  */
7180  if (ifpinfo->local_conds)
7181  return;
7182 
7183  /*
7184  * If the query has FETCH FIRST .. WITH TIES, 1) it must have ORDER BY as
7185  * well, which is used to determine which additional rows tie for the last
7186  * place in the result set, and 2) ORDER BY must already have been
7187  * determined to be safe to push down before we get here. So in that case
7188  * the FETCH clause is safe to push down with ORDER BY if the remote
7189  * server is v13 or later, but if not, the remote query will fail entirely
7190  * for lack of support for it. Since we do not currently have a way to do
7191  * a remote-version check (without accessing the remote server), disable
7192  * pushing the FETCH clause for now.
7193  */
7194  if (parse->limitOption == LIMIT_OPTION_WITH_TIES)
7195  return;
7196 
7197  /*
7198  * Also, the LIMIT/OFFSET cannot be pushed down, if their expressions are
7199  * not safe to remote.
7200  */
7201  if (!is_foreign_expr(root, input_rel, (Expr *) parse->limitOffset) ||
7202  !is_foreign_expr(root, input_rel, (Expr *) parse->limitCount))
7203  return;
7204 
7205  /* Safe to push down */
7206  fpinfo->pushdown_safe = true;
7207 
7208  /* Construct PgFdwPathExtraData */
7209  fpextra = (PgFdwPathExtraData *) palloc0(sizeof(PgFdwPathExtraData));
7210  fpextra->target = root->upper_targets[UPPERREL_FINAL];
7211  fpextra->has_final_sort = has_final_sort;
7212  fpextra->has_limit = extra->limit_needed;
7213  fpextra->limit_tuples = extra->limit_tuples;
7214  fpextra->count_est = extra->count_est;
7215  fpextra->offset_est = extra->offset_est;
7216 
7217  /*
7218  * Estimate the costs of performing the final sort and the LIMIT
7219  * restriction remotely. If has_final_sort is false, we wouldn't need to
7220  * execute EXPLAIN anymore if use_remote_estimate, since the costs can be
7221  * roughly estimated using the costs we already have for the underlying
7222  * relation, in the same way as when use_remote_estimate is false. Since
7223  * it's pretty expensive to execute EXPLAIN, force use_remote_estimate to
7224  * false in that case.
7225  */
7226  if (!fpextra->has_final_sort)
7227  {
7228  save_use_remote_estimate = ifpinfo->use_remote_estimate;
7229  ifpinfo->use_remote_estimate = false;
7230  }
7231  estimate_path_cost_size(root, input_rel, NIL, pathkeys, fpextra,
7232  &rows, &width, &disabled_nodes,
7233  &startup_cost, &total_cost);
7234  if (!fpextra->has_final_sort)
7235  ifpinfo->use_remote_estimate = save_use_remote_estimate;
7236 
7237  /*
7238  * Build the fdw_private list that will be used by postgresGetForeignPlan.
7239  * Items in the list must match order in enum FdwPathPrivateIndex.
7240  */
7241  fdw_private = list_make2(makeBoolean(has_final_sort),
7242  makeBoolean(extra->limit_needed));
7243 
7244  /*
7245  * Create foreign final path; this gets rid of a no-longer-needed outer
7246  * plan (if any), which makes the EXPLAIN output look cleaner
7247  */
7248  final_path = create_foreign_upper_path(root,
7249  input_rel,
7250  root->upper_targets[UPPERREL_FINAL],
7251  rows,
7252  disabled_nodes,
7253  startup_cost,
7254  total_cost,
7255  pathkeys,
7256  NULL, /* no extra plan */
7257  NIL, /* no fdw_restrictinfo list */
7258  fdw_private);
7259 
7260  /* and add it to the final_rel */
7261  add_path(final_rel, (Path *) final_path);
7262 }
7263 
7264 /*
7265  * postgresIsForeignPathAsyncCapable
7266  * Check whether a given ForeignPath node is async-capable.
7267  */
7268 static bool
7270 {
7271  RelOptInfo *rel = ((Path *) path)->parent;
7272  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) rel->fdw_private;
7273 
7274  return fpinfo->async_capable;
7275 }
7276 
7277 /*
7278  * postgresForeignAsyncRequest
7279  * Asynchronously request next tuple from a foreign PostgreSQL table.
7280  */
7281 static void
7283 {
7284  produce_tuple_asynchronously(areq, true);
7285 }
7286 
7287 /*
7288  * postgresForeignAsyncConfigureWait
7289  * Configure a file descriptor event for which we wish to wait.
7290  */
7291 static void
7293 {
7294  ForeignScanState *node = (ForeignScanState *) areq->requestee;
7295  PgFdwScanState *fsstate = (PgFdwScanState *) node->fdw_state;
7296  AsyncRequest *pendingAreq = fsstate->conn_state->pendingAreq;
7297  AppendState *requestor = (AppendState *) areq->requestor;
7298  WaitEventSet *set = requestor->as_eventset;
7299 
7300  /* This should not be called unless callback_pending */
7301  Assert(areq->callback_pending);
7302 
7303  /*
7304  * If process_pending_request() has been invoked on the given request
7305  * before we get here, we might have some tuples already; in which case
7306  * complete the request
7307  */
7308  if (fsstate->next_tuple < fsstate->num_tuples)
7309  {
7311  if (areq->request_complete)
7312  return;
7313  Assert(areq->callback_pending);
7314  }
7315 
7316  /* We must have run out of tuples */
7317  Assert(fsstate->next_tuple >= fsstate->num_tuples);
7318 
7319  /* The core code would have registered postmaster death event */
7321 
7322  /* Begin an asynchronous data fetch if not already done */
7323  if (!pendingAreq)
7324  fetch_more_data_begin(areq);
7325  else if (pendingAreq->requestor != areq->requestor)
7326  {
7327  /*
7328  * This is the case when the in-process request was made by another
7329  * Append. Note that it might be useless to process the request made
7330  * by that Append, because the query might not need tuples from that
7331  * Append anymore; so we avoid processing it to begin a fetch for the
7332  * given request if possible. If there are any child subplans of the
7333  * same parent that are ready for new requests, skip the given
7334  * request. Likewise, if there are any configured events other than
7335  * the postmaster death event, skip it. Otherwise, process the
7336  * in-process request, then begin a fetch to configure the event
7337  * below, because we might otherwise end up with no configured events
7338  * other than the postmaster death event.
7339  */
7340  if (!bms_is_empty(requestor->as_needrequest))
7341  return;
7342  if (GetNumRegisteredWaitEvents(set) > 1)
7343  return;
7344  process_pending_request(pendingAreq);
7345  fetch_more_data_begin(areq);
7346  }
7347  else if (pendingAreq->requestee != areq->requestee)
7348  {
7349  /*
7350  * This is the case when the in-process request was made by the same
7351  * parent but for a different child. Since we configure only the
7352  * event for the request made for that child, skip the given request.
7353  */
7354  return;
7355  }
7356  else
7357  Assert(pendingAreq == areq);
7358 
7359  AddWaitEventToSet(set, WL_SOCKET_READABLE, PQsocket(fsstate->conn),
7360  NULL, areq);
7361 }
7362 
7363 /*
7364  * postgresForeignAsyncNotify
7365  * Fetch some more tuples from a file descriptor that becomes ready,
7366  * requesting next tuple.
7367  */
7368 static void
7370 {
7371  ForeignScanState *node = (ForeignScanState *) areq->requestee;
7372  PgFdwScanState *fsstate = (PgFdwScanState *) node->fdw_state;
7373 
7374  /* The core code would have initialized the callback_pending flag */
7375  Assert(!areq->callback_pending);
7376 
7377  /*
7378  * If process_pending_request() has been invoked on the given request
7379  * before we get here, we might have some tuples already; in which case
7380  * produce the next tuple
7381  */
7382  if (fsstate->next_tuple < fsstate->num_tuples)
7383  {
7384  produce_tuple_asynchronously(areq, true);
7385  return;
7386  }
7387 
7388  /* We must have run out of tuples */
7389  Assert(fsstate->next_tuple >= fsstate->num_tuples);
7390 
7391  /* The request should be currently in-process */
7392  Assert(fsstate->conn_state->pendingAreq == areq);
7393 
7394  /* On error, report the original query, not the FETCH. */
7395  if (!PQconsumeInput(fsstate->conn))
7396  pgfdw_report_error(ERROR, NULL, fsstate->conn, false, fsstate->query);
7397 
7398  fetch_more_data(node);
7399 
7400  produce_tuple_asynchronously(areq, true);
7401 }
7402 
7403 /*
7404  * Asynchronously produce next tuple from a foreign PostgreSQL table.
7405  */
7406 static void
7408 {
7409  ForeignScanState *node = (ForeignScanState *) areq->requestee;
7410  PgFdwScanState *fsstate = (PgFdwScanState *) node->fdw_state;
7411  AsyncRequest *pendingAreq = fsstate->conn_state->pendingAreq;
7412  TupleTableSlot *result;
7413 
7414  /* This should not be called if the request is currently in-process */
7415  Assert(areq != pendingAreq);
7416 
7417  /* Fetch some more tuples, if we've run out */
7418  if (fsstate->next_tuple >= fsstate->num_tuples)
7419  {
7420  /* No point in another fetch if we already detected EOF, though */
7421  if (!fsstate->eof_reached)
7422  {
7423  /* Mark the request as pending for a callback */
7425  /* Begin another fetch if requested and if no pending request */
7426  if (fetch && !pendingAreq)
7427  fetch_more_data_begin(areq);
7428  }
7429  else
7430  {
7431  /* There's nothing more to do; just return a NULL pointer */
7432  result = NULL;
7433  /* Mark the request as complete */
7434  ExecAsyncRequestDone(areq, result);
7435  }
7436  return;
7437  }
7438 
7439  /* Get a tuple from the ForeignScan node */
7440  result = areq->requestee->ExecProcNodeReal(areq->requestee);
7441  if (!TupIsNull(result))
7442  {
7443  /* Mark the request as complete */
7444  ExecAsyncRequestDone(areq, result);
7445  return;
7446  }
7447 
7448  /* We must have run out of tuples */
7449  Assert(fsstate->next_tuple >= fsstate->num_tuples);
7450 
7451  /* Fetch some more tuples, if we've not detected EOF yet */
7452  if (!fsstate->eof_reached)
7453  {
7454  /* Mark the request as pending for a callback */
7456  /* Begin another fetch if requested and if no pending request */
7457  if (fetch && !pendingAreq)
7458  fetch_more_data_begin(areq);
7459  }
7460  else
7461  {
7462  /* There's nothing more to do; just return a NULL pointer */
7463  result = NULL;
7464  /* Mark the request as complete */
7465  ExecAsyncRequestDone(areq, result);
7466  }
7467 }
7468 
7469 /*
7470  * Begin an asynchronous data fetch.
7471  *
7472  * Note: this function assumes there is no currently-in-progress asynchronous
7473  * data fetch.
7474  *
7475  * Note: fetch_more_data must be called to fetch the result.
7476  */
7477 static void
7479 {
7480  ForeignScanState *node = (ForeignScanState *) areq->requestee;
7481  PgFdwScanState *fsstate = (PgFdwScanState *) node->fdw_state;
7482  char sql[64];
7483 
7484  Assert(!fsstate->conn_state->pendingAreq);
7485 
7486  /* Create the cursor synchronously. */
7487  if (!fsstate->cursor_exists)
7488  create_cursor(node);
7489 
7490  /* We will send this query, but not wait for the response. */
7491  snprintf(sql, sizeof(sql), "FETCH %d FROM c%u",
7492  fsstate->fetch_size, fsstate->cursor_number);
7493 
7494  if (!PQsendQuery(fsstate->conn, sql))
7495  pgfdw_report_error(ERROR, NULL, fsstate->conn, false, fsstate->query);
7496 
7497  /* Remember that the request is in process */
7498  fsstate->conn_state->pendingAreq = areq;
7499 }
7500 
7501 /*
7502  * Process a pending asynchronous request.
7503  */
7504 void
7506 {
7507  ForeignScanState *node = (ForeignScanState *) areq->requestee;
7508  PgFdwScanState *fsstate = (PgFdwScanState *) node->fdw_state;
7509 
7510  /* The request would have been pending for a callback */
7511  Assert(areq->callback_pending);
7512 
7513  /* The request should be currently in-process */
7514  Assert(fsstate->conn_state->pendingAreq == areq);
7515 
7516  fetch_more_data(node);
7517 
7518  /*
7519  * If we didn't get any tuples, must be end of data; complete the request
7520  * now. Otherwise, we postpone completing the request until we are called
7521  * from postgresForeignAsyncConfigureWait()/postgresForeignAsyncNotify().
7522  */
7523  if (fsstate->next_tuple >= fsstate->num_tuples)
7524  {
7525  /* Unlike AsyncNotify, we unset callback_pending ourselves */
7526  areq->callback_pending = false;
7527  /* Mark the request as complete */
7528  ExecAsyncRequestDone(areq, NULL);
7529  /* Unlike AsyncNotify, we call ExecAsyncResponse ourselves */
7530  ExecAsyncResponse(areq);
7531  }
7532 }
7533 
7534 /*
7535  * Complete a pending asynchronous request.
7536  */
7537 static void
7539 {
7540  /* The request would have been pending for a callback */
7541  Assert(areq->callback_pending);
7542 
7543  /* Unlike AsyncNotify, we unset callback_pending ourselves */
7544  areq->callback_pending = false;
7545 
7546  /* We begin a fetch afterwards if necessary; don't fetch */
7547  produce_tuple_asynchronously(areq, false);
7548 
7549  /* Unlike AsyncNotify, we call ExecAsyncResponse ourselves */
7550  ExecAsyncResponse(areq);
7551 
7552  /* Also, we do instrumentation ourselves, if required */
7553  if (areq->requestee->instrument)
7555  TupIsNull(areq->result) ? 0.0 : 1.0);
7556 }
7557 
7558 /*
7559  * Create a tuple from the specified row of the PGresult.
7560  *
7561  * rel is the local representation of the foreign table, attinmeta is
7562  * conversion data for the rel's tupdesc, and retrieved_attrs is an
7563  * integer list of the table column numbers present in the PGresult.
7564  * fsstate is the ForeignScan plan node's execution state.
7565  * temp_context is a working context that can be reset after each tuple.
7566  *
7567  * Note: either rel or fsstate, but not both, can be NULL. rel is NULL
7568  * if we're processing a remote join, while fsstate is NULL in a non-query
7569  * context such as ANALYZE, or if we're processing a non-scan query node.
7570  */
7571 static HeapTuple
7573  int row,
7574  Relation rel,
7575  AttInMetadata *attinmeta,
7576  List *retrieved_attrs,
7577  ForeignScanState *fsstate,
7578  MemoryContext temp_context)
7579 {
7580  HeapTuple tuple;
7581  TupleDesc tupdesc;
7582  Datum *values;
7583  bool *nulls;
7584  ItemPointer ctid = NULL;
7585  ConversionLocation errpos;
7586  ErrorContextCallback errcallback;
7587  MemoryContext oldcontext;
7588  ListCell *lc;
7589  int j;
7590 
7591  Assert(row < PQntuples(res));
7592 
7593  /*
7594  * Do the following work in a temp context that we reset after each tuple.
7595  * This cleans up not only the data we have direct access to, but any
7596  * cruft the I/O functions might leak.
7597  */
7598  oldcontext = MemoryContextSwitchTo(temp_context);
7599 
7600  /*
7601  * Get the tuple descriptor for the row. Use the rel's tupdesc if rel is
7602  * provided, otherwise look to the scan node's ScanTupleSlot.
7603  */
7604  if (rel)
7605  tupdesc = RelationGetDescr(rel);
7606  else
7607  {
7608  Assert(fsstate);
7609  tupdesc = fsstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor;
7610  }
7611 
7612  values = (Datum *) palloc0(tupdesc->natts * sizeof(Datum));
7613  nulls = (bool *) palloc(tupdesc->natts * sizeof(bool));
7614  /* Initialize to nulls for any columns not present in result */
7615  memset(nulls, true, tupdesc->natts * sizeof(bool));
7616 
7617  /*
7618  * Set up and install callback to report where conversion error occurs.
7619  */
7620  errpos.cur_attno = 0;
7621  errpos.rel = rel;
7622  errpos.fsstate = fsstate;
7623  errcallback.callback = conversion_error_callback;
7624  errcallback.arg = (void *) &errpos;
7625  errcallback.previous = error_context_stack;
7626  error_context_stack = &errcallback;
7627 
7628  /*
7629  * i indexes columns in the relation, j indexes columns in the PGresult.
7630  */
7631  j = 0;
7632  foreach(lc, retrieved_attrs)
7633  {
7634  int i = lfirst_int(lc);
7635  char *valstr;
7636 
7637  /* fetch next column's textual value */
7638  if (PQgetisnull(res, row, j))
7639  valstr = NULL;
7640  else
7641  valstr = PQgetvalue(res, row, j);
7642 
7643  /*
7644  * convert value to internal representation
7645  *
7646  * Note: we ignore system columns other than ctid and oid in result
7647  */
7648  errpos.cur_attno = i;
7649  if (i > 0)
7650  {
7651  /* ordinary column */
7652  Assert(i <= tupdesc->natts);
7653  nulls[i - 1] = (valstr == NULL);
7654  /* Apply the input function even to nulls, to support domains */
7655  values[i - 1] = InputFunctionCall(&attinmeta->attinfuncs[i - 1],
7656  valstr,
7657  attinmeta->attioparams[i - 1],
7658  attinmeta->atttypmods[i - 1]);
7659  }
7660  else if (i == SelfItemPointerAttributeNumber)
7661  {
7662  /* ctid */
7663  if (valstr != NULL)
7664  {
7665  Datum datum;
7666 
7667  datum = DirectFunctionCall1(tidin, CStringGetDatum(valstr));
7668  ctid = (ItemPointer) DatumGetPointer(datum);
7669  }
7670  }
7671  errpos.cur_attno = 0;
7672 
7673  j++;
7674  }
7675 
7676  /* Uninstall error context callback. */
7677  error_context_stack = errcallback.previous;
7678 
7679  /*
7680  * Check we got the expected number of columns. Note: j == 0 and
7681  * PQnfields == 1 is expected, since deparse emits a NULL if no columns.
7682  */
7683  if (j > 0 && j != PQnfields(res))
7684  elog(ERROR, "remote query result does not match the foreign table");
7685 
7686  /*
7687  * Build the result tuple in caller's memory context.
7688  */
7689  MemoryContextSwitchTo(oldcontext);
7690 
7691  tuple = heap_form_tuple(tupdesc, values, nulls);
7692 
7693  /*
7694  * If we have a CTID to return, install it in both t_self and t_ctid.
7695  * t_self is the normal place, but if the tuple is converted to a
7696  * composite Datum, t_self will be lost; setting t_ctid allows CTID to be
7697  * preserved during EvalPlanQual re-evaluations (see ROW_MARK_COPY code).
7698  */
7699  if (ctid)
7700  tuple->t_self = tuple->t_data->t_ctid = *ctid;
7701 
7702  /*
7703  * Stomp on the xmin, xmax, and cmin fields from the tuple created by
7704  * heap_form_tuple. heap_form_tuple actually creates the tuple with
7705  * DatumTupleFields, not HeapTupleFields, but the executor expects
7706  * HeapTupleFields and will happily extract system columns on that
7707  * assumption. If we don't do this then, for example, the tuple length
7708  * ends up in the xmin field, which isn't what we want.
7709  */
7713 
7714  /* Clean up */
7715  MemoryContextReset(temp_context);
7716 
7717  return tuple;
7718 }
7719 
7720 /*
7721  * Callback function which is called when error occurs during column value
7722  * conversion. Print names of column and relation.
7723  *
7724  * Note that this function mustn't do any catalog lookups, since we are in
7725  * an already-failed transaction. Fortunately, we can get the needed info
7726  * from the relation or the query's rangetable instead.
7727  */
7728 static void
7730 {
7732  Relation rel = errpos->rel;
7733  ForeignScanState *fsstate = errpos->fsstate;
7734  const char *attname = NULL;
7735  const char *relname = NULL;
7736  bool is_wholerow = false;
7737 
7738  /*
7739  * If we're in a scan node, always use aliases from the rangetable, for
7740  * consistency between the simple-relation and remote-join cases. Look at
7741  * the relation's tupdesc only if we're not in a scan node.
7742  */
7743  if (fsstate)
7744  {
7745  /* ForeignScan case */
7746  ForeignScan *fsplan = castNode(ForeignScan, fsstate->ss.ps.plan);
7747  int varno = 0;
7748  AttrNumber colno = 0;
7749 
7750  if (fsplan->scan.scanrelid > 0)
7751  {
7752  /* error occurred in a scan against a foreign table */
7753  varno = fsplan->scan.scanrelid;
7754  colno = errpos->cur_attno;
7755  }
7756  else
7757  {
7758  /* error occurred in a scan against a foreign join */
7759  TargetEntry *tle;
7760 
7761  tle = list_nth_node(TargetEntry, fsplan->fdw_scan_tlist,
7762  errpos->cur_attno - 1);
7763 
7764  /*
7765  * Target list can have Vars and expressions. For Vars, we can
7766  * get some information, however for expressions we can't. Thus
7767  * for expressions, just show generic context message.
7768  */
7769  if (IsA(tle->expr, Var))
7770  {
7771  Var *var = (Var *) tle->expr;
7772 
7773  varno = var->varno;
7774  colno = var->varattno;
7775  }
7776  }
7777 
7778  if (varno > 0)
7779  {
7780  EState *estate = fsstate->ss.ps.state;
7781  RangeTblEntry *rte = exec_rt_fetch(varno, estate);
7782 
7783  relname = rte->eref->aliasname;
7784 
7785  if (colno == 0)
7786  is_wholerow = true;
7787  else if (colno > 0 && colno <= list_length(rte->eref->colnames))
7788  attname = strVal(list_nth(rte->eref->colnames, colno - 1));
7789  else if (colno == SelfItemPointerAttributeNumber)
7790  attname = "ctid";
7791  }
7792  }
7793  else if (rel)
7794  {
7795  /* Non-ForeignScan case (we should always have a rel here) */
7796  TupleDesc tupdesc = RelationGetDescr(rel);
7797 
7799  if (errpos->cur_attno > 0 && errpos->cur_attno <= tupdesc->natts)
7800  {
7801  Form_pg_attribute attr = TupleDescAttr(tupdesc,
7802  errpos->cur_attno - 1);
7803 
7804  attname = NameStr(attr->attname);
7805  }
7806  else if (errpos->cur_attno == SelfItemPointerAttributeNumber)
7807  attname = "ctid";
7808  }
7809 
7810  if (relname && is_wholerow)
7811  errcontext("whole-row reference to foreign table \"%s\"", relname);
7812  else if (relname && attname)
7813  errcontext("column \"%s\" of foreign table \"%s\"", attname, relname);
7814  else
7815  errcontext("processing expression at position %d in select list",
7816  errpos->cur_attno);
7817 }
7818 
7819 /*
7820  * Given an EquivalenceClass and a foreign relation, find an EC member
7821  * that can be used to sort the relation remotely according to a pathkey
7822  * using this EC.
7823  *
7824  * If there is more than one suitable candidate, return an arbitrary
7825  * one of them. If there is none, return NULL.
7826  *
7827  * This checks that the EC member expression uses only Vars from the given
7828  * rel and is shippable. Caller must separately verify that the pathkey's
7829  * ordering operator is shippable.
7830  */
7833 {
7834  ListCell *lc;
7835 
7836  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) rel->fdw_private;
7837 
7838  foreach(lc, ec->ec_members)
7839  {
7841 
7842  /*
7843  * Note we require !bms_is_empty, else we'd accept constant
7844  * expressions which are not suitable for the purpose.
7845  */
7846  if (bms_is_subset(em->em_relids, rel->relids) &&
7847  !bms_is_empty(em->em_relids) &&
7849  is_foreign_expr(root, rel, em->em_expr))
7850  return em;
7851  }
7852 
7853  return NULL;
7854 }
7855 
7856 /*
7857  * Find an EquivalenceClass member that is to be computed as a sort column
7858  * in the given rel's reltarget, and is shippable.
7859  *
7860  * If there is more than one suitable candidate, return an arbitrary
7861  * one of them. If there is none, return NULL.
7862  *
7863  * This checks that the EC member expression uses only Vars from the given
7864  * rel and is shippable. Caller must separately verify that the pathkey's
7865  * ordering operator is shippable.
7866  */
7869  RelOptInfo *rel)
7870 {
7871  PathTarget *target = rel->reltarget;
7872  ListCell *lc1;
7873  int i;
7874 
7875  i = 0;
7876  foreach(lc1, target->exprs)
7877  {
7878  Expr *expr = (Expr *) lfirst(lc1);
7879  Index sgref = get_pathtarget_sortgroupref(target, i);
7880  ListCell *lc2;
7881 
7882  /* Ignore non-sort expressions */
7883  if (sgref == 0 ||
7885  root->parse->sortClause) == NULL)
7886  {
7887  i++;
7888  continue;
7889  }
7890 
7891  /* We ignore binary-compatible relabeling on both ends */
7892  while (expr && IsA(expr, RelabelType))
7893  expr = ((RelabelType *) expr)->arg;
7894 
7895  /* Locate an EquivalenceClass member matching this expr, if any */
7896  foreach(lc2, ec->ec_members)
7897  {
7899  Expr *em_expr;
7900 
7901  /* Don't match constants */
7902  if (em->em_is_const)
7903  continue;
7904 
7905  /* Ignore child members */
7906  if (em->em_is_child)
7907  continue;
7908 
7909  /* Match if same expression (after stripping relabel) */
7910  em_expr = em->em_expr;
7911  while (em_expr && IsA(em_expr, RelabelType))
7912  em_expr = ((RelabelType *) em_expr)->arg;
7913 
7914  if (!equal(em_expr, expr))
7915  continue;
7916 
7917  /* Check that expression (including relabels!) is shippable */
7918  if (is_foreign_expr(root, rel, em->em_expr))
7919  return em;
7920  }
7921 
7922  i++;
7923  }
7924 
7925  return NULL;
7926 }
7927 
7928 /*
7929  * Determine batch size for a given foreign table. The option specified for
7930  * a table has precedence.
7931  */
7932 static int
7934 {
7935  Oid foreigntableid = RelationGetRelid(rel);
7936  ForeignTable *table;
7937  ForeignServer *server;
7938  List *options;
7939  ListCell *lc;
7940 
7941  /* we use 1 by default, which means "no batching" */
7942  int batch_size = 1;
7943 
7944  /*
7945  * Load options for table and server. We append server options after table
7946  * options, because table options take precedence.
7947  */
7948  table = GetForeignTable(foreigntableid);
7949  server = GetForeignServer(table->serverid);
7950 
7951  options = NIL;
7952  options = list_concat(options, table->options);
7953  options = list_concat(options, server->options);
7954 
7955  /* See if either table or server specifies batch_size. */
7956  foreach(lc, options)
7957  {
7958  DefElem *def = (DefElem *) lfirst(lc);
7959 
7960  if (strcmp(def->defname, "batch_size") == 0)
7961  {
7962  (void) parse_int(defGetString(def), &batch_size, 0, NULL);
7963  break;
7964  }
7965  }
7966 
7967  return batch_size;
7968 }
void get_translated_update_targetlist(PlannerInfo *root, Index relid, List **processed_tlist, List **update_colnos)
Definition: appendinfo.c:694
void add_row_identity_var(PlannerInfo *root, Var *orig_var, Index rtindex, const char *rowid_name)
Definition: appendinfo.c:793
int16 AttrNumber
Definition: attnum.h:21
#define AttributeNumberIsValid(attributeNumber)
Definition: attnum.h:34
#define InvalidAttrNumber
Definition: attnum.h:23
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1306
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:412
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:510
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:251
Bitmapset * bms_intersect(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:292
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:917
Bitmapset * bms_del_member(Bitmapset *a, int x)
Definition: bitmapset.c:868
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:582
bool bms_nonempty_difference(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:641
#define bms_is_empty(a)
Definition: bitmapset.h:118
uint32 BlockNumber
Definition: block.h:31
static Datum values[MAXATTR]
Definition: bootstrap.c:150
#define NameStr(name)
Definition: c.h:737
#define Min(x, y)
Definition: c.h:995
#define MAXALIGN(LEN)
Definition: c.h:802
#define Max(x, y)
Definition: c.h:989
#define Assert(condition)
Definition: c.h:849
#define CppAsString2(x)
Definition: c.h:330
unsigned int Index
Definition: c.h:605
#define MemSet(start, val, len)
Definition: c.h:1011
#define OidIsValid(objectId)
Definition: c.h:766
Selectivity clauselist_selectivity(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: clausesel.c:100
unsigned int GetCursorNumber(PGconn *conn)
Definition: connection.c:824
void do_sql_command(PGconn *conn, const char *sql)
Definition: connection.c:717
void ReleaseConnection(PGconn *conn)
Definition: connection.c:803
void pgfdw_report_error(int elevel, PGresult *res, PGconn *conn, bool clear, const char *sql)
Definition: connection.c:889
PGresult * pgfdw_exec_query(PGconn *conn, const char *query, PgFdwConnState *state)
Definition: connection.c:853
static unsigned int cursor_number
Definition: connection.c:84
PGconn * GetConnection(UserMapping *user, bool will_prep_stmt, PgFdwConnState **state)
Definition: connection.c:195
unsigned int GetPrepStmtNumber(PGconn *conn)
Definition: connection.c:838
PGresult * pgfdw_get_result(PGconn *conn)
Definition: connection.c:870
List * ExtractExtensionList(const char *extensionsString, bool warnOnMissing)
Definition: option.c:445
double cpu_operator_cost
Definition: costsize.c:134
void set_baserel_size_estimates(PlannerInfo *root, RelOptInfo *rel)
Definition: costsize.c:5326
void cost_sort(Path *path, PlannerInfo *root, List *pathkeys, int input_disabled_nodes, Cost input_cost, double tuples, int width, Cost comparison_cost, int sort_mem, double limit_tuples)
Definition: costsize.c:2144
double cpu_tuple_cost
Definition: costsize.c:132
void cost_qual_eval(QualCost *cost, List *quals, PlannerInfo *root)
Definition: costsize.c:4732
double seq_page_cost
Definition: costsize.c:130
double clamp_row_est(double nrows)
Definition: costsize.c:213
bool is_projection_capable_path(Path *path)
Definition: createplan.c:7296
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)
Definition: createplan.c:5896
Plan * change_plan_targetlist(Plan *subplan, List *tlist, bool tlist_parallel_safe)
Definition: createplan.c:2151
bool defGetBoolean(DefElem *def)
Definition: define.c:107
char * defGetString(DefElem *def)
Definition: define.c:48
void deparseAnalyzeSizeSql(StringInfo buf, Relation rel)
Definition: deparse.c:2499
const char * get_jointype_name(JoinType jointype)
Definition: deparse.c:1641
void deparseAnalyzeInfoSql(StringInfo buf, Relation rel)
Definition: deparse.c:2521
void deparseDirectDeleteSql(StringInfo buf, PlannerInfo *root, Index rtindex, Relation rel, RelOptInfo *foreignrel, List *remote_conds, List **params_list, List *returningList, List **retrieved_attrs)
Definition: deparse.c:2391
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)
Definition: deparse.c:2276
bool is_foreign_param(PlannerInfo *root, RelOptInfo *baserel, Expr *expr)
Definition: deparse.c:1082
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)
Definition: deparse.c:1233
void deparseStringLiteral(StringInfo buf, const char *val)
Definition: deparse.c:2849
void rebuildInsertSql(StringInfo buf, Relation rel, char *orig_query, List *target_attrs, int values_end_len, int num_params, int num_rows)
Definition: deparse.c:2156
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)
Definition: deparse.c:2083
void deparseUpdateSql(StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, List *targetAttrs, List *withCheckOptionList, List *returningList, List **retrieved_attrs)
Definition: deparse.c:2216
void deparseDeleteSql(StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, List *returningList, List **retrieved_attrs)
Definition: deparse.c:2362
void deparseAnalyzeSql(StringInfo buf, Relation rel, PgFdwSamplingMethod sample_method, double sample_frac, List **retrieved_attrs)
Definition: deparse.c:2561
bool is_foreign_expr(PlannerInfo *root, RelOptInfo *baserel, Expr *expr)
Definition: deparse.c:244
List * build_tlist_to_deparse(RelOptInfo *foreignrel)
Definition: deparse.c:1176
void classifyConditions(PlannerInfo *root, RelOptInfo *baserel, List *input_conds, List **remote_conds, List **local_conds)
Definition: deparse.c:218
void deparseTruncateSql(StringInfo buf, List *rels, DropBehavior behavior, bool restart_seqs)
Definition: deparse.c:2646
bool is_foreign_pathkey(PlannerInfo *root, RelOptInfo *baserel, PathKey *pathkey)
Definition: deparse.c:1123
ErrorContextCallback * error_context_stack
Definition: elog.c:94
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define PG_RE_THROW()
Definition: elog.h:412
#define errcontext
Definition: elog.h:196
#define DEBUG3
Definition: elog.h:28
#define PG_TRY(...)
Definition: elog.h:371
#define PG_END_TRY(...)
Definition: elog.h:396
#define ERROR
Definition: elog.h:39
#define PG_CATCH(...)
Definition: elog.h:381
#define elog(elevel,...)
Definition: elog.h:225
#define PG_FINALLY(...)
Definition: elog.h:388
#define ereport(elevel,...)
Definition: elog.h:149
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:223
List * generate_implied_equalities_for_column(PlannerInfo *root, RelOptInfo *rel, ec_matches_callback_type callback, void *callback_arg, Relids prohibited_rels)
Definition: equivclass.c:3014
bool eclass_useful_for_merging(PlannerInfo *root, EquivalenceClass *eclass, RelOptInfo *rel)
Definition: equivclass.c:3266
void ExecAsyncResponse(AsyncRequest *areq)
Definition: execAsync.c:117
void ExecAsyncRequestPending(AsyncRequest *areq)
Definition: execAsync.c:149
void ExecAsyncRequestDone(AsyncRequest *areq, TupleTableSlot *result)
Definition: execAsync.c:137
List * ExecInitExprList(List *nodes, PlanState *parent)
Definition: execExpr.c:330
AttrNumber ExecFindJunkAttributeInTlist(List *targetlist, const char *attrName)
Definition: execJunk.c:222
AttInMetadata * TupleDescGetAttInMetadata(TupleDesc tupdesc)
Definition: execTuples.c:2173
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1639
TupleTableSlot * ExecStoreAllNullTuple(TupleTableSlot *slot)
Definition: execTuples.c:1663
HeapTuple ExecFetchSlotHeapTuple(TupleTableSlot *slot, bool materialize, bool *shouldFree)
Definition: execTuples.c:1731
TupleTableSlot * ExecStoreHeapTuple(HeapTuple tuple, TupleTableSlot *slot, bool shouldFree)
Definition: execTuples.c:1439
void ExecForceStoreHeapTuple(HeapTuple tuple, TupleTableSlot *slot, bool shouldFree)
Definition: execTuples.c:1556
TupleTableSlot * ExecGetReturningSlot(EState *estate, ResultRelInfo *relInfo)
Definition: execUtils.c:1184
Relation ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
Definition: execUtils.c:699
Oid ExecGetResultRelCheckAsUser(ResultRelInfo *relInfo, EState *estate)
Definition: execUtils.c:1397
#define outerPlanState(node)
Definition: execnodes.h:1224
static RangeTblEntry * exec_rt_fetch(Index rti, EState *estate)
Definition: executor.h:598
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:344
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:65
static Datum ExecGetJunkAttribute(TupleTableSlot *slot, AttrNumber attno, bool *isNull)
Definition: executor.h:190
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition: executor.h:273
void ExplainPropertyText(const char *qlabel, const char *value, ExplainState *es)
Definition: explain.c:5111
void ExplainPropertyInteger(const char *qlabel, const char *unit, int64 value, ExplainState *es)
Definition: explain.c:5120
int(* AcquireSampleRowsFunc)(Relation relation, int elevel, HeapTuple *rows, int targrows, double *totalrows, double *totaldeadrows)
Definition: fdwapi.h:151
int PQserverVersion(const PGconn *conn)
Definition: fe-connect.c:7202
int PQsocket(const PGconn *conn)
Definition: fe-connect.c:7238
int PQsendQueryParams(PGconn *conn, const char *command, int nParams, const Oid *paramTypes, const char *const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat)
Definition: fe-exec.c:1492
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:3411
char * PQcmdTuples(PGresult *res)
Definition: fe-exec.c:3822
int PQntuples(const PGresult *res)
Definition: fe-exec.c:3481
int PQconsumeInput(PGconn *conn)
Definition: fe-exec.c:1984
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3876
int PQsendPrepare(PGconn *conn, const char *stmtName, const char *query, int nParams, const Oid *paramTypes)
Definition: fe-exec.c:1536
int PQgetisnull(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3901
int PQsendQuery(PGconn *conn, const char *query)
Definition: fe-exec.c:1416
int PQsendQueryPrepared(PGconn *conn, const char *stmtName, int nParams, const char *const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat)
Definition: fe-exec.c:1633
int PQnfields(const PGresult *res)
Definition: fe-exec.c:3489
int extra_float_digits
Definition: float.c:41
Datum InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
Definition: fmgr.c:1530
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:127
char * OutputFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1683
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:641
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
ForeignTable * GetForeignTable(Oid relid)
Definition: foreign.c:254
Path * GetExistingLocalJoinPath(RelOptInfo *joinrel)
Definition: foreign.c:741
UserMapping * GetUserMapping(Oid userid, Oid serverid)
Definition: foreign.c:200
ForeignServer * GetForeignServer(Oid serverid)
Definition: foreign.c:111
int DateStyle
Definition: globals.c:124
int IntervalStyle
Definition: globals.c:126
int work_mem
Definition: globals.c:130
bool parse_int(const char *value, int *result, int flags, const char **hintmsg)
Definition: guc.c:2870
int NewGUCNestLevel(void)
Definition: guc.c:2234
bool parse_real(const char *value, double *result, int flags, const char **hintmsg)
Definition: guc.c:2960
void AtEOXact_GUC(bool isCommit, int nestLevel)
Definition: guc.c:2261
int set_config_option(const char *name, const char *value, GucContext context, GucSource source, GucAction action, bool changeVal, int elevel, bool is_reload)
Definition: guc.c:3341
@ GUC_ACTION_SAVE
Definition: guc.h:201
@ PGC_S_SESSION
Definition: guc.h:122
@ PGC_USERSET
Definition: guc.h:75
static int server_version_num
Definition: guc_tables.c:577
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition: heaptuple.c:1116
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1434
#define SizeofHeapTupleHeader
Definition: htup_details.h:185
#define HeapTupleHeaderSetXmin(tup, xid)
Definition: htup_details.h:315
#define HeapTupleHeaderSetXmax(tup, xid)
Definition: htup_details.h:376
#define HeapTupleHeaderSetCmin(tup, cid)
Definition: htup_details.h:393
#define stmt
Definition: indent_codes.h:59
static struct @157 value
Bitmapset * get_rel_all_updated_cols(PlannerInfo *root, RelOptInfo *rel)
Definition: inherit.c:657
void InstrUpdateTupleCount(Instrumentation *instr, double nTuples)
Definition: instrument.c:132
int j
Definition: isn.c:74
int i
Definition: isn.c:73
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
ItemPointerData * ItemPointer
Definition: itemptr.h:49
int GetNumRegisteredWaitEvents(WaitEventSet *set)
Definition: latch.c:2262
int AddWaitEventToSet(WaitEventSet *set, uint32 events, pgsocket fd, Latch *latch, void *user_data)
Definition: latch.c:963
#define WL_SOCKET_READABLE
Definition: latch.h:128
@ PGRES_COMMAND_OK
Definition: libpq-fe.h:120
@ PGRES_TUPLES_OK
Definition: libpq-fe.h:123
#define PQ_QUERY_PARAM_MAX_LIMIT
Definition: libpq-fe.h:495
List * lappend(List *list, void *datum)
Definition: list.c:339
List * lappend_int(List *list, int datum)
Definition: list.c:357
List * list_copy(const List *oldlist)
Definition: list.c:1573
List * list_delete(List *list, void *datum)
Definition: list.c:853
bool list_member_ptr(const List *list, const void *datum)
Definition: list.c:682
void list_free(List *list)
Definition: list.c:1546
bool list_member_int(const List *list, int datum)
Definition: list.c:702
List * list_concat(List *list1, const List *list2)
Definition: list.c:561
bool list_member(const List *list, const void *datum)
Definition: list.c:661
List * list_append_unique_ptr(List *list, void *datum)
Definition: list.c:1356
#define NoLock
Definition: lockdefs.h:34
char * get_namespace_name_or_temp(Oid nspid)
Definition: lsyscache.c:3390
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2907
Oid get_rel_namespace(Oid relid)
Definition: lsyscache.c:1952
Oid get_rel_type_id(Oid relid)
Definition: lsyscache.c:1979
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1928
Datum subpath(PG_FUNCTION_ARGS)
Definition: ltree_op.c:310
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:240
Var * makeVar(int varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition: makefuncs.c:66
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:383
char * pstrdup(const char *in)
Definition: mcxt.c:1696
void pfree(void *pointer)
Definition: mcxt.c:1521
void * palloc0(Size size)
Definition: mcxt.c:1347
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
void * palloc(Size size)
Definition: mcxt.c:1317
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:170
#define USE_ISO_DATES
Definition: miscadmin.h:236
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
#define INTSTYLE_POSTGRES
Definition: miscadmin.h:256
Oid GetUserId(void)
Definition: miscinit.c:514
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
#define copyObject(obj)
Definition: nodes.h:224
double Cost
Definition: nodes.h:251
#define IS_OUTER_JOIN(jointype)
Definition: nodes.h:338
OnConflictAction
Definition: nodes.h:417
@ ONCONFLICT_NONE
Definition: nodes.h:418
@ ONCONFLICT_NOTHING
Definition: nodes.h:419
CmdType
Definition: nodes.h:263
@ CMD_INSERT
Definition: nodes.h:267
@ CMD_DELETE
Definition: nodes.h:268
@ CMD_UPDATE
Definition: nodes.h:266
@ CMD_SELECT
Definition: nodes.h:265
double Selectivity
Definition: nodes.h:250
@ AGGSPLIT_SIMPLE
Definition: nodes.h:377
@ LIMIT_OPTION_WITH_TIES
Definition: nodes.h:432
#define makeNode(_type_)
Definition: nodes.h:155
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
JoinType
Definition: nodes.h:288
@ JOIN_SEMI
Definition: nodes.h:307
@ JOIN_FULL
Definition: nodes.h:295
@ JOIN_INNER
Definition: nodes.h:293
@ JOIN_RIGHT
Definition: nodes.h:296
@ JOIN_LEFT
Definition: nodes.h:294
#define PVC_RECURSE_PLACEHOLDERS
Definition: optimizer.h:191
#define PVC_INCLUDE_PLACEHOLDERS
Definition: optimizer.h:190
#define PVC_INCLUDE_AGGREGATES
Definition: optimizer.h:186
@ FDW_IMPORT_SCHEMA_LIMIT_TO
Definition: parsenodes.h:2956
@ FDW_IMPORT_SCHEMA_EXCEPT
Definition: parsenodes.h:2957
@ RTE_RELATION
Definition: parsenodes.h:1017
DropBehavior
Definition: parsenodes.h:2330
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
void update_mergeclause_eclasses(PlannerInfo *root, RestrictInfo *restrictinfo)
Definition: pathkeys.c:1509
PathKey * make_canonical_pathkey(PlannerInfo *root, EquivalenceClass *eclass, Oid opfamily, int strategy, bool nulls_first)
Definition: pathkeys.c:56
bool pathkeys_contained_in(List *keys1, List *keys2)
Definition: pathkeys.c:343
SortPath * create_sort_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, List *pathkeys, double limit_tuples)
Definition: pathnode.c:3082
ProjectionPath * create_projection_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target)
Definition: pathnode.c:2763
ForeignPath * create_foreign_join_path(PlannerInfo *root, RelOptInfo *rel, PathTarget *target, double rows, int disabled_nodes, Cost startup_cost, Cost total_cost, List *pathkeys, Relids required_outer, Path *fdw_outerpath, List *fdw_restrictinfo, List *fdw_private)
Definition: pathnode.c:2355
ForeignPath * create_foreign_upper_path(PlannerInfo *root, RelOptInfo *rel, PathTarget *target, double rows, int disabled_nodes, Cost startup_cost, Cost total_cost, List *pathkeys, Path *fdw_outerpath, List *fdw_restrictinfo, List *fdw_private)
Definition: pathnode.c:2409
void add_path(RelOptInfo *parent_rel, Path *new_path)
Definition: pathnode.c:461
ForeignPath * create_foreignscan_path(PlannerInfo *root, RelOptInfo *rel, PathTarget *target, double rows, int disabled_nodes, Cost startup_cost, Cost total_cost, List *pathkeys, Relids required_outer, Path *fdw_outerpath, List *fdw_restrictinfo, List *fdw_private)
Definition: pathnode.c:2307
void adjust_limit_rows_costs(double *rows, Cost *startup_cost, Cost *total_cost, int64 offset_est, int64 count_est)
Definition: pathnode.c:3978
#define RINFO_IS_PUSHED_DOWN(rinfo, joinrelids)
Definition: pathnodes.h:2731
@ PARTITIONWISE_AGGREGATE_FULL
Definition: pathnodes.h:3281
@ PARTITIONWISE_AGGREGATE_NONE
Definition: pathnodes.h:3280
#define IS_SIMPLE_REL(rel)
Definition: pathnodes.h:839
#define IS_JOIN_REL(rel)
Definition: pathnodes.h:844
#define get_pathtarget_sortgroupref(target, colno)
Definition: pathnodes.h:1558
#define planner_rt_fetch(rti, root)
Definition: pathnodes.h:570
UpperRelationKind
Definition: pathnodes.h:70
@ UPPERREL_GROUP_AGG
Definition: pathnodes.h:74
@ UPPERREL_FINAL
Definition: pathnodes.h:79
@ UPPERREL_ORDERED
Definition: pathnodes.h:78
@ RELOPT_BASEREL
Definition: pathnodes.h:827
@ RELOPT_UPPER_REL
Definition: pathnodes.h:831
@ RELOPT_JOINREL
Definition: pathnodes.h:828
#define IS_OTHER_REL(rel)
Definition: pathnodes.h:854
#define IS_UPPER_REL(rel)
Definition: pathnodes.h:849
NameData attname
Definition: pg_attribute.h:41
int16 attnum
Definition: pg_attribute.h:74
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
bool attnotnull
Definition: pg_attribute.h:130
void * arg
NameData relname
Definition: pg_class.h:38
#define NAMEDATALEN
#define lfirst(lc)
Definition: pg_list.h:172
#define lfirst_node(type, lc)
Definition: pg_list.h:176
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:518
#define lfirst_int(lc)
Definition: pg_list.h:173
#define list_make5(x1, x2, x3, x4, x5)
Definition: pg_list.h:222
#define list_make1(x1)
Definition: pg_list.h:212
#define linitial(l)
Definition: pg_list.h:178
#define list_make3(x1, x2, x3)
Definition: pg_list.h:216
static void * list_nth(const List *list, int n)
Definition: pg_list.h:299
#define list_nth_node(type, list, n)
Definition: pg_list.h:327
#define linitial_oid(l)
Definition: pg_list.h:180
#define list_make2(x1, x2)
Definition: pg_list.h:214
#define list_make4(x1, x2, x3, x4)
Definition: pg_list.h:219
static char ** options
#define plan(x)
Definition: pg_regress.c:162
static char * user
Definition: pg_regress.c:120
uint64 fetch_size
Definition: pg_rewind.c:85
static char * buf
Definition: pg_test_fsync.c:73
#define outerPlan(node)
Definition: plannodes.h:183
#define snprintf
Definition: port.h:238
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
uintptr_t Datum
Definition: postgres.h:64
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
static int postgresGetForeignModifyBatchSize(ResultRelInfo *resultRelInfo)
#define DEFAULT_FDW_SORT_MULTIPLIER
Definition: postgres_fdw.c:63
static const char ** convert_prep_stmt_params(PgFdwModifyState *fmstate, ItemPointer tupleid, TupleTableSlot **slots, int numSlots)
static ForeignScan * find_modifytable_subplan(PlannerInfo *root, ModifyTable *plan, Index rtindex, int subplan_index)
static TupleTableSlot * apply_returning_filter(PgFdwDirectModifyState *dmstate, ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
static bool foreign_join_ok(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinPathExtraData *extra)
static void postgresBeginForeignScan(ForeignScanState *node, int eflags)
static bool postgresIsForeignPathAsyncCapable(ForeignPath *path)
static void store_returning_result(PgFdwModifyState *fmstate, TupleTableSlot *slot, PGresult *res)
static void create_cursor(ForeignScanState *node)
static void postgresExecForeignTruncate(List *rels, DropBehavior behavior, bool restart_seqs)
static void postgresExplainForeignModify(ModifyTableState *mtstate, ResultRelInfo *rinfo, List *fdw_private, int subplan_index, ExplainState *es)
static void analyze_row_processor(PGresult *res, int row, PgFdwAnalyzeState *astate)
static TupleTableSlot ** postgresExecForeignBatchInsert(EState *estate, ResultRelInfo *resultRelInfo, TupleTableSlot **slots, TupleTableSlot **planSlots, int *numSlots)
static void deallocate_query(PgFdwModifyState *fmstate)
static void postgresGetForeignJoinPaths(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra)
static void postgresExplainForeignScan(ForeignScanState *node, ExplainState *es)
static TupleDesc get_tupdesc_for_join_scan_tuples(ForeignScanState *node)
static void adjust_foreign_grouping_path_cost(PlannerInfo *root, List *pathkeys, double retrieved_rows, double width, double limit_tuples, int *disabled_nodes, Cost *p_startup_cost, Cost *p_run_cost)
static TupleTableSlot * postgresExecForeignUpdate(EState *estate, ResultRelInfo *resultRelInfo, TupleTableSlot *slot, TupleTableSlot *planSlot)
static bool postgresPlanDirectModify(PlannerInfo *root, ModifyTable *plan, Index resultRelation, int subplan_index)
static void conversion_error_callback(void *arg)
static void postgresReScanForeignScan(ForeignScanState *node)
static void prepare_foreign_modify(PgFdwModifyState *fmstate)
static void postgresForeignAsyncRequest(AsyncRequest *areq)
static int postgresIsForeignRelUpdatable(Relation rel)
void reset_transmission_modes(int nestlevel)
int set_transmission_modes(void)
static double postgresGetAnalyzeInfoForForeignTable(Relation relation, bool *can_tablesample)
PG_MODULE_MAGIC
Definition: postgres_fdw.c:54
FdwDirectModifyPrivateIndex
Definition: postgres_fdw.c:124
@ FdwDirectModifyPrivateSetProcessed
Definition: postgres_fdw.c:132
@ FdwDirectModifyPrivateHasReturning
Definition: postgres_fdw.c:128
@ FdwDirectModifyPrivateRetrievedAttrs
Definition: postgres_fdw.c:130
@ FdwDirectModifyPrivateUpdateSql
Definition: postgres_fdw.c:126
static void rebuild_fdw_scan_tlist(ForeignScan *fscan, List *tlist)
static ForeignScan * postgresGetForeignPlan(PlannerInfo *root, RelOptInfo *foreignrel, Oid foreigntableid, ForeignPath *best_path, List *tlist, List *scan_clauses, Plan *outer_plan)
static void postgresEndForeignScan(ForeignScanState *node)
static void postgresGetForeignPaths(PlannerInfo *root, RelOptInfo *baserel, Oid foreigntableid)
static void add_foreign_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, RelOptInfo *grouped_rel, GroupPathExtraData *extra)
static List * postgresPlanForeignModify(PlannerInfo *root, ModifyTable *plan, Index resultRelation, int subplan_index)
static void estimate_path_cost_size(PlannerInfo *root, RelOptInfo *foreignrel, List *param_join_conds, List *pathkeys, PgFdwPathExtraData *fpextra, double *p_rows, int *p_width, int *p_disabled_nodes, Cost *p_startup_cost, Cost *p_total_cost)
static void fetch_more_data(ForeignScanState *node)
static void prepare_query_params(PlanState *node, List *fdw_exprs, int numParams, FmgrInfo **param_flinfo, List **param_exprs, const char ***param_values)
static void postgresEndForeignModify(EState *estate, ResultRelInfo *resultRelInfo)
static void produce_tuple_asynchronously(AsyncRequest *areq, bool fetch)
static void add_foreign_ordered_paths(PlannerInfo *root, RelOptInfo *input_rel, RelOptInfo *ordered_rel)
static bool semijoin_target_ok(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel)
struct PgFdwModifyState PgFdwModifyState
static void merge_fdw_options(PgFdwRelationInfo *fpinfo, const PgFdwRelationInfo *fpinfo_o, const PgFdwRelationInfo *fpinfo_i)
static void postgresAddForeignUpdateTargets(PlannerInfo *root, Index rtindex, RangeTblEntry *target_rte, Relation target_relation)
static void postgresGetForeignRelSize(PlannerInfo *root, RelOptInfo *baserel, Oid foreigntableid)
Definition: postgres_fdw.c:624
static HeapTuple make_tuple_from_result_row(PGresult *res, int row, Relation rel, AttInMetadata *attinmeta, List *retrieved_attrs, ForeignScanState *fsstate, MemoryContext temp_context)
static void postgresEndDirectModify(ForeignScanState *node)
static void get_remote_estimate(const char *sql, PGconn *conn, double *rows, int *width, Cost *startup_cost, Cost *total_cost)
static void postgresForeignAsyncConfigureWait(AsyncRequest *areq)
static void postgresGetForeignUpperPaths(PlannerInfo *root, UpperRelationKind stage, RelOptInfo *input_rel, RelOptInfo *output_rel, void *extra)
static void apply_server_options(PgFdwRelationInfo *fpinfo)
static void close_cursor(PGconn *conn, unsigned int cursor_number, PgFdwConnState *conn_state)
FdwPathPrivateIndex
Definition: postgres_fdw.c:284
@ FdwPathPrivateHasLimit
Definition: postgres_fdw.c:288
@ FdwPathPrivateHasFinalSort
Definition: postgres_fdw.c:286
static int get_batch_size_option(Relation rel)
static void postgresForeignAsyncNotify(AsyncRequest *areq)
EquivalenceMember * find_em_for_rel(PlannerInfo *root, EquivalenceClass *ec, RelOptInfo *rel)
static void add_foreign_final_paths(PlannerInfo *root, RelOptInfo *input_rel, RelOptInfo *final_rel, FinalPathExtraData *extra)
static void fetch_more_data_begin(AsyncRequest *areq)
static void execute_dml_stmt(ForeignScanState *node)
static TupleTableSlot * postgresIterateForeignScan(ForeignScanState *node)
static TupleTableSlot * postgresExecForeignDelete(EState *estate, ResultRelInfo *resultRelInfo, TupleTableSlot *slot, TupleTableSlot *planSlot)
static bool foreign_grouping_ok(PlannerInfo *root, RelOptInfo *grouped_rel, Node *havingQual)
FdwScanPrivateIndex
Definition: postgres_fdw.c:73
@ FdwScanPrivateRetrievedAttrs
Definition: postgres_fdw.c:77
@ FdwScanPrivateSelectSql
Definition: postgres_fdw.c:75
@ FdwScanPrivateFetchSize
Definition: postgres_fdw.c:79
@ FdwScanPrivateRelations
Definition: postgres_fdw.c:85
static bool ec_member_matches_foreign(PlannerInfo *root, RelOptInfo *rel, EquivalenceClass *ec, EquivalenceMember *em, void *arg)
FdwModifyPrivateIndex
Definition: postgres_fdw.c:101
@ FdwModifyPrivateLen
Definition: postgres_fdw.c:107
@ FdwModifyPrivateUpdateSql
Definition: postgres_fdw.c:103
@ FdwModifyPrivateTargetAttnums
Definition: postgres_fdw.c:105
@ FdwModifyPrivateRetrievedAttrs
Definition: postgres_fdw.c:111
@ FdwModifyPrivateHasReturning
Definition: postgres_fdw.c:109
static TupleTableSlot ** execute_foreign_modify(EState *estate, ResultRelInfo *resultRelInfo, CmdType operation, TupleTableSlot **slots, TupleTableSlot **planSlots, int *numSlots)
static PgFdwModifyState * create_foreign_modify(EState *estate, RangeTblEntry *rte, ResultRelInfo *resultRelInfo, CmdType operation, Plan *subplan, char *query, List *target_attrs, int values_end, bool has_returning, List *retrieved_attrs)
static void add_paths_with_pathkeys_for_rel(PlannerInfo *root, RelOptInfo *rel, Path *epq_path, List *restrictlist)
static bool postgresRecheckForeignScan(ForeignScanState *node, TupleTableSlot *slot)
static List * postgresImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid)
static void complete_pending_request(AsyncRequest *areq)
struct ConversionLocation ConversionLocation
struct PgFdwScanState PgFdwScanState
static bool postgresAnalyzeForeignTable(Relation relation, AcquireSampleRowsFunc *func, BlockNumber *totalpages)
static List * build_remote_returning(Index rtindex, Relation rel, List *returningList)
static TupleTableSlot * get_returning_data(ForeignScanState *node)
void process_pending_request(AsyncRequest *areq)
#define DEFAULT_FDW_TUPLE_COST
Definition: postgres_fdw.c:60
struct PgFdwDirectModifyState PgFdwDirectModifyState
static void postgresBeginForeignModify(ModifyTableState *mtstate, ResultRelInfo *resultRelInfo, List *fdw_private, int subplan_index, int eflags)
static void process_query_params(ExprContext *econtext, FmgrInfo *param_flinfo, List *param_exprs, const char **param_values)
static void postgresBeginForeignInsert(ModifyTableState *mtstate, ResultRelInfo *resultRelInfo)
static void init_returning_filter(PgFdwDirectModifyState *dmstate, List *fdw_scan_tlist, Index rtindex)
static TupleTableSlot * postgresIterateDirectModify(ForeignScanState *node)
static void postgresBeginDirectModify(ForeignScanState *node, int eflags)
static List * get_useful_pathkeys_for_relation(PlannerInfo *root, RelOptInfo *rel)
Definition: postgres_fdw.c:908
struct PgFdwAnalyzeState PgFdwAnalyzeState
Datum postgres_fdw_handler(PG_FUNCTION_ARGS)
Definition: postgres_fdw.c:554
static TupleTableSlot * postgresExecForeignInsert(EState *estate, ResultRelInfo *resultRelInfo, TupleTableSlot *slot, TupleTableSlot *planSlot)
static void apply_table_options(PgFdwRelationInfo *fpinfo)
static int postgresAcquireSampleRowsFunc(Relation relation, int elevel, HeapTuple *rows, int targrows, double *totalrows, double *totaldeadrows)
PG_FUNCTION_INFO_V1(postgres_fdw_handler)
static void postgresEndForeignInsert(EState *estate, ResultRelInfo *resultRelInfo)
EquivalenceMember * find_em_for_rel_target(PlannerInfo *root, EquivalenceClass *ec, RelOptInfo *rel)
static void postgresExplainDirectModify(ForeignScanState *node, ExplainState *es)
#define DEFAULT_FDW_STARTUP_COST
Definition: postgres_fdw.c:57
static List * get_useful_ecs_for_relation(PlannerInfo *root, RelOptInfo *rel)
Definition: postgres_fdw.c:812
static void finish_foreign_modify(PgFdwModifyState *fmstate)
bool is_shippable(Oid objectId, Oid classId, PgFdwRelationInfo *fpinfo)
Definition: shippable.c:162
PgFdwSamplingMethod
Definition: postgres_fdw.h:146
@ ANALYZE_SAMPLE_AUTO
Definition: postgres_fdw.h:148
@ ANALYZE_SAMPLE_OFF
Definition: postgres_fdw.h:147
@ ANALYZE_SAMPLE_BERNOULLI
Definition: postgres_fdw.h:151
@ ANALYZE_SAMPLE_SYSTEM
Definition: postgres_fdw.h:150
@ ANALYZE_SAMPLE_RANDOM
Definition: postgres_fdw.h:149
void get_agg_clause_costs(PlannerInfo *root, AggSplit aggsplit, AggClauseCosts *costs)
Definition: prepagg.c:560
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
MemoryContextSwitchTo(old_ctx)
tree ctl root
Definition: radixtree.h:1886
static struct subre * parse(struct vars *v, int stopper, int type, struct state *init, struct state *final)
Definition: regcomp.c:715
#define RelationGetRelid(relation)
Definition: rel.h:505
#define RelationGetDescr(relation)
Definition: rel.h:531
#define RelationGetRelationName(relation)
Definition: rel.h:539
ParamPathInfo * get_baserel_parampathinfo(PlannerInfo *root, RelOptInfo *baserel, Relids required_outer)
Definition: relnode.c:1545
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:414
RelOptInfo * find_join_rel(PlannerInfo *root, Relids relids)
Definition: relnode.c:527
List * extract_actual_clauses(List *restrictinfo_list, bool pseudoconstant)
Definition: restrictinfo.c:494
RestrictInfo * make_restrictinfo(PlannerInfo *root, Expr *clause, bool is_pushed_down, bool has_clone, bool is_clone, bool pseudoconstant, Index security_level, Relids required_relids, Relids incompatible_relids, Relids outer_relids)
Definition: restrictinfo.c:63
bool join_clause_is_movable_to(RestrictInfo *rinfo, RelOptInfo *baserel)
Definition: restrictinfo.c:584
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:12840
void reservoir_init_selection_state(ReservoirState rs, int n)
Definition: sampling.c:133
double sampler_random_fract(pg_prng_state *randstate)
Definition: sampling.c:241
double reservoir_get_next_S(ReservoirState rs, double t, int n)
Definition: sampling.c:147
double estimate_num_groups(PlannerInfo *root, List *groupExprs, double input_rows, List **pgset, EstimationInfo *estinfo)
Definition: selfuncs.c:3420
#define BTLessStrategyNumber
Definition: stratnum.h:29
PGconn * conn
Definition: streamutil.c:55
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41
void resetStringInfo(StringInfo str)
Definition: stringinfo.c:78
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:97
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:182
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:194
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
QualCost finalCost
Definition: pathnodes.h:61
QualCost transCost
Definition: pathnodes.h:60
Bitmapset * as_needrequest
Definition: execnodes.h:1463
struct WaitEventSet * as_eventset
Definition: execnodes.h:1464
List * appendplans
Definition: plannodes.h:270
struct PlanState * requestor
Definition: execnodes.h:611
TupleTableSlot * result
Definition: execnodes.h:616
bool request_complete
Definition: execnodes.h:615
bool callback_pending
Definition: execnodes.h:614
struct PlanState * requestee
Definition: execnodes.h:612
FmgrInfo * attinfuncs
Definition: funcapi.h:41
Oid * attioparams
Definition: funcapi.h:44
int32 * atttypmods
Definition: funcapi.h:47
AttrNumber cur_attno
Definition: postgres_fdw.c:307
ForeignScanState * fsstate
Definition: postgres_fdw.c:309
char * defname
Definition: parsenodes.h:817
MemoryContext es_query_cxt
Definition: execnodes.h:675
List * ec_opfamilies
Definition: pathnodes.h:1392
struct ErrorContextCallback * previous
Definition: elog.h:296
void(* callback)(void *arg)
Definition: elog.h:297
bool verbose
Definition: explain.h:48
List * rtable_names
Definition: explain.h:66
List * rtable
Definition: explain.h:65
EndForeignInsert_function EndForeignInsert
Definition: fdwapi.h:239
ReScanForeignScan_function ReScanForeignScan
Definition: fdwapi.h:214
BeginForeignInsert_function BeginForeignInsert
Definition: fdwapi.h:238
RecheckForeignScan_function RecheckForeignScan
Definition: fdwapi.h:249
AddForeignUpdateTargets_function AddForeignUpdateTargets
Definition: fdwapi.h:229
BeginForeignModify_function BeginForeignModify
Definition: fdwapi.h:231
EndForeignModify_function EndForeignModify
Definition: fdwapi.h:237
BeginDirectModify_function BeginDirectModify
Definition: fdwapi.h:242
PlanForeignModify_function PlanForeignModify
Definition: fdwapi.h:230
PlanDirectModify_function PlanDirectModify
Definition: fdwapi.h:241
ExecForeignInsert_function ExecForeignInsert
Definition: fdwapi.h:232
BeginForeignScan_function BeginForeignScan
Definition: fdwapi.h:212
ForeignAsyncRequest_function ForeignAsyncRequest
Definition: fdwapi.h:278
IterateDirectModify_function IterateDirectModify
Definition: fdwapi.h:243
ExecForeignUpdate_function ExecForeignUpdate
Definition: fdwapi.h:235
GetForeignJoinPaths_function GetForeignJoinPaths
Definition: fdwapi.h:223
ExecForeignBatchInsert_function ExecForeignBatchInsert
Definition: fdwapi.h:233
GetForeignPaths_function GetForeignPaths
Definition: fdwapi.h:210
GetForeignModifyBatchSize_function GetForeignModifyBatchSize
Definition: fdwapi.h:234
GetForeignRelSize_function GetForeignRelSize
Definition: fdwapi.h:209
ExplainForeignScan_function ExplainForeignScan
Definition: fdwapi.h:252
EndForeignScan_function EndForeignScan
Definition: fdwapi.h:215
AnalyzeForeignTable_function AnalyzeForeignTable
Definition: fdwapi.h:257
EndDirectModify_function EndDirectModify
Definition: fdwapi.h:244
ExplainForeignModify_function ExplainForeignModify
Definition: fdwapi.h:253
IsForeignPathAsyncCapable_function IsForeignPathAsyncCapable
Definition: fdwapi.h:277
IterateForeignScan_function IterateForeignScan
Definition: fdwapi.h:213
ForeignAsyncNotify_function ForeignAsyncNotify
Definition: fdwapi.h:280
ImportForeignSchema_function ImportForeignSchema
Definition: fdwapi.h:260
GetForeignPlan_function GetForeignPlan
Definition: fdwapi.h:211
ExecForeignDelete_function ExecForeignDelete
Definition: fdwapi.h:236
ExecForeignTruncate_function ExecForeignTruncate
Definition: fdwapi.h:263
ExplainDirectModify_function ExplainDirectModify
Definition: fdwapi.h:254
IsForeignRelUpdatable_function IsForeignRelUpdatable
Definition: fdwapi.h:240
GetForeignUpperPaths_function GetForeignUpperPaths
Definition: fdwapi.h:226
ForeignAsyncConfigureWait_function ForeignAsyncConfigureWait
Definition: fdwapi.h:279
Cardinality limit_tuples
Definition: pathnodes.h:3326
Definition: fmgr.h:57
List * fdw_private
Definition: pathnodes.h:1882
ResultRelInfo * resultRelInfo
Definition: execnodes.h:2079
ScanState ss
Definition: execnodes.h:2076
Oid checkAsUser
Definition: plannodes.h:713
CmdType operation
Definition: plannodes.h:711
List * fdw_exprs
Definition: plannodes.h:716
Bitmapset * fs_relids
Definition: plannodes.h:720
List * fdw_private
Definition: plannodes.h:717
Bitmapset * fs_base_relids
Definition: plannodes.h:721
Index resultRelation
Definition: plannodes.h:712
List * fdw_scan_tlist
Definition: plannodes.h:718
List * options
Definition: foreign.h:42
char * servername
Definition: foreign.h:39
Oid serverid
Definition: foreign.h:36
List * options
Definition: foreign.h:57
Oid serverid
Definition: foreign.h:56
PartitionwiseAggregateType patype
Definition: pathnodes.h:3310
ItemPointerData t_self
Definition: htup.h:65
HeapTupleHeader t_data
Definition: htup.h:68
ItemPointerData t_ctid
Definition: htup_details.h:161
double tuplecount
Definition: instrument.h:80
SpecialJoinInfo * sjinfo
Definition: pathnodes.h:3243
List * joinqual
Definition: plannodes.h:794
JoinType jointype
Definition: plannodes.h:792
Definition: pg_list.h:54
CmdType operation
Definition: execnodes.h:1367
ResultRelInfo * resultRelInfo
Definition: execnodes.h:1371
PlanState ps
Definition: execnodes.h:1366
Definition: nodes.h:129
Cardinality ppi_rows
Definition: pathnodes.h:1589
List * ppi_clauses
Definition: pathnodes.h:1590
Relids ppi_req_outer
Definition: pathnodes.h:1588
Oid pk_opfamily
Definition: pathnodes.h:1478
List * exprs
Definition: pathnodes.h:1542
QualCost cost
Definition: pathnodes.h:1548
List * pathkeys
Definition: pathnodes.h:1675
Cardinality rows
Definition: pathnodes.h:1669
Cost startup_cost
Definition: pathnodes.h:1671
int disabled_nodes
Definition: pathnodes.h:1670
Cost total_cost
Definition: pathnodes.h:1672
bool parallel_safe
Definition: pathnodes.h:1664
ReservoirStateData rstate
Definition: postgres_fdw.c:269
AttInMetadata * attinmeta
Definition: postgres_fdw.c:258
MemoryContext anl_cxt
Definition: postgres_fdw.c:272
HeapTuple * rows
Definition: postgres_fdw.c:262
MemoryContext temp_cxt
Definition: postgres_fdw.c:273
AsyncRequest * pendingAreq
Definition: postgres_fdw.h:139
PgFdwConnState * conn_state
Definition: postgres_fdw.c:232
MemoryContext temp_cxt
Definition: postgres_fdw.c:249
const char ** param_values
Definition: postgres_fdw.c:236
AttInMetadata * attinmeta
Definition: postgres_fdw.c:222
MemoryContext temp_cxt
Definition: postgres_fdw.c:209
AttInMetadata * attinmeta
Definition: postgres_fdw.c:184
FmgrInfo * p_flinfo
Definition: postgres_fdw.c:203
PgFdwConnState * conn_state
Definition: postgres_fdw.c:188
AttrNumber ctidAttno
Definition: postgres_fdw.c:201
struct PgFdwModifyState * aux_fmstate
Definition: postgres_fdw.c:212
List * retrieved_attrs
Definition: postgres_fdw.c:198
PathTarget * target
Definition: postgres_fdw.c:294
List * shippable_extensions
Definition: postgres_fdw.h:82
Relids lower_subquery_rels
Definition: postgres_fdw.h:120
RelOptInfo * outerrel
Definition: postgres_fdw.h:103
ForeignTable * table
Definition: postgres_fdw.h:86
Selectivity joinclause_sel
Definition: postgres_fdw.h:60
List * final_remote_exprs
Definition: postgres_fdw.h:47
UserMapping * user
Definition: postgres_fdw.h:88
Relids hidden_subquery_rels
Definition: postgres_fdw.h:122
Selectivity local_conds_sel
Definition: postgres_fdw.h:57
ForeignServer * server
Definition: postgres_fdw.h:87
QualCost local_conds_cost
Definition: postgres_fdw.h:56
Bitmapset * attrs_used
Definition: postgres_fdw.h:50
RelOptInfo * innerrel
Definition: postgres_fdw.h:104
UpperRelationKind stage
Definition: postgres_fdw.h:110
List * retrieved_attrs
Definition: postgres_fdw.c:147
FmgrInfo * param_flinfo
Definition: postgres_fdw.c:155
const char ** param_values
Definition: postgres_fdw.c:157
AttInMetadata * attinmeta
Definition: postgres_fdw.c:143
MemoryContext batch_cxt
Definition: postgres_fdw.c:172
unsigned int cursor_number
Definition: postgres_fdw.c:152
List * param_exprs
Definition: postgres_fdw.c:156
MemoryContext temp_cxt
Definition: postgres_fdw.c:173
TupleDesc tupdesc
Definition: postgres_fdw.c:142
PgFdwConnState * conn_state
Definition: postgres_fdw.c:151
HeapTuple * tuples
Definition: postgres_fdw.c:160
Relids ph_eval_at
Definition: pathnodes.h:3098
Instrumentation * instrument
Definition: execnodes.h:1138
ExecProcNodeMtd ExecProcNodeReal
Definition: execnodes.h:1135
Plan * plan
Definition: execnodes.h:1128
EState * state
Definition: execnodes.h:1130
Bitmapset * chgParam
Definition: execnodes.h:1160
ExprContext * ps_ExprContext
Definition: execnodes.h:1167
bool async_capable
Definition: execnodes.h:1170
List * qual
Definition: plannodes.h:154
List * targetlist
Definition: plannodes.h:153
Cost per_tuple
Definition: pathnodes.h:48
Cost startup
Definition: pathnodes.h:47
List * groupClause
Definition: parsenodes.h:202
List * groupingSets
Definition: parsenodes.h:205
RTEKind rtekind
Definition: parsenodes.h:1047
char * relname
Definition: primnodes.h:82
List * baserestrictinfo
Definition: pathnodes.h:985
List * joininfo
Definition: pathnodes.h:991
Relids relids
Definition: pathnodes.h:871
struct PathTarget * reltarget
Definition: pathnodes.h:893
Index relid
Definition: pathnodes.h:918
Cardinality tuples
Definition: pathnodes.h:949
Relids top_parent_relids
Definition: pathnodes.h:1009
BlockNumber pages
Definition: pathnodes.h:948
Relids lateral_relids
Definition: pathnodes.h:913
List * pathlist
Definition: pathnodes.h:898
RelOptKind reloptkind
Definition: pathnodes.h:865
Relids lateral_referencers
Definition: pathnodes.h:942
QualCost baserestrictcost
Definition: pathnodes.h:987
Oid userid
Definition: pathnodes.h:966
bool has_eclass_joins
Definition: pathnodes.h:993
Cardinality rows
Definition: pathnodes.h:877
TriggerDesc * trigdesc
Definition: rel.h:117
Form_pg_class rd_rel
Definition: rel.h:111
pg_prng_state randstate
Definition: sampling.h:49
Expr * clause
Definition: pathnodes.h:2574
struct ResultRelInfo * ri_RootResultRelInfo
Definition: execnodes.h:590
Relation ri_RelationDesc
Definition: execnodes.h:459
List * ri_WithCheckOptions
Definition: execnodes.h:525
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:492
Index ri_RangeTableIndex
Definition: execnodes.h:456
void * ri_FdwState
Definition: execnodes.h:512
ProjectionInfo * ri_projectReturning
Definition: execnodes.h:547
List * ri_returningList
Definition: execnodes.h:544
bool ri_usesFdwDirectModify
Definition: execnodes.h:515
int ri_BatchSize
Definition: execnodes.h:520
Relation ss_currentRelation
Definition: execnodes.h:1576
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1578
PlanState ps
Definition: execnodes.h:1575
Index scanrelid
Definition: plannodes.h:390
Expr * expr
Definition: primnodes.h:2190
Index ressortgroupref
Definition: primnodes.h:2196
bool trig_insert_after_row
Definition: reltrigger.h:57
bool trig_update_before_row
Definition: reltrigger.h:61
bool trig_insert_before_row
Definition: reltrigger.h:56
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:123
bool * tts_isnull
Definition: tuptable.h:127
Datum * tts_values
Definition: tuptable.h:125
Definition: primnodes.h:248
AttrNumber varattno
Definition: primnodes.h:260
int varno
Definition: primnodes.h:255
Definition: regguts.h:323
Definition: regcomp.c:281
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
#define SelfItemPointerAttributeNumber
Definition: sysattr.h:21
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
Datum tidin(PG_FUNCTION_ARGS)
Definition: tid.c:52
List * get_sortgrouplist_exprs(List *sgClauses, List *targetList)
Definition: tlist.c:392
PathTarget * copy_pathtarget(PathTarget *src)
Definition: tlist.c:657
SortGroupClause * get_sortgroupref_clause_noerr(Index sortref, List *clauses)
Definition: tlist.c:443
bool grouping_is_sortable(List *groupClause)
Definition: tlist.c:540
List * add_to_flat_tlist(List *tlist, List *exprs)
Definition: tlist.c:132
void add_new_columns_to_pathtarget(PathTarget *target, List *exprs)
Definition: tlist.c:752
TargetEntry * tlist_member(Expr *node, List *targetlist)
Definition: tlist.c:79
#define InvalidTransactionId
Definition: transam.h:31
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:133
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:454
static TupleTableSlot * ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
Definition: tuptable.h:509
static Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition: tuptable.h:395
#define TupIsNull(slot)
Definition: tuptable.h:306
static void slot_getallattrs(TupleTableSlot *slot)
Definition: tuptable.h:368
Boolean * makeBoolean(bool val)
Definition: value.c:49
String * makeString(char *str)
Definition: value.c:63
Integer * makeInteger(int i)
Definition: value.c:23
#define boolVal(v)
Definition: value.h:81
#define intVal(v)
Definition: value.h:79
#define strVal(v)
Definition: value.h:82
List * pull_var_clause(Node *node, int flags)
Definition: var.c:612
void pull_varattnos(Node *node, Index varno, Bitmapset **varattnos)
Definition: var.c:296