PostgreSQL Source Code  git master
postgres_fdw.h File Reference
#include "foreign/foreign.h"
#include "lib/stringinfo.h"
#include "libpq-fe.h"
#include "nodes/execnodes.h"
#include "nodes/pathnodes.h"
#include "utils/relcache.h"
Include dependency graph for postgres_fdw.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  PgFdwRelationInfo
 
struct  PgFdwConnState
 

Typedefs

typedef struct PgFdwRelationInfo PgFdwRelationInfo
 
typedef struct PgFdwConnState PgFdwConnState
 

Functions

int set_transmission_modes (void)
 
void reset_transmission_modes (int nestlevel)
 
void process_pending_request (AsyncRequest *areq)
 
PGconnGetConnection (UserMapping *user, bool will_prep_stmt, PgFdwConnState **state)
 
void ReleaseConnection (PGconn *conn)
 
unsigned int GetCursorNumber (PGconn *conn)
 
unsigned int GetPrepStmtNumber (PGconn *conn)
 
void do_sql_command (PGconn *conn, const char *sql)
 
PGresultpgfdw_get_result (PGconn *conn, const char *query)
 
PGresultpgfdw_exec_query (PGconn *conn, const char *query, PgFdwConnState *state)
 
void pgfdw_report_error (int elevel, PGresult *res, PGconn *conn, bool clear, const char *sql)
 
int ExtractConnectionOptions (List *defelems, const char **keywords, const char **values)
 
ListExtractExtensionList (const char *extensionsString, bool warnOnMissing)
 
void classifyConditions (PlannerInfo *root, RelOptInfo *baserel, List *input_conds, List **remote_conds, List **local_conds)
 
bool is_foreign_expr (PlannerInfo *root, RelOptInfo *baserel, Expr *expr)
 
bool is_foreign_param (PlannerInfo *root, RelOptInfo *baserel, Expr *expr)
 
void deparseInsertSql (StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, List *targetAttrs, bool doNothing, List *withCheckOptionList, List *returningList, List **retrieved_attrs, int *values_end_len)
 
void rebuildInsertSql (StringInfo buf, Relation rel, char *orig_query, List *target_attrs, int values_end_len, int num_params, int num_rows)
 
void deparseUpdateSql (StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, List *targetAttrs, List *withCheckOptionList, List *returningList, List **retrieved_attrs)
 
void deparseDirectUpdateSql (StringInfo buf, PlannerInfo *root, Index rtindex, Relation rel, RelOptInfo *foreignrel, List *targetlist, List *targetAttrs, List *remote_conds, List **params_list, List *returningList, List **retrieved_attrs)
 
void deparseDeleteSql (StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, List *returningList, List **retrieved_attrs)
 
void deparseDirectDeleteSql (StringInfo buf, PlannerInfo *root, Index rtindex, Relation rel, RelOptInfo *foreignrel, List *remote_conds, List **params_list, List *returningList, List **retrieved_attrs)
 
void deparseAnalyzeSizeSql (StringInfo buf, Relation rel)
 
void deparseAnalyzeSql (StringInfo buf, Relation rel, List **retrieved_attrs)
 
void deparseTruncateSql (StringInfo buf, List *rels, DropBehavior behavior, bool restart_seqs)
 
void deparseStringLiteral (StringInfo buf, const char *val)
 
Exprfind_em_expr_for_rel (EquivalenceClass *ec, RelOptInfo *rel)
 
Exprfind_em_expr_for_input_target (PlannerInfo *root, EquivalenceClass *ec, PathTarget *target)
 
Listbuild_tlist_to_deparse (RelOptInfo *foreignrel)
 
void deparseSelectStmtForRel (StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel, List *tlist, List *remote_conds, List *pathkeys, bool has_final_sort, bool has_limit, bool is_subquery, List **retrieved_attrs, List **params_list)
 
const char * get_jointype_name (JoinType jointype)
 
bool is_builtin (Oid objectId)
 
bool is_shippable (Oid objectId, Oid classId, PgFdwRelationInfo *fpinfo)
 

Variables

char * pgfdw_application_name
 

Typedef Documentation

◆ PgFdwConnState

◆ PgFdwRelationInfo

Function Documentation

◆ build_tlist_to_deparse()

List* build_tlist_to_deparse ( RelOptInfo foreignrel)

Definition at line 1071 of file deparse.c.

References add_to_flat_tlist(), RestrictInfo::clause, PathTarget::exprs, RelOptInfo::fdw_private, PgFdwRelationInfo::grouped_tlist, IS_UPPER_REL, lfirst_node, PgFdwRelationInfo::local_conds, NIL, pull_var_clause(), PVC_RECURSE_PLACEHOLDERS, and RelOptInfo::reltarget.

Referenced by estimate_path_cost_size(), and postgresGetForeignPlan().

1072 {
1073  List *tlist = NIL;
1074  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
1075  ListCell *lc;
1076 
1077  /*
1078  * For an upper relation, we have already built the target list while
1079  * checking shippability, so just return that.
1080  */
1081  if (IS_UPPER_REL(foreignrel))
1082  return fpinfo->grouped_tlist;
1083 
1084  /*
1085  * We require columns specified in foreignrel->reltarget->exprs and those
1086  * required for evaluating the local conditions.
1087  */
1088  tlist = add_to_flat_tlist(tlist,
1089  pull_var_clause((Node *) foreignrel->reltarget->exprs,
1091  foreach(lc, fpinfo->local_conds)
1092  {
1093  RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
1094 
1095  tlist = add_to_flat_tlist(tlist,
1096  pull_var_clause((Node *) rinfo->clause,
1098  }
1099 
1100  return tlist;
1101 }
#define NIL
Definition: pg_list.h:65
#define PVC_RECURSE_PLACEHOLDERS
Definition: optimizer.h:192
Definition: nodes.h:536
List * pull_var_clause(Node *node, int flags)
Definition: var.c:597
#define lfirst_node(type, lc)
Definition: pg_list.h:172
Expr * clause
Definition: pathnodes.h:2056
List * exprs
Definition: pathnodes.h:1110
void * fdw_private
Definition: pathnodes.h:737
List * add_to_flat_tlist(List *tlist, List *exprs)
Definition: tlist.c:121
#define IS_UPPER_REL(rel)
Definition: pathnodes.h:664
Definition: pg_list.h:50
struct PathTarget * reltarget
Definition: pathnodes.h:692

◆ classifyConditions()

void classifyConditions ( PlannerInfo root,
RelOptInfo baserel,
List input_conds,
List **  remote_conds,
List **  local_conds 
)

Definition at line 207 of file deparse.c.

References RestrictInfo::clause, is_foreign_expr(), lappend(), lfirst_node, and NIL.

Referenced by estimate_path_cost_size(), and postgresGetForeignRelSize().

212 {
213  ListCell *lc;
214 
215  *remote_conds = NIL;
216  *local_conds = NIL;
217 
218  foreach(lc, input_conds)
219  {
221 
222  if (is_foreign_expr(root, baserel, ri->clause))
223  *remote_conds = lappend(*remote_conds, ri);
224  else
225  *local_conds = lappend(*local_conds, ri);
226  }
227 }
#define NIL
Definition: pg_list.h:65
#define lfirst_node(type, lc)
Definition: pg_list.h:172
List * lappend(List *list, void *datum)
Definition: list.c:336
Expr * clause
Definition: pathnodes.h:2056
bool is_foreign_expr(PlannerInfo *root, RelOptInfo *baserel, Expr *expr)
Definition: deparse.c:233

◆ deparseAnalyzeSizeSql()

void deparseAnalyzeSizeSql ( StringInfo  buf,
Relation  rel 
)

Definition at line 2256 of file deparse.c.

References appendStringInfo(), appendStringInfoString(), StringInfoData::data, deparseRelation(), deparseStringLiteral(), initStringInfo(), and relname.

Referenced by postgresAnalyzeForeignTable().

2257 {
2259 
2260  /* We'll need the remote relation name as a literal. */
2261  initStringInfo(&relname);
2262  deparseRelation(&relname, rel);
2263 
2264  appendStringInfoString(buf, "SELECT pg_catalog.pg_relation_size(");
2265  deparseStringLiteral(buf, relname.data);
2266  appendStringInfo(buf, "::pg_catalog.regclass) / %d", BLCKSZ);
2267 }
NameData relname
Definition: pg_class.h:38
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
void deparseStringLiteral(StringInfo buf, const char *val)
Definition: deparse.c:2537
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2497

◆ deparseAnalyzeSql()

void deparseAnalyzeSql ( StringInfo  buf,
Relation  rel,
List **  retrieved_attrs 
)

Definition at line 2276 of file deparse.c.

References appendStringInfoString(), attname, defGetString(), DefElem::defname, deparseRelation(), GetForeignColumnOptions(), i, lappend_int(), lfirst, NameStr, TupleDescData::natts, NIL, options, quote_identifier(), RelationGetDescr, RelationGetRelid, and TupleDescAttr.

Referenced by postgresAcquireSampleRowsFunc().

2277 {
2278  Oid relid = RelationGetRelid(rel);
2279  TupleDesc tupdesc = RelationGetDescr(rel);
2280  int i;
2281  char *colname;
2282  List *options;
2283  ListCell *lc;
2284  bool first = true;
2285 
2286  *retrieved_attrs = NIL;
2287 
2288  appendStringInfoString(buf, "SELECT ");
2289  for (i = 0; i < tupdesc->natts; i++)
2290  {
2291  /* Ignore dropped columns. */
2292  if (TupleDescAttr(tupdesc, i)->attisdropped)
2293  continue;
2294 
2295  if (!first)
2296  appendStringInfoString(buf, ", ");
2297  first = false;
2298 
2299  /* Use attribute name or column_name option. */
2300  colname = NameStr(TupleDescAttr(tupdesc, i)->attname);
2301  options = GetForeignColumnOptions(relid, i + 1);
2302 
2303  foreach(lc, options)
2304  {
2305  DefElem *def = (DefElem *) lfirst(lc);
2306 
2307  if (strcmp(def->defname, "column_name") == 0)
2308  {
2309  colname = defGetString(def);
2310  break;
2311  }
2312  }
2313 
2315 
2316  *retrieved_attrs = lappend_int(*retrieved_attrs, i + 1);
2317  }
2318 
2319  /* Don't generate bad syntax for zero-column relation. */
2320  if (first)
2321  appendStringInfoString(buf, "NULL");
2322 
2323  /*
2324  * Construct FROM clause
2325  */
2326  appendStringInfoString(buf, " FROM ");
2327  deparseRelation(buf, rel);
2328 }
#define NIL
Definition: pg_list.h:65
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:11374
#define RelationGetDescr(relation)
Definition: rel.h:503
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
unsigned int Oid
Definition: postgres_ext.h:31
List * GetForeignColumnOptions(Oid relid, AttrNumber attnum)
Definition: foreign.c:286
NameData attname
Definition: pg_attribute.h:41
char * defGetString(DefElem *def)
Definition: define.c:49
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
List * lappend_int(List *list, int datum)
Definition: list.c:354
static char ** options
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2497
#define lfirst(lc)
Definition: pg_list.h:169
int i
#define NameStr(name)
Definition: c.h:681
char * defname
Definition: parsenodes.h:758
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:477

◆ deparseDeleteSql()

void deparseDeleteSql ( StringInfo  buf,
RangeTblEntry rte,
Index  rtindex,
Relation  rel,
List returningList,
List **  retrieved_attrs 
)

Definition at line 2119 of file deparse.c.

References appendStringInfoString(), deparseRelation(), deparseReturningList(), NIL, TriggerDesc::trig_delete_after_row, and RelationData::trigdesc.

Referenced by postgresPlanForeignModify().

2123 {
2124  appendStringInfoString(buf, "DELETE FROM ");
2125  deparseRelation(buf, rel);
2126  appendStringInfoString(buf, " WHERE ctid = $1");
2127 
2128  deparseReturningList(buf, rte, rtindex, rel,
2129  rel->trigdesc && rel->trigdesc->trig_delete_after_row,
2130  NIL, returningList, retrieved_attrs);
2131 }
#define NIL
Definition: pg_list.h:65
static void deparseReturningList(StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, bool trig_after_row, List *withCheckOptionList, List *returningList, List **retrieved_attrs)
Definition: deparse.c:2199
TriggerDesc * trigdesc
Definition: rel.h:115
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
bool trig_delete_after_row
Definition: reltrigger.h:67
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2497

◆ deparseDirectDeleteSql()

void deparseDirectDeleteSql ( StringInfo  buf,
PlannerInfo root,
Index  rtindex,
Relation  rel,
RelOptInfo foreignrel,
List remote_conds,
List **  params_list,
List returningList,
List **  retrieved_attrs 
)

Definition at line 2148 of file deparse.c.

References appendConditions(), appendStringInfo(), appendStringInfoString(), buf, deparse_expr_cxt::buf, deparseExplicitTargetList(), deparseFromExprForRel(), deparseRelation(), deparseReturningList(), foreign_glob_cxt::foreignrel, deparse_expr_cxt::foreignrel, list_concat(), NIL, deparse_expr_cxt::params_list, planner_rt_fetch, REL_ALIAS_PREFIX, RELOPT_JOINREL, RelOptInfo::reloptkind, foreign_glob_cxt::root, deparse_expr_cxt::root, and deparse_expr_cxt::scanrel.

Referenced by postgresPlanDirectModify().

2155 {
2156  deparse_expr_cxt context;
2157 
2158  /* Set up context struct for recursion */
2159  context.root = root;
2160  context.foreignrel = foreignrel;
2161  context.scanrel = foreignrel;
2162  context.buf = buf;
2163  context.params_list = params_list;
2164 
2165  appendStringInfoString(buf, "DELETE FROM ");
2166  deparseRelation(buf, rel);
2167  if (foreignrel->reloptkind == RELOPT_JOINREL)
2168  appendStringInfo(buf, " %s%d", REL_ALIAS_PREFIX, rtindex);
2169 
2170  if (foreignrel->reloptkind == RELOPT_JOINREL)
2171  {
2172  List *ignore_conds = NIL;
2173 
2174  appendStringInfoString(buf, " USING ");
2175  deparseFromExprForRel(buf, root, foreignrel, true, rtindex,
2176  &ignore_conds, params_list);
2177  remote_conds = list_concat(remote_conds, ignore_conds);
2178  }
2179 
2180  if (remote_conds)
2181  {
2182  appendStringInfoString(buf, " WHERE ");
2183  appendConditions(remote_conds, &context);
2184  }
2185 
2186  if (foreignrel->reloptkind == RELOPT_JOINREL)
2187  deparseExplicitTargetList(returningList, true, retrieved_attrs,
2188  &context);
2189  else
2190  deparseReturningList(buf, planner_rt_fetch(rtindex, root),
2191  rtindex, rel, false,
2192  NIL, returningList, retrieved_attrs);
2193 }
#define NIL
Definition: pg_list.h:65
RelOptKind reloptkind
Definition: pathnodes.h:678
List ** params_list
Definition: deparse.c:103
List * list_concat(List *list1, const List *list2)
Definition: list.c:530
static void deparseReturningList(StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, bool trig_after_row, List *withCheckOptionList, List *returningList, List **retrieved_attrs)
Definition: deparse.c:2199
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define planner_rt_fetch(rti, root)
Definition: pathnodes.h:388
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:68
#define REL_ALIAS_PREFIX
Definition: deparse.c:106
static void deparseExplicitTargetList(List *tlist, bool is_returning, List **retrieved_attrs, deparse_expr_cxt *context)
Definition: deparse.c:1539
static void appendConditions(List *exprs, deparse_expr_cxt *context)
Definition: deparse.c:1468
StringInfo buf
Definition: deparse.c:102
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2497
PlannerInfo * root
Definition: deparse.c:97
static void deparseFromExprForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel, bool use_alias, Index ignore_rel, List **ignore_conds, List **params_list)
Definition: deparse.c:1616
RelOptInfo * scanrel
Definition: deparse.c:99
Definition: pg_list.h:50
RelOptInfo * foreignrel
Definition: deparse.c:98

◆ deparseDirectUpdateSql()

void deparseDirectUpdateSql ( StringInfo  buf,
PlannerInfo root,
Index  rtindex,
Relation  rel,
RelOptInfo foreignrel,
List targetlist,
List targetAttrs,
List remote_conds,
List **  params_list,
List returningList,
List **  retrieved_attrs 
)

Definition at line 2034 of file deparse.c.

References appendConditions(), appendStringInfo(), appendStringInfoString(), Assert, attnum, buf, deparse_expr_cxt::buf, deparseColumnRef(), deparseExplicitTargetList(), deparseExpr(), deparseFromExprForRel(), deparseRelation(), deparseReturningList(), TargetEntry::expr, forboth, foreign_glob_cxt::foreignrel, deparse_expr_cxt::foreignrel, lfirst_int, lfirst_node, list_concat(), NIL, deparse_expr_cxt::params_list, planner_rt_fetch, REL_ALIAS_PREFIX, RELOPT_JOINREL, RelOptInfo::reloptkind, reset_transmission_modes(), TargetEntry::resjunk, foreign_glob_cxt::root, deparse_expr_cxt::root, deparse_expr_cxt::scanrel, and set_transmission_modes().

Referenced by postgresPlanDirectModify().

2043 {
2044  deparse_expr_cxt context;
2045  int nestlevel;
2046  bool first;
2047  RangeTblEntry *rte = planner_rt_fetch(rtindex, root);
2048  ListCell *lc,
2049  *lc2;
2050 
2051  /* Set up context struct for recursion */
2052  context.root = root;
2053  context.foreignrel = foreignrel;
2054  context.scanrel = foreignrel;
2055  context.buf = buf;
2056  context.params_list = params_list;
2057 
2058  appendStringInfoString(buf, "UPDATE ");
2059  deparseRelation(buf, rel);
2060  if (foreignrel->reloptkind == RELOPT_JOINREL)
2061  appendStringInfo(buf, " %s%d", REL_ALIAS_PREFIX, rtindex);
2062  appendStringInfoString(buf, " SET ");
2063 
2064  /* Make sure any constants in the exprs are printed portably */
2065  nestlevel = set_transmission_modes();
2066 
2067  first = true;
2068  forboth(lc, targetlist, lc2, targetAttrs)
2069  {
2070  TargetEntry *tle = lfirst_node(TargetEntry, lc);
2071  int attnum = lfirst_int(lc2);
2072 
2073  /* update's new-value expressions shouldn't be resjunk */
2074  Assert(!tle->resjunk);
2075 
2076  if (!first)
2077  appendStringInfoString(buf, ", ");
2078  first = false;
2079 
2080  deparseColumnRef(buf, rtindex, attnum, rte, false);
2081  appendStringInfoString(buf, " = ");
2082  deparseExpr((Expr *) tle->expr, &context);
2083  }
2084 
2085  reset_transmission_modes(nestlevel);
2086 
2087  if (foreignrel->reloptkind == RELOPT_JOINREL)
2088  {
2089  List *ignore_conds = NIL;
2090 
2091  appendStringInfoString(buf, " FROM ");
2092  deparseFromExprForRel(buf, root, foreignrel, true, rtindex,
2093  &ignore_conds, params_list);
2094  remote_conds = list_concat(remote_conds, ignore_conds);
2095  }
2096 
2097  if (remote_conds)
2098  {
2099  appendStringInfoString(buf, " WHERE ");
2100  appendConditions(remote_conds, &context);
2101  }
2102 
2103  if (foreignrel->reloptkind == RELOPT_JOINREL)
2104  deparseExplicitTargetList(returningList, true, retrieved_attrs,
2105  &context);
2106  else
2107  deparseReturningList(buf, rte, rtindex, rel, false,
2108  NIL, returningList, retrieved_attrs);
2109 }
#define NIL
Definition: pg_list.h:65
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:446
RelOptKind reloptkind
Definition: pathnodes.h:678
List ** params_list
Definition: deparse.c:103
int set_transmission_modes(void)
List * list_concat(List *list1, const List *list2)
Definition: list.c:530
static void deparseReturningList(StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, bool trig_after_row, List *withCheckOptionList, List *returningList, List **retrieved_attrs)
Definition: deparse.c:2199
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
bool resjunk
Definition: primnodes.h:1462
#define lfirst_int(lc)
Definition: pg_list.h:170
#define planner_rt_fetch(rti, root)
Definition: pathnodes.h:388
#define lfirst_node(type, lc)
Definition: pg_list.h:172
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:68
#define REL_ALIAS_PREFIX
Definition: deparse.c:106
static void deparseExplicitTargetList(List *tlist, bool is_returning, List **retrieved_attrs, deparse_expr_cxt *context)
Definition: deparse.c:1539
static void appendConditions(List *exprs, deparse_expr_cxt *context)
Definition: deparse.c:1468
StringInfo buf
Definition: deparse.c:102
int16 attnum
Definition: pg_attribute.h:83
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2497
PlannerInfo * root
Definition: deparse.c:97
#define Assert(condition)
Definition: c.h:804
Expr * expr
Definition: primnodes.h:1455
void reset_transmission_modes(int nestlevel)
static void deparseExpr(Expr *expr, deparse_expr_cxt *context)
Definition: deparse.c:2572
static void deparseFromExprForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel, bool use_alias, Index ignore_rel, List **ignore_conds, List **params_list)
Definition: deparse.c:1616
RelOptInfo * scanrel
Definition: deparse.c:99
Definition: pg_list.h:50
RelOptInfo * foreignrel
Definition: deparse.c:98
static void deparseColumnRef(StringInfo buf, int varno, int varattno, RangeTblEntry *rte, bool qualify_col)
Definition: deparse.c:2369

◆ deparseInsertSql()

void deparseInsertSql ( StringInfo  buf,
RangeTblEntry rte,
Index  rtindex,
Relation  rel,
List targetAttrs,
bool  doNothing,
List withCheckOptionList,
List returningList,
List **  retrieved_attrs,
int *  values_end_len 
)

Definition at line 1841 of file deparse.c.

References appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), attnum, deparseColumnRef(), deparseRelation(), deparseReturningList(), StringInfoData::len, lfirst_int, RelationGetDescr, TriggerDesc::trig_insert_after_row, RelationData::trigdesc, and TupleDescAttr.

Referenced by postgresBeginForeignInsert(), and postgresPlanForeignModify().

1846 {
1847  TupleDesc tupdesc = RelationGetDescr(rel);
1848  AttrNumber pindex;
1849  bool first;
1850  ListCell *lc;
1851 
1852  appendStringInfoString(buf, "INSERT INTO ");
1853  deparseRelation(buf, rel);
1854 
1855  if (targetAttrs)
1856  {
1857  appendStringInfoChar(buf, '(');
1858 
1859  first = true;
1860  foreach(lc, targetAttrs)
1861  {
1862  int attnum = lfirst_int(lc);
1863 
1864  if (!first)
1865  appendStringInfoString(buf, ", ");
1866  first = false;
1867 
1868  deparseColumnRef(buf, rtindex, attnum, rte, false);
1869  }
1870 
1871  appendStringInfoString(buf, ") VALUES (");
1872 
1873  pindex = 1;
1874  first = true;
1875  foreach(lc, targetAttrs)
1876  {
1877  int attnum = lfirst_int(lc);
1878  Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1);
1879 
1880  if (!first)
1881  appendStringInfoString(buf, ", ");
1882  first = false;
1883 
1884  if (attr->attgenerated)
1885  appendStringInfoString(buf, "DEFAULT");
1886  else
1887  {
1888  appendStringInfo(buf, "$%d", pindex);
1889  pindex++;
1890  }
1891  }
1892 
1893  appendStringInfoChar(buf, ')');
1894  }
1895  else
1896  appendStringInfoString(buf, " DEFAULT VALUES");
1897  *values_end_len = buf->len;
1898 
1899  if (doNothing)
1900  appendStringInfoString(buf, " ON CONFLICT DO NOTHING");
1901 
1902  deparseReturningList(buf, rte, rtindex, rel,
1903  rel->trigdesc && rel->trigdesc->trig_insert_after_row,
1904  withCheckOptionList, returningList, retrieved_attrs);
1905 }
#define RelationGetDescr(relation)
Definition: rel.h:503
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
static void deparseReturningList(StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, bool trig_after_row, List *withCheckOptionList, List *returningList, List **retrieved_attrs)
Definition: deparse.c:2199
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define lfirst_int(lc)
Definition: pg_list.h:170
TriggerDesc * trigdesc
Definition: rel.h:115
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:207
bool trig_insert_after_row
Definition: reltrigger.h:57
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
int16 attnum
Definition: pg_attribute.h:83
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2497
int16 AttrNumber
Definition: attnum.h:21
static void deparseColumnRef(StringInfo buf, int varno, int varattno, RangeTblEntry *rte, bool qualify_col)
Definition: deparse.c:2369

◆ deparseSelectStmtForRel()

void deparseSelectStmtForRel ( StringInfo  buf,
PlannerInfo root,
RelOptInfo foreignrel,
List tlist,
List remote_conds,
List pathkeys,
bool  has_final_sort,
bool  has_limit,
bool  is_subquery,
List **  retrieved_attrs,
List **  params_list 
)

Definition at line 1128 of file deparse.c.

References appendConditions(), appendGroupByClause(), appendLimitClause(), appendOrderByClause(), appendStringInfoString(), Assert, buf, deparse_expr_cxt::buf, deparseFromExpr(), deparseLockingClause(), deparseSelectSql(), RelOptInfo::fdw_private, deparse_expr_cxt::foreignrel, IS_JOIN_REL, IS_SIMPLE_REL, IS_UPPER_REL, PgFdwRelationInfo::outerrel, deparse_expr_cxt::params_list, PgFdwRelationInfo::remote_conds, foreign_glob_cxt::root, deparse_expr_cxt::root, and deparse_expr_cxt::scanrel.

Referenced by deparseRangeTblRef(), estimate_path_cost_size(), and postgresGetForeignPlan().

1132 {
1133  deparse_expr_cxt context;
1134  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) rel->fdw_private;
1135  List *quals;
1136 
1137  /*
1138  * We handle relations for foreign tables, joins between those and upper
1139  * relations.
1140  */
1141  Assert(IS_JOIN_REL(rel) || IS_SIMPLE_REL(rel) || IS_UPPER_REL(rel));
1142 
1143  /* Fill portions of context common to upper, join and base relation */
1144  context.buf = buf;
1145  context.root = root;
1146  context.foreignrel = rel;
1147  context.scanrel = IS_UPPER_REL(rel) ? fpinfo->outerrel : rel;
1148  context.params_list = params_list;
1149 
1150  /* Construct SELECT clause */
1151  deparseSelectSql(tlist, is_subquery, retrieved_attrs, &context);
1152 
1153  /*
1154  * For upper relations, the WHERE clause is built from the remote
1155  * conditions of the underlying scan relation; otherwise, we can use the
1156  * supplied list of remote conditions directly.
1157  */
1158  if (IS_UPPER_REL(rel))
1159  {
1160  PgFdwRelationInfo *ofpinfo;
1161 
1162  ofpinfo = (PgFdwRelationInfo *) fpinfo->outerrel->fdw_private;
1163  quals = ofpinfo->remote_conds;
1164  }
1165  else
1166  quals = remote_conds;
1167 
1168  /* Construct FROM and WHERE clauses */
1169  deparseFromExpr(quals, &context);
1170 
1171  if (IS_UPPER_REL(rel))
1172  {
1173  /* Append GROUP BY clause */
1174  appendGroupByClause(tlist, &context);
1175 
1176  /* Append HAVING clause */
1177  if (remote_conds)
1178  {
1179  appendStringInfoString(buf, " HAVING ");
1180  appendConditions(remote_conds, &context);
1181  }
1182  }
1183 
1184  /* Add ORDER BY clause if we found any useful pathkeys */
1185  if (pathkeys)
1186  appendOrderByClause(pathkeys, has_final_sort, &context);
1187 
1188  /* Add LIMIT clause if necessary */
1189  if (has_limit)
1190  appendLimitClause(&context);
1191 
1192  /* Add any necessary FOR UPDATE/SHARE. */
1193  deparseLockingClause(&context);
1194 }
static void appendGroupByClause(List *tlist, deparse_expr_cxt *context)
Definition: deparse.c:3436
List ** params_list
Definition: deparse.c:103
#define IS_JOIN_REL(rel)
Definition: pathnodes.h:659
static void appendLimitClause(deparse_expr_cxt *context)
Definition: deparse.c:3527
RelOptInfo * outerrel
Definition: postgres_fdw.h:102
#define IS_SIMPLE_REL(rel)
Definition: pathnodes.h:654
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:68
static void appendOrderByClause(List *pathkeys, bool has_final_sort, deparse_expr_cxt *context)
Definition: deparse.c:3473
static void deparseSelectSql(List *tlist, bool is_subquery, List **retrieved_attrs, deparse_expr_cxt *context)
Definition: deparse.c:1210
static void appendConditions(List *exprs, deparse_expr_cxt *context)
Definition: deparse.c:1468
StringInfo buf
Definition: deparse.c:102
void * fdw_private
Definition: pathnodes.h:737
PlannerInfo * root
Definition: deparse.c:97
#define Assert(condition)
Definition: c.h:804
static void deparseFromExpr(List *quals, deparse_expr_cxt *context)
Definition: deparse.c:1268
#define IS_UPPER_REL(rel)
Definition: pathnodes.h:664
static void deparseLockingClause(deparse_expr_cxt *context)
Definition: deparse.c:1378
RelOptInfo * scanrel
Definition: deparse.c:99
Definition: pg_list.h:50
RelOptInfo * foreignrel
Definition: deparse.c:98

◆ deparseStringLiteral()

void deparseStringLiteral ( StringInfo  buf,
const char *  val 
)

Definition at line 2537 of file deparse.c.

References appendStringInfoChar(), ESCAPE_STRING_SYNTAX, and SQL_STR_DOUBLE.

Referenced by deparseAnalyzeSizeSql(), deparseConst(), and postgresImportForeignSchema().

2538 {
2539  const char *valptr;
2540 
2541  /*
2542  * Rather than making assumptions about the remote server's value of
2543  * standard_conforming_strings, always use E'foo' syntax if there are any
2544  * backslashes. This will fail on remote servers before 8.1, but those
2545  * are long out of support.
2546  */
2547  if (strchr(val, '\\') != NULL)
2549  appendStringInfoChar(buf, '\'');
2550  for (valptr = val; *valptr; valptr++)
2551  {
2552  char ch = *valptr;
2553 
2554  if (SQL_STR_DOUBLE(ch, true))
2555  appendStringInfoChar(buf, ch);
2556  appendStringInfoChar(buf, ch);
2557  }
2558  appendStringInfoChar(buf, '\'');
2559 }
#define ESCAPE_STRING_SYNTAX
Definition: c.h:1167
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
#define SQL_STR_DOUBLE(ch, escape_backslash)
Definition: c.h:1164
long val
Definition: informix.c:664

◆ deparseTruncateSql()

void deparseTruncateSql ( StringInfo  buf,
List rels,
DropBehavior  behavior,
bool  restart_seqs 
)

Definition at line 2334 of file deparse.c.

References appendStringInfo(), appendStringInfoString(), deparseRelation(), DROP_CASCADE, DROP_RESTRICT, lfirst, and list_head().

Referenced by postgresExecForeignTruncate().

2338 {
2339  ListCell *cell;
2340 
2341  appendStringInfoString(buf, "TRUNCATE ");
2342 
2343  foreach(cell, rels)
2344  {
2345  Relation rel = lfirst(cell);
2346 
2347  if (cell != list_head(rels))
2348  appendStringInfoString(buf, ", ");
2349 
2350  deparseRelation(buf, rel);
2351  }
2352 
2353  appendStringInfo(buf, " %s IDENTITY",
2354  restart_seqs ? "RESTART" : "CONTINUE");
2355 
2356  if (behavior == DROP_RESTRICT)
2357  appendStringInfoString(buf, " RESTRICT");
2358  else if (behavior == DROP_CASCADE)
2359  appendStringInfoString(buf, " CASCADE");
2360 }
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static ListCell * list_head(const List *l)
Definition: pg_list.h:125
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2497
#define lfirst(lc)
Definition: pg_list.h:169

◆ deparseUpdateSql()

void deparseUpdateSql ( StringInfo  buf,
RangeTblEntry rte,
Index  rtindex,
Relation  rel,
List targetAttrs,
List withCheckOptionList,
List returningList,
List **  retrieved_attrs 
)

Definition at line 1974 of file deparse.c.

References appendStringInfo(), appendStringInfoString(), attnum, deparseColumnRef(), deparseRelation(), deparseReturningList(), lfirst_int, RelationGetDescr, TriggerDesc::trig_update_after_row, RelationData::trigdesc, and TupleDescAttr.

Referenced by postgresPlanForeignModify().

1979 {
1980  TupleDesc tupdesc = RelationGetDescr(rel);
1981  AttrNumber pindex;
1982  bool first;
1983  ListCell *lc;
1984 
1985  appendStringInfoString(buf, "UPDATE ");
1986  deparseRelation(buf, rel);
1987  appendStringInfoString(buf, " SET ");
1988 
1989  pindex = 2; /* ctid is always the first param */
1990  first = true;
1991  foreach(lc, targetAttrs)
1992  {
1993  int attnum = lfirst_int(lc);
1994  Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1);
1995 
1996  if (!first)
1997  appendStringInfoString(buf, ", ");
1998  first = false;
1999 
2000  deparseColumnRef(buf, rtindex, attnum, rte, false);
2001  if (attr->attgenerated)
2002  appendStringInfoString(buf, " = DEFAULT");
2003  else
2004  {
2005  appendStringInfo(buf, " = $%d", pindex);
2006  pindex++;
2007  }
2008  }
2009  appendStringInfoString(buf, " WHERE ctid = $1");
2010 
2011  deparseReturningList(buf, rte, rtindex, rel,
2012  rel->trigdesc && rel->trigdesc->trig_update_after_row,
2013  withCheckOptionList, returningList, retrieved_attrs);
2014 }
#define RelationGetDescr(relation)
Definition: rel.h:503
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
static void deparseReturningList(StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, bool trig_after_row, List *withCheckOptionList, List *returningList, List **retrieved_attrs)
Definition: deparse.c:2199
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define lfirst_int(lc)
Definition: pg_list.h:170
TriggerDesc * trigdesc
Definition: rel.h:115
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:207
bool trig_update_after_row
Definition: reltrigger.h:62
int16 attnum
Definition: pg_attribute.h:83
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2497
int16 AttrNumber
Definition: attnum.h:21
static void deparseColumnRef(StringInfo buf, int varno, int varattno, RangeTblEntry *rte, bool qualify_col)
Definition: deparse.c:2369

◆ do_sql_command()

void do_sql_command ( PGconn conn,
const char *  sql 
)

Definition at line 590 of file connection.c.

References ERROR, pgfdw_get_result(), pgfdw_report_error(), PGRES_COMMAND_OK, PQclear(), PQresultStatus(), and PQsendQuery().

Referenced by begin_remote_xact(), configure_remote_session(), pgfdw_subxact_callback(), pgfdw_xact_callback(), and postgresExecForeignTruncate().

591 {
592  PGresult *res;
593 
594  if (!PQsendQuery(conn, sql))
595  pgfdw_report_error(ERROR, NULL, conn, false, sql);
596  res = pgfdw_get_result(conn, sql);
597  if (PQresultStatus(res) != PGRES_COMMAND_OK)
598  pgfdw_report_error(ERROR, res, conn, true, sql);
599  PQclear(res);
600 }
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:3178
int PQsendQuery(PGconn *conn, const char *query)
Definition: fe-exec.c:1326
#define ERROR
Definition: elog.h:46
void pgfdw_report_error(int elevel, PGresult *res, PGconn *conn, bool clear, const char *sql)
Definition: connection.c:797
void PQclear(PGresult *res)
Definition: fe-exec.c:694
PGresult * pgfdw_get_result(PGconn *conn, const char *query)
Definition: connection.c:732

◆ ExtractConnectionOptions()

int ExtractConnectionOptions ( List defelems,
const char **  keywords,
const char **  values 
)

Definition at line 377 of file option.c.

References defGetString(), DefElem::defname, i, InitPgFdwOptions(), is_libpq_option(), and lfirst.

Referenced by connect_pg_server().

379 {
380  ListCell *lc;
381  int i;
382 
383  /* Build our options lists if we didn't yet. */
385 
386  i = 0;
387  foreach(lc, defelems)
388  {
389  DefElem *d = (DefElem *) lfirst(lc);
390 
391  if (is_libpq_option(d->defname))
392  {
393  keywords[i] = d->defname;
394  values[i] = defGetString(d);
395  i++;
396  }
397  }
398  return i;
399 }
char * defGetString(DefElem *def)
Definition: define.c:49
#define lfirst(lc)
Definition: pg_list.h:169
static Datum values[MAXATTR]
Definition: bootstrap.c:156
int i
static bool is_libpq_option(const char *keyword)
Definition: option.c:356
char * defname
Definition: parsenodes.h:758
static void InitPgFdwOptions(void)
Definition: option.c:215

◆ ExtractExtensionList()

List* ExtractExtensionList ( const char *  extensionsString,
bool  warnOnMissing 
)

Definition at line 408 of file option.c.

References ereport, errcode(), errmsg(), ERROR, get_extension_oid(), lappend_oid(), lfirst, list_free(), NIL, OidIsValid, pstrdup(), SplitIdentifierString(), and WARNING.

Referenced by apply_server_options(), and postgres_fdw_validator().

409 {
410  List *extensionOids = NIL;
411  List *extlist;
412  ListCell *lc;
413 
414  /* SplitIdentifierString scribbles on its input, so pstrdup first */
415  if (!SplitIdentifierString(pstrdup(extensionsString), ',', &extlist))
416  {
417  /* syntax error in name list */
418  ereport(ERROR,
419  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
420  errmsg("parameter \"%s\" must be a list of extension names",
421  "extensions")));
422  }
423 
424  foreach(lc, extlist)
425  {
426  const char *extension_name = (const char *) lfirst(lc);
427  Oid extension_oid = get_extension_oid(extension_name, true);
428 
429  if (OidIsValid(extension_oid))
430  {
431  extensionOids = lappend_oid(extensionOids, extension_oid);
432  }
433  else if (warnOnMissing)
434  {
436  (errcode(ERRCODE_UNDEFINED_OBJECT),
437  errmsg("extension \"%s\" is not installed",
438  extension_name)));
439  }
440  }
441 
442  list_free(extlist);
443  return extensionOids;
444 }
#define NIL
Definition: pg_list.h:65
char * pstrdup(const char *in)
Definition: mcxt.c:1299
int errcode(int sqlerrcode)
Definition: elog.c:698
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:372
#define OidIsValid(objectId)
Definition: c.h:710
#define ERROR
Definition: elog.h:46
bool SplitIdentifierString(char *rawstring, char separator, List **namelist)
Definition: varlena.c:3746
#define WARNING
Definition: elog.h:40
#define ereport(elevel,...)
Definition: elog.h:157
#define lfirst(lc)
Definition: pg_list.h:169
Oid get_extension_oid(const char *extname, bool missing_ok)
Definition: extension.c:140
int errmsg(const char *fmt,...)
Definition: elog.c:909
void list_free(List *list)
Definition: list.c:1391
Definition: pg_list.h:50

◆ find_em_expr_for_input_target()

Expr* find_em_expr_for_input_target ( PlannerInfo root,
EquivalenceClass ec,
PathTarget target 
)

Definition at line 7339 of file postgres_fdw.c.

References arg, EquivalenceClass::ec_members, elog, EquivalenceMember::em_expr, EquivalenceMember::em_is_child, EquivalenceMember::em_is_const, equal(), ERROR, PathTarget::exprs, get_pathtarget_sortgroupref, get_sortgroupref_clause_noerr(), i, IsA, lfirst, PlannerInfo::parse, and Query::sortClause.

Referenced by add_foreign_ordered_paths(), and appendOrderByClause().

7342 {
7343  ListCell *lc1;
7344  int i;
7345 
7346  i = 0;
7347  foreach(lc1, target->exprs)
7348  {
7349  Expr *expr = (Expr *) lfirst(lc1);
7350  Index sgref = get_pathtarget_sortgroupref(target, i);
7351  ListCell *lc2;
7352 
7353  /* Ignore non-sort expressions */
7354  if (sgref == 0 ||
7356  root->parse->sortClause) == NULL)
7357  {
7358  i++;
7359  continue;
7360  }
7361 
7362  /* We ignore binary-compatible relabeling on both ends */
7363  while (expr && IsA(expr, RelabelType))
7364  expr = ((RelabelType *) expr)->arg;
7365 
7366  /* Locate an EquivalenceClass member matching this expr, if any */
7367  foreach(lc2, ec->ec_members)
7368  {
7370  Expr *em_expr;
7371 
7372  /* Don't match constants */
7373  if (em->em_is_const)
7374  continue;
7375 
7376  /* Ignore child members */
7377  if (em->em_is_child)
7378  continue;
7379 
7380  /* Match if same expression (after stripping relabel) */
7381  em_expr = em->em_expr;
7382  while (em_expr && IsA(em_expr, RelabelType))
7383  em_expr = ((RelabelType *) em_expr)->arg;
7384 
7385  if (equal(em_expr, expr))
7386  return em->em_expr;
7387  }
7388 
7389  i++;
7390  }
7391 
7392  elog(ERROR, "could not find pathkey item to sort");
7393  return NULL; /* keep compiler quiet */
7394 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:587
Query * parse
Definition: pathnodes.h:162
List * sortClause
Definition: parsenodes.h:169
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3149
#define ERROR
Definition: elog.h:46
List * exprs
Definition: pathnodes.h:1110
SortGroupClause * get_sortgroupref_clause_noerr(Index sortref, List *clauses)
Definition: tlist.c:432
unsigned int Index
Definition: c.h:549
#define get_pathtarget_sortgroupref(target, colno)
Definition: pathnodes.h:1119
#define lfirst(lc)
Definition: pg_list.h:169
#define elog(elevel,...)
Definition: elog.h:232
int i
void * arg
List * ec_members
Definition: pathnodes.h:989

◆ find_em_expr_for_rel()

Expr* find_em_expr_for_rel ( EquivalenceClass ec,
RelOptInfo rel 
)

Definition at line 939 of file equivclass.c.

Referenced by appendOrderByClause(), and get_useful_pathkeys_for_relation().

940 {
941  ListCell *lc_em;
942 
943  foreach(lc_em, ec->ec_members)
944  {
945  EquivalenceMember *em = lfirst(lc_em);
946 
947  if (bms_is_subset(em->em_relids, rel->relids) &&
948  !bms_is_empty(em->em_relids))
949  {
950  /*
951  * If there is more than one equivalence member whose Vars are
952  * taken entirely from this relation, we'll be content to choose
953  * any one of those.
954  */
955  return em->em_expr;
956  }
957  }
958 
959  /* We didn't find any suitable equivalence class expression */
960  return NULL;
961 }
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:315
Relids relids
Definition: pathnodes.h:681
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:701
#define lfirst(lc)
Definition: pg_list.h:169
List * ec_members
Definition: pathnodes.h:989

◆ get_jointype_name()

const char* get_jointype_name ( JoinType  jointype)

Definition at line 1502 of file deparse.c.

References elog, ERROR, JOIN_FULL, JOIN_INNER, JOIN_LEFT, and JOIN_RIGHT.

Referenced by deparseFromExprForRel(), and foreign_join_ok().

1503 {
1504  switch (jointype)
1505  {
1506  case JOIN_INNER:
1507  return "INNER";
1508 
1509  case JOIN_LEFT:
1510  return "LEFT";
1511 
1512  case JOIN_RIGHT:
1513  return "RIGHT";
1514 
1515  case JOIN_FULL:
1516  return "FULL";
1517 
1518  default:
1519  /* Shouldn't come here, but protect from buggy code. */
1520  elog(ERROR, "unsupported join type %d", jointype);
1521  }
1522 
1523  /* Keep compiler happy */
1524  return NULL;
1525 }
#define ERROR
Definition: elog.h:46
#define elog(elevel,...)
Definition: elog.h:232

◆ GetConnection()

PGconn* GetConnection ( UserMapping user,
bool  will_prep_stmt,
PgFdwConnState **  state 
)

Definition at line 127 of file connection.c.

References Assert, begin_remote_xact(), CacheRegisterSyscacheCallback(), ConnCacheEntry::conn, CONNECTION_BAD, CopyErrorData(), CurrentMemoryContext, DEBUG3, disconnect_pg_server(), elog, HASHCTL::entrysize, ereport, errdetail_internal(), errmsg_internal(), FlushErrorState(), FOREIGNSERVEROID, FreeErrorData(), HASH_BLOBS, hash_create(), HASH_ELEM, HASH_ENTER, hash_search(), ConnCacheEntry::have_prep_stmt, ConnCacheEntry::invalidated, ConnCacheEntry::key, HASHCTL::keysize, make_new_connection(), MemoryContextSwitchTo(), pchomp(), PgFdwConnState::pendingAreq, PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, pgfdw_inval_callback(), pgfdw_reject_incomplete_xact_state_change(), pgfdw_subxact_callback(), pgfdw_xact_callback(), PQerrorMessage(), PQstatus(), process_pending_request(), RegisterSubXactCallback(), RegisterXactCallback(), ErrorData::sqlerrcode, ConnCacheEntry::state, UserMapping::umid, USERMAPPINGOID, ConnCacheEntry::xact_depth, and xact_got_connection.

Referenced by create_foreign_modify(), dumpBlobs(), dumpDatabase(), dumpDatabaseConfig(), dumpTableData_copy(), estimate_path_cost_size(), expand_extension_name_patterns(), expand_foreign_server_name_patterns(), expand_schema_name_patterns(), expand_table_name_patterns(), getTables(), main(), postgresAcquireSampleRowsFunc(), postgresAnalyzeForeignTable(), postgresBeginDirectModify(), postgresBeginForeignScan(), postgresExecForeignTruncate(), postgresImportForeignSchema(), setup_connection(), StartLogStreamer(), StreamLog(), and StreamLogicalLog().

128 {
129  bool found;
130  bool retry = false;
131  ConnCacheEntry *entry;
134 
135  /* First time through, initialize connection cache hashtable */
136  if (ConnectionHash == NULL)
137  {
138  HASHCTL ctl;
139 
140  ctl.keysize = sizeof(ConnCacheKey);
141  ctl.entrysize = sizeof(ConnCacheEntry);
142  ConnectionHash = hash_create("postgres_fdw connections", 8,
143  &ctl,
145 
146  /*
147  * Register some callback functions that manage connection cleanup.
148  * This should be done just once in each backend.
149  */
156  }
157 
158  /* Set flag that we did GetConnection during the current transaction */
159  xact_got_connection = true;
160 
161  /* Create hash key for the entry. Assume no pad bytes in key struct */
162  key = user->umid;
163 
164  /*
165  * Find or create cached entry for requested connection.
166  */
167  entry = hash_search(ConnectionHash, &key, HASH_ENTER, &found);
168  if (!found)
169  {
170  /*
171  * We need only clear "conn" here; remaining fields will be filled
172  * later when "conn" is set.
173  */
174  entry->conn = NULL;
175  }
176 
177  /* Reject further use of connections which failed abort cleanup. */
179 
180  /*
181  * If the connection needs to be remade due to invalidation, disconnect as
182  * soon as we're out of all transactions.
183  */
184  if (entry->conn != NULL && entry->invalidated && entry->xact_depth == 0)
185  {
186  elog(DEBUG3, "closing connection %p for option changes to take effect",
187  entry->conn);
188  disconnect_pg_server(entry);
189  }
190 
191  /*
192  * If cache entry doesn't have a connection, we have to establish a new
193  * connection. (If connect_pg_server throws an error, the cache entry
194  * will remain in a valid empty state, ie conn == NULL.)
195  */
196  if (entry->conn == NULL)
197  make_new_connection(entry, user);
198 
199  /*
200  * We check the health of the cached connection here when starting a new
201  * remote transaction. If a broken connection is detected, we try to
202  * reestablish a new connection later.
203  */
204  PG_TRY();
205  {
206  /* Process a pending asynchronous request if any. */
207  if (entry->state.pendingAreq)
209  /* Start a new transaction or subtransaction if needed. */
210  begin_remote_xact(entry);
211  }
212  PG_CATCH();
213  {
215  ErrorData *errdata = CopyErrorData();
216 
217  /*
218  * If connection failure is reported when starting a new remote
219  * transaction (not subtransaction), new connection will be
220  * reestablished later.
221  *
222  * After a broken connection is detected in libpq, any error other
223  * than connection failure (e.g., out-of-memory) can be thrown
224  * somewhere between return from libpq and the expected ereport() call
225  * in pgfdw_report_error(). In this case, since PQstatus() indicates
226  * CONNECTION_BAD, checking only PQstatus() causes the false detection
227  * of connection failure. To avoid this, we also verify that the
228  * error's sqlstate is ERRCODE_CONNECTION_FAILURE. Note that also
229  * checking only the sqlstate can cause another false detection
230  * because pgfdw_report_error() may report ERRCODE_CONNECTION_FAILURE
231  * for any libpq-originated error condition.
232  */
233  if (errdata->sqlerrcode != ERRCODE_CONNECTION_FAILURE ||
234  PQstatus(entry->conn) != CONNECTION_BAD ||
235  entry->xact_depth > 0)
236  {
237  MemoryContextSwitchTo(ecxt);
238  PG_RE_THROW();
239  }
240 
241  /* Clean up the error state */
242  FlushErrorState();
243  FreeErrorData(errdata);
244  errdata = NULL;
245 
246  retry = true;
247  }
248  PG_END_TRY();
249 
250  /*
251  * If a broken connection is detected, disconnect it, reestablish a new
252  * connection and retry a new remote transaction. If connection failure is
253  * reported again, we give up getting a connection.
254  */
255  if (retry)
256  {
257  Assert(entry->xact_depth == 0);
258 
259  ereport(DEBUG3,
260  (errmsg_internal("could not start remote transaction on connection %p",
261  entry->conn)),
262  errdetail_internal("%s", pchomp(PQerrorMessage(entry->conn))));
263 
264  elog(DEBUG3, "closing connection %p to reestablish a new one",
265  entry->conn);
266  disconnect_pg_server(entry);
267 
268  if (entry->conn == NULL)
269  make_new_connection(entry, user);
270 
271  begin_remote_xact(entry);
272  }
273 
274  /* Remember if caller will prepare statements */
275  entry->have_prep_stmt |= will_prep_stmt;
276 
277  /* If caller needs access to the per-connection state, return it. */
278  if (state)
279  *state = &entry->state;
280 
281  return entry->conn;
282 }
Oid umid
Definition: foreign.h:47
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6744
#define HASH_ELEM
Definition: hsearch.h:95
int sqlerrcode
Definition: elog.h:381
#define DEBUG3
Definition: elog.h:23
struct ConnCacheEntry ConnCacheEntry
ErrorData * CopyErrorData(void)
Definition: elog.c:1560
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Size entrysize
Definition: hsearch.h:76
bool have_prep_stmt
Definition: connection.c:58
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
void FlushErrorState(void)
Definition: elog.c:1654
int errdetail_internal(const char *fmt,...)
Definition: elog.c:1069
char * pchomp(const char *in)
Definition: mcxt.c:1327
void FreeErrorData(ErrorData *edata)
Definition: elog.c:1616
void process_pending_request(AsyncRequest *areq)
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:349
PgFdwConnState state
Definition: connection.c:67
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
bool invalidated
Definition: connection.c:61
static void pgfdw_inval_callback(Datum arg, int cacheid, uint32 hashvalue)
Definition: connection.c:1067
#define HASH_BLOBS
Definition: hsearch.h:97
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1498
static void pgfdw_xact_callback(XactEvent event, void *arg)
Definition: connection.c:852
static HTAB * ConnectionHash
Definition: connection.c:73
uintptr_t Datum
Definition: postgres.h:411
void RegisterSubXactCallback(SubXactCallback callback, void *arg)
Definition: xact.c:3592
Size keysize
Definition: hsearch.h:75
#define ereport(elevel,...)
Definition: elog.h:157
AsyncRequest * pendingAreq
Definition: postgres_fdw.h:134
int errmsg_internal(const char *fmt,...)
Definition: elog.c:996
#define PG_CATCH()
Definition: elog.h:323
PGconn * conn
Definition: connection.c:54
static void disconnect_pg_server(ConnCacheEntry *entry)
Definition: connection.c:479
#define Assert(condition)
Definition: c.h:804
void RegisterXactCallback(XactCallback callback, void *arg)
Definition: xact.c:3537
static void pgfdw_reject_incomplete_xact_state_change(ConnCacheEntry *entry)
Definition: connection.c:1117
static bool xact_got_connection
Definition: connection.c:80
#define PG_RE_THROW()
Definition: elog.h:354
static void make_new_connection(ConnCacheEntry *entry, UserMapping *user)
Definition: connection.c:289
#define elog(elevel,...)
Definition: elog.h:232
static void pgfdw_subxact_callback(SubXactEvent event, SubTransactionId mySubid, SubTransactionId parentSubid, void *arg)
Definition: connection.c:983
ConnStatusType PQstatus(const PGconn *conn)
Definition: fe-connect.c:6691
#define PG_TRY()
Definition: elog.h:313
static void begin_remote_xact(ConnCacheEntry *entry)
Definition: connection.c:613
Oid ConnCacheKey
Definition: connection.c:49
#define PG_END_TRY()
Definition: elog.h:338

◆ GetCursorNumber()

unsigned int GetCursorNumber ( PGconn conn)

Definition at line 677 of file connection.c.

References cursor_number.

Referenced by postgresAcquireSampleRowsFunc(), and postgresBeginForeignScan().

678 {
679  return ++cursor_number;
680 }
static unsigned int cursor_number
Definition: connection.c:76

◆ GetPrepStmtNumber()

unsigned int GetPrepStmtNumber ( PGconn conn)

Definition at line 691 of file connection.c.

References prep_stmt_number.

Referenced by prepare_foreign_modify().

692 {
693  return ++prep_stmt_number;
694 }
static unsigned int prep_stmt_number
Definition: connection.c:77

◆ is_builtin()

bool is_builtin ( Oid  objectId)

Definition at line 152 of file shippable.c.

References FirstGenbkiObjectId.

Referenced by deparse_type_name(), and is_shippable().

153 {
154  return (objectId < FirstGenbkiObjectId);
155 }
#define FirstGenbkiObjectId
Definition: transam.h:195

◆ is_foreign_expr()

bool is_foreign_expr ( PlannerInfo root,
RelOptInfo baserel,
Expr expr 
)

Definition at line 233 of file deparse.c.

References foreign_loc_cxt::collation, contain_mutable_functions(), FDW_COLLATE_NONE, FDW_COLLATE_UNSAFE, RelOptInfo::fdw_private, foreign_expr_walker(), foreign_glob_cxt::foreignrel, InvalidOid, IS_UPPER_REL, PgFdwRelationInfo::outerrel, foreign_glob_cxt::relids, RelOptInfo::relids, foreign_glob_cxt::root, and foreign_loc_cxt::state.

Referenced by add_foreign_final_paths(), add_foreign_ordered_paths(), classifyConditions(), foreign_grouping_ok(), foreign_join_ok(), get_useful_pathkeys_for_relation(), postgresGetForeignPaths(), postgresGetForeignPlan(), and postgresPlanDirectModify().

236 {
237  foreign_glob_cxt glob_cxt;
238  foreign_loc_cxt loc_cxt;
239  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) (baserel->fdw_private);
240 
241  /*
242  * Check that the expression consists of nodes that are safe to execute
243  * remotely.
244  */
245  glob_cxt.root = root;
246  glob_cxt.foreignrel = baserel;
247 
248  /*
249  * For an upper relation, use relids from its underneath scan relation,
250  * because the upperrel's own relids currently aren't set to anything
251  * meaningful by the core code. For other relation, use their own relids.
252  */
253  if (IS_UPPER_REL(baserel))
254  glob_cxt.relids = fpinfo->outerrel->relids;
255  else
256  glob_cxt.relids = baserel->relids;
257  loc_cxt.collation = InvalidOid;
258  loc_cxt.state = FDW_COLLATE_NONE;
259  if (!foreign_expr_walker((Node *) expr, &glob_cxt, &loc_cxt, NULL))
260  return false;
261 
262  /*
263  * If the expression has a valid collation that does not arise from a
264  * foreign var, the expression can not be sent over.
265  */
266  if (loc_cxt.state == FDW_COLLATE_UNSAFE)
267  return false;
268 
269  /*
270  * An expression which includes any mutable functions can't be sent over
271  * because its result is not stable. For example, sending now() remote
272  * side could cause confusion from clock offsets. Future versions might
273  * be able to make this choice with more granularity. (We check this last
274  * because it requires a lot of expensive catalog lookups.)
275  */
276  if (contain_mutable_functions((Node *) expr))
277  return false;
278 
279  /* OK to evaluate on the remote server */
280  return true;
281 }
FDWCollateState state
Definition: deparse.c:89
static bool foreign_expr_walker(Node *node, foreign_glob_cxt *glob_cxt, foreign_loc_cxt *outer_cxt, foreign_loc_cxt *case_arg_cxt)
Definition: deparse.c:301
Definition: nodes.h:536
RelOptInfo * outerrel
Definition: postgres_fdw.h:102
Relids relids
Definition: deparse.c:68
PlannerInfo * root
Definition: deparse.c:66
RelOptInfo * foreignrel
Definition: deparse.c:67
Relids relids
Definition: pathnodes.h:681
#define InvalidOid
Definition: postgres_ext.h:36
void * fdw_private
Definition: pathnodes.h:737
#define IS_UPPER_REL(rel)
Definition: pathnodes.h:664
bool contain_mutable_functions(Node *clause)
Definition: clauses.c:363

◆ is_foreign_param()

bool is_foreign_param ( PlannerInfo root,
RelOptInfo baserel,
Expr expr 
)

Definition at line 1004 of file deparse.c.

References bms_is_member(), RelOptInfo::fdw_private, IS_UPPER_REL, nodeTag, PgFdwRelationInfo::outerrel, foreign_glob_cxt::relids, RelOptInfo::relids, T_Param, T_Var, Var::varlevelsup, and Var::varno.

Referenced by foreign_grouping_ok().

1007 {
1008  if (expr == NULL)
1009  return false;
1010 
1011  switch (nodeTag(expr))
1012  {
1013  case T_Var:
1014  {
1015  /* It would have to be sent unless it's a foreign Var */
1016  Var *var = (Var *) expr;
1017  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) (baserel->fdw_private);
1018  Relids relids;
1019 
1020  if (IS_UPPER_REL(baserel))
1021  relids = fpinfo->outerrel->relids;
1022  else
1023  relids = baserel->relids;
1024 
1025  if (bms_is_member(var->varno, relids) && var->varlevelsup == 0)
1026  return false; /* foreign Var, so not a param */
1027  else
1028  return true; /* it'd have to be a param */
1029  break;
1030  }
1031  case T_Param:
1032  /* Params always have to be sent to the foreign server */
1033  return true;
1034  default:
1035  break;
1036  }
1037  return false;
1038 }
int varno
Definition: primnodes.h:189
Index varlevelsup
Definition: primnodes.h:196
Definition: primnodes.h:186
RelOptInfo * outerrel
Definition: postgres_fdw.h:102
Relids relids
Definition: pathnodes.h:681
Definition: nodes.h:156
void * fdw_private
Definition: pathnodes.h:737
#define IS_UPPER_REL(rel)
Definition: pathnodes.h:664
#define nodeTag(nodeptr)
Definition: nodes.h:541
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:427
Definition: nodes.h:158

◆ is_shippable()

bool is_shippable ( Oid  objectId,
Oid  classId,
PgFdwRelationInfo fpinfo 
)

Definition at line 162 of file shippable.c.

References ShippableCacheKey::classid, HASH_ENTER, HASH_FIND, hash_search(), InitializeShippableCache(), is_builtin(), sort-test::key, lookup_shippable(), NIL, ShippableCacheKey::objid, PgFdwRelationInfo::server, ForeignServer::serverid, ShippableCacheKey::serverid, ShippableCacheEntry::shippable, and PgFdwRelationInfo::shippable_extensions.

Referenced by foreign_expr_walker().

163 {
165  ShippableCacheEntry *entry;
166 
167  /* Built-in objects are presumed shippable. */
168  if (is_builtin(objectId))
169  return true;
170 
171  /* Otherwise, give up if user hasn't specified any shippable extensions. */
172  if (fpinfo->shippable_extensions == NIL)
173  return false;
174 
175  /* Initialize cache if first time through. */
176  if (!ShippableCacheHash)
178 
179  /* Set up cache hash key */
180  key.objid = objectId;
181  key.classid = classId;
182  key.serverid = fpinfo->server->serverid;
183 
184  /* See if we already cached the result. */
185  entry = (ShippableCacheEntry *)
187  (void *) &key,
188  HASH_FIND,
189  NULL);
190 
191  if (!entry)
192  {
193  /* Not found in cache, so perform shippability lookup. */
194  bool shippable = lookup_shippable(objectId, classId, fpinfo);
195 
196  /*
197  * Don't create a new hash entry until *after* we have the shippable
198  * result in hand, as the underlying catalog lookups might trigger a
199  * cache invalidation.
200  */
201  entry = (ShippableCacheEntry *)
203  (void *) &key,
204  HASH_ENTER,
205  NULL);
206 
207  entry->shippable = shippable;
208  }
209 
210  return entry->shippable;
211 }
#define NIL
Definition: pg_list.h:65
bool is_builtin(Oid objectId)
Definition: shippable.c:152
ForeignServer * server
Definition: postgres_fdw.h:86
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
static void InitializeShippableCache(void)
Definition: shippable.c:91
static bool lookup_shippable(Oid objectId, Oid classId, PgFdwRelationInfo *fpinfo)
Definition: shippable.c:116
static HTAB * ShippableCacheHash
Definition: shippable.c:34
List * shippable_extensions
Definition: postgres_fdw.h:81
Oid serverid
Definition: foreign.h:36

◆ pgfdw_exec_query()

PGresult* pgfdw_exec_query ( PGconn conn,
const char *  query,
PgFdwConnState state 
)

Definition at line 704 of file connection.c.

References ERROR, PgFdwConnState::pendingAreq, pgfdw_get_result(), pgfdw_report_error(), PQsendQuery(), and process_pending_request().

Referenced by close_cursor(), deallocate_query(), fetch_more_data(), get_remote_estimate(), postgresAcquireSampleRowsFunc(), postgresAnalyzeForeignTable(), postgresImportForeignSchema(), and postgresReScanForeignScan().

705 {
706  /* First, process a pending asynchronous request, if any. */
707  if (state && state->pendingAreq)
709 
710  /*
711  * Submit a query. Since we don't use non-blocking mode, this also can
712  * block. But its risk is relatively small, so we ignore that for now.
713  */
714  if (!PQsendQuery(conn, query))
715  pgfdw_report_error(ERROR, NULL, conn, false, query);
716 
717  /* Wait for the result. */
718  return pgfdw_get_result(conn, query);
719 }
int PQsendQuery(PGconn *conn, const char *query)
Definition: fe-exec.c:1326
#define ERROR
Definition: elog.h:46
void process_pending_request(AsyncRequest *areq)
void pgfdw_report_error(int elevel, PGresult *res, PGconn *conn, bool clear, const char *sql)
Definition: connection.c:797
AsyncRequest * pendingAreq
Definition: postgres_fdw.h:134
PGresult * pgfdw_get_result(PGconn *conn, const char *query)
Definition: connection.c:732

◆ pgfdw_get_result()

PGresult* pgfdw_get_result ( PGconn conn,
const char *  query 
)

Definition at line 732 of file connection.c.

References CHECK_FOR_INTERRUPTS, ERROR, MyLatch, PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, PG_WAIT_EXTENSION, pgfdw_report_error(), PQclear(), PQconsumeInput(), PQgetResult(), PQisBusy(), PQsocket(), ResetLatch(), WaitLatchOrSocket(), WL_EXIT_ON_PM_DEATH, WL_LATCH_SET, and WL_SOCKET_READABLE.

Referenced by create_cursor(), do_sql_command(), execute_dml_stmt(), execute_foreign_modify(), fetch_more_data(), pgfdw_exec_query(), and prepare_foreign_modify().

733 {
734  PGresult *volatile last_res = NULL;
735 
736  /* In what follows, do not leak any PGresults on an error. */
737  PG_TRY();
738  {
739  for (;;)
740  {
741  PGresult *res;
742 
743  while (PQisBusy(conn))
744  {
745  int wc;
746 
747  /* Sleep until there's something to do */
751  PQsocket(conn),
752  -1L, PG_WAIT_EXTENSION);
754 
756 
757  /* Data available in socket? */
758  if (wc & WL_SOCKET_READABLE)
759  {
760  if (!PQconsumeInput(conn))
761  pgfdw_report_error(ERROR, NULL, conn, false, query);
762  }
763  }
764 
765  res = PQgetResult(conn);
766  if (res == NULL)
767  break; /* query is complete */
768 
769  PQclear(last_res);
770  last_res = res;
771  }
772  }
773  PG_CATCH();
774  {
775  PQclear(last_res);
776  PG_RE_THROW();
777  }
778  PG_END_TRY();
779 
780  return last_res;
781 }
#define PG_WAIT_EXTENSION
Definition: wait_event.h:23
#define WL_SOCKET_READABLE
Definition: latch.h:126
void ResetLatch(Latch *latch)
Definition: latch.c:660
#define ERROR
Definition: elog.h:46
int WaitLatchOrSocket(Latch *latch, int wakeEvents, pgsocket sock, long timeout, uint32 wait_event_info)
Definition: latch.c:500
void pgfdw_report_error(int elevel, PGresult *res, PGconn *conn, bool clear, const char *sql)
Definition: connection.c:797
int PQconsumeInput(PGconn *conn)
Definition: fe-exec.c:1904
void PQclear(PGresult *res)
Definition: fe-exec.c:694
#define PG_CATCH()
Definition: elog.h:323
int PQisBusy(PGconn *conn)
Definition: fe-exec.c:1951
#define PG_RE_THROW()
Definition: elog.h:354
struct Latch * MyLatch
Definition: globals.c:57
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:120
#define PG_TRY()
Definition: elog.h:313
#define WL_LATCH_SET
Definition: latch.h:125
int PQsocket(const PGconn *conn)
Definition: fe-connect.c:6770
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:1978
#define PG_END_TRY()
Definition: elog.h:338
#define WL_EXIT_ON_PM_DEATH
Definition: latch.h:130

◆ pgfdw_report_error()

void pgfdw_report_error ( int  elevel,
PGresult res,
PGconn conn,
bool  clear,
const char *  sql 
)

Definition at line 797 of file connection.c.

References ereport, errcode(), errcontext, errdetail_internal(), errhint(), errmsg(), errmsg_internal(), MAKE_SQLSTATE, pchomp(), PG_DIAG_CONTEXT, PG_DIAG_MESSAGE_DETAIL, PG_DIAG_MESSAGE_HINT, PG_DIAG_MESSAGE_PRIMARY, PG_DIAG_SQLSTATE, PG_END_TRY, PG_FINALLY, PG_TRY, PQclear(), PQerrorMessage(), and PQresultErrorField().

Referenced by close_cursor(), create_cursor(), deallocate_query(), do_sql_command(), execute_dml_stmt(), execute_foreign_modify(), fetch_more_data(), fetch_more_data_begin(), get_remote_estimate(), pgfdw_exec_cleanup_query(), pgfdw_exec_query(), pgfdw_get_result(), postgresAcquireSampleRowsFunc(), postgresAnalyzeForeignTable(), postgresForeignAsyncNotify(), postgresImportForeignSchema(), postgresReScanForeignScan(), and prepare_foreign_modify().

799 {
800  /* If requested, PGresult must be released before leaving this function. */
801  PG_TRY();
802  {
803  char *diag_sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE);
804  char *message_primary = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY);
805  char *message_detail = PQresultErrorField(res, PG_DIAG_MESSAGE_DETAIL);
806  char *message_hint = PQresultErrorField(res, PG_DIAG_MESSAGE_HINT);
807  char *message_context = PQresultErrorField(res, PG_DIAG_CONTEXT);
808  int sqlstate;
809 
810  if (diag_sqlstate)
811  sqlstate = MAKE_SQLSTATE(diag_sqlstate[0],
812  diag_sqlstate[1],
813  diag_sqlstate[2],
814  diag_sqlstate[3],
815  diag_sqlstate[4]);
816  else
817  sqlstate = ERRCODE_CONNECTION_FAILURE;
818 
819  /*
820  * If we don't get a message from the PGresult, try the PGconn. This
821  * is needed because for connection-level failures, PQexec may just
822  * return NULL, not a PGresult at all.
823  */
824  if (message_primary == NULL)
825  message_primary = pchomp(PQerrorMessage(conn));
826 
827  ereport(elevel,
828  (errcode(sqlstate),
829  message_primary ? errmsg_internal("%s", message_primary) :
830  errmsg("could not obtain message string for remote error"),
831  message_detail ? errdetail_internal("%s", message_detail) : 0,
832  message_hint ? errhint("%s", message_hint) : 0,
833  message_context ? errcontext("%s", message_context) : 0,
834  sql ? errcontext("remote SQL command: %s", sql) : 0));
835  }
836  PG_FINALLY();
837  {
838  if (clear)
839  PQclear(res);
840  }
841  PG_END_TRY();
842 }
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6744
int errhint(const char *fmt,...)
Definition: elog.c:1156
#define PG_DIAG_MESSAGE_PRIMARY
Definition: postgres_ext.h:58
#define PG_DIAG_MESSAGE_DETAIL
Definition: postgres_ext.h:59
#define MAKE_SQLSTATE(ch1, ch2, ch3, ch4, ch5)
Definition: elog.h:64
int errcode(int sqlerrcode)
Definition: elog.c:698
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
int errdetail_internal(const char *fmt,...)
Definition: elog.c:1069
char * pchomp(const char *in)
Definition: mcxt.c:1327
static int elevel
Definition: vacuumlazy.c:401
#define PG_FINALLY()
Definition: elog.h:330
#define PG_DIAG_MESSAGE_HINT
Definition: postgres_ext.h:60
#define ereport(elevel,...)
Definition: elog.h:157
void PQclear(PGresult *res)
Definition: fe-exec.c:694
int errmsg_internal(const char *fmt,...)
Definition: elog.c:996
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:3233
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define errcontext
Definition: elog.h:204
#define PG_TRY()
Definition: elog.h:313
#define PG_END_TRY()
Definition: elog.h:338
#define PG_DIAG_CONTEXT
Definition: postgres_ext.h:64

◆ process_pending_request()

void process_pending_request ( AsyncRequest areq)

Definition at line 7057 of file postgres_fdw.c.

References Assert, AsyncRequest::callback_pending, ExecAsyncRequestDone(), ExecAsyncResponse(), ForeignScanState::fdw_state, fetch_more_data(), PG_USED_FOR_ASSERTS_ONLY, and AsyncRequest::requestee.

Referenced by create_cursor(), execute_dml_stmt(), execute_foreign_modify(), GetConnection(), pgfdw_exec_query(), and postgresForeignAsyncConfigureWait().

7058 {
7059  ForeignScanState *node = (ForeignScanState *) areq->requestee;
7061 
7062  /* The request would have been pending for a callback */
7063  Assert(areq->callback_pending);
7064 
7065  /* The request should be currently in-process */
7066  Assert(fsstate->conn_state->pendingAreq == areq);
7067 
7068  fetch_more_data(node);
7069 
7070  /*
7071  * If we didn't get any tuples, must be end of data; complete the request
7072  * now. Otherwise, we postpone completing the request until we are called
7073  * from postgresForeignAsyncConfigureWait()/postgresForeignAsyncNotify().
7074  */
7075  if (fsstate->next_tuple >= fsstate->num_tuples)
7076  {
7077  /* Unlike AsyncNotify, we unset callback_pending ourselves */
7078  areq->callback_pending = false;
7079  /* Mark the request as complete */
7080  ExecAsyncRequestDone(areq, NULL);
7081  /* Unlike AsyncNotify, we call ExecAsyncResponse ourselves */
7082  ExecAsyncResponse(areq);
7083  }
7084 }
struct PlanState * requestee
Definition: execnodes.h:538
void ExecAsyncRequestDone(AsyncRequest *areq, TupleTableSlot *result)
Definition: execAsync.c:137
bool callback_pending
Definition: execnodes.h:540
#define Assert(condition)
Definition: c.h:804
static void fetch_more_data(ForeignScanState *node)
void ExecAsyncResponse(AsyncRequest *areq)
Definition: execAsync.c:117
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:155

◆ rebuildInsertSql()

void rebuildInsertSql ( StringInfo  buf,
Relation  rel,
char *  orig_query,
List target_attrs,
int  values_end_len,
int  num_params,
int  num_rows 
)

Definition at line 1914 of file deparse.c.

References appendBinaryStringInfo(), appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), Assert, attnum, i, lfirst_int, RelationGetDescr, and TupleDescAttr.

Referenced by execute_foreign_modify().

1918 {
1919  TupleDesc tupdesc = RelationGetDescr(rel);
1920  int i;
1921  int pindex;
1922  bool first;
1923  ListCell *lc;
1924 
1925  /* Make sure the values_end_len is sensible */
1926  Assert((values_end_len > 0) && (values_end_len <= strlen(orig_query)));
1927 
1928  /* Copy up to the end of the first record from the original query */
1929  appendBinaryStringInfo(buf, orig_query, values_end_len);
1930 
1931  /*
1932  * Add records to VALUES clause (we already have parameters for the first
1933  * row, so start at the right offset).
1934  */
1935  pindex = num_params + 1;
1936  for (i = 0; i < num_rows; i++)
1937  {
1938  appendStringInfoString(buf, ", (");
1939 
1940  first = true;
1941  foreach(lc, target_attrs)
1942  {
1943  int attnum = lfirst_int(lc);
1944  Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1);
1945 
1946  if (!first)
1947  appendStringInfoString(buf, ", ");
1948  first = false;
1949 
1950  if (attr->attgenerated)
1951  appendStringInfoString(buf, "DEFAULT");
1952  else
1953  {
1954  appendStringInfo(buf, "$%d", pindex);
1955  pindex++;
1956  }
1957  }
1958 
1959  appendStringInfoChar(buf, ')');
1960  }
1961 
1962  /* Copy stuff after VALUES clause from the original query */
1963  appendStringInfoString(buf, orig_query + values_end_len);
1964 }
#define RelationGetDescr(relation)
Definition: rel.h:503
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define lfirst_int(lc)
Definition: pg_list.h:170
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:207
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
int16 attnum
Definition: pg_attribute.h:83
#define Assert(condition)
Definition: c.h:804
int i
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:227

◆ ReleaseConnection()

void ReleaseConnection ( PGconn conn)

Definition at line 656 of file connection.c.

Referenced by estimate_path_cost_size(), finish_foreign_modify(), postgresAcquireSampleRowsFunc(), postgresAnalyzeForeignTable(), postgresEndDirectModify(), postgresEndForeignScan(), and postgresImportForeignSchema().

657 {
658  /*
659  * Currently, we don't actually track connection references because all
660  * cleanup is managed on a transaction or subtransaction basis instead. So
661  * there's nothing to do here.
662  */
663 }

◆ reset_transmission_modes()

void reset_transmission_modes ( int  nestlevel)

Definition at line 3890 of file postgres_fdw.c.

References AtEOXact_GUC().

Referenced by appendConditions(), appendLimitClause(), appendOrderByClause(), convert_prep_stmt_params(), deparseDirectUpdateSql(), and process_query_params().

3891 {
3892  AtEOXact_GUC(true, nestlevel);
3893 }
void AtEOXact_GUC(bool isCommit, int nestLevel)
Definition: guc.c:6242

◆ set_transmission_modes()

int set_transmission_modes ( void  )

Definition at line 3862 of file postgres_fdw.c.

References DateStyle, extra_float_digits, GUC_ACTION_SAVE, IntervalStyle, INTSTYLE_POSTGRES, NewGUCNestLevel(), PGC_S_SESSION, PGC_USERSET, set_config_option(), and USE_ISO_DATES.

Referenced by appendConditions(), appendLimitClause(), appendOrderByClause(), convert_prep_stmt_params(), deparseDirectUpdateSql(), and process_query_params().

3863 {
3864  int nestlevel = NewGUCNestLevel();
3865 
3866  /*
3867  * The values set here should match what pg_dump does. See also
3868  * configure_remote_session in connection.c.
3869  */
3870  if (DateStyle != USE_ISO_DATES)
3871  (void) set_config_option("datestyle", "ISO",
3873  GUC_ACTION_SAVE, true, 0, false);
3875  (void) set_config_option("intervalstyle", "postgres",
3877  GUC_ACTION_SAVE, true, 0, false);
3878  if (extra_float_digits < 3)
3879  (void) set_config_option("extra_float_digits", "3",
3881  GUC_ACTION_SAVE, true, 0, false);
3882 
3883  return nestlevel;
3884 }
int IntervalStyle
Definition: globals.c:120
#define USE_ISO_DATES
Definition: miscadmin.h:229
int extra_float_digits
Definition: float.c:42
int DateStyle
Definition: globals.c:118
int NewGUCNestLevel(void)
Definition: guc.c:6228
int set_config_option(const char *name, const char *value, GucContext context, GucSource source, GucAction action, bool changeVal, int elevel, bool is_reload)
Definition: guc.c:7319
#define INTSTYLE_POSTGRES
Definition: miscadmin.h:249

Variable Documentation

◆ pgfdw_application_name

char* pgfdw_application_name

Definition at line 51 of file option.c.

Referenced by _PG_init(), and connect_pg_server().