LCOV - differential code coverage report
Current view: top level - contrib/postgres_fdw - postgres_fdw.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 92.3 % 2312 2135 39 38 84 16 46 1191 67 831 112 1249 3 17
Current Date: 2023-04-08 17:13:01 Functions: 98.9 % 88 87 1 74 4 9 1 75
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (60,120] days: 57.0 % 86 49 37 49 1
Legend: Lines: hit not hit (120,180] days: 100.0 % 11 11 1 9 1
(180,240] days: 100.0 % 15 15 7 3 5 15
(240..) days: 93.6 % 2200 2060 2 38 84 16 46 1183 6 825 104 1161
Function coverage date bins:
(60,120] days: 50.0 % 2 1 1 1
(240..) days: 54.1 % 159 86 1 74 3 9 1 71

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

Generated by: LCOV version v1.16-55-g56c0a2a