PostgreSQL Source Code  git master
postgres_fdw.h File Reference
#include "foreign/foreign.h"
#include "lib/stringinfo.h"
#include "nodes/pathnodes.h"
#include "utils/relcache.h"
#include "libpq-fe.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
 

Typedefs

typedef struct PgFdwRelationInfo PgFdwRelationInfo
 

Functions

int set_transmission_modes (void)
 
void reset_transmission_modes (int nestlevel)
 
PGconnGetConnection (UserMapping *user, bool will_prep_stmt)
 
void ReleaseConnection (PGconn *conn)
 
unsigned int GetCursorNumber (PGconn *conn)
 
unsigned int GetPrepStmtNumber (PGconn *conn)
 
PGresultpgfdw_get_result (PGconn *conn, const char *query)
 
PGresultpgfdw_exec_query (PGconn *conn, const char *query)
 
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)
 
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 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)
 

Typedef Documentation

◆ PgFdwRelationInfo

Function Documentation

◆ build_tlist_to_deparse()

List* build_tlist_to_deparse ( RelOptInfo foreignrel)

Definition at line 924 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().

925 {
926  List *tlist = NIL;
927  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
928  ListCell *lc;
929 
930  /*
931  * For an upper relation, we have already built the target list while
932  * checking shippability, so just return that.
933  */
934  if (IS_UPPER_REL(foreignrel))
935  return fpinfo->grouped_tlist;
936 
937  /*
938  * We require columns specified in foreignrel->reltarget->exprs and those
939  * required for evaluating the local conditions.
940  */
941  tlist = add_to_flat_tlist(tlist,
942  pull_var_clause((Node *) foreignrel->reltarget->exprs,
944  foreach(lc, fpinfo->local_conds)
945  {
946  RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
947 
948  tlist = add_to_flat_tlist(tlist,
949  pull_var_clause((Node *) rinfo->clause,
951  }
952 
953  return tlist;
954 }
#define NIL
Definition: pg_list.h:65
#define PVC_RECURSE_PLACEHOLDERS
Definition: optimizer.h:176
Definition: nodes.h:525
List * pull_var_clause(Node *node, int flags)
Definition: var.c:535
#define lfirst_node(type, lc)
Definition: pg_list.h:193
Expr * clause
Definition: pathnodes.h:1943
List * exprs
Definition: pathnodes.h:1044
void * fdw_private
Definition: pathnodes.h:695
List * add_to_flat_tlist(List *tlist, List *exprs)
Definition: tlist.c:154
#define IS_UPPER_REL(rel)
Definition: pathnodes.h:624
Definition: pg_list.h:50
struct PathTarget * reltarget
Definition: pathnodes.h:652

◆ classifyConditions()

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

Definition at line 206 of file deparse.c.

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

Referenced by estimate_path_cost_size(), and postgresGetForeignRelSize().

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

◆ deparseAnalyzeSizeSql()

void deparseAnalyzeSizeSql ( StringInfo  buf,
Relation  rel 
)

Definition at line 2029 of file deparse.c.

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

Referenced by postgresAnalyzeForeignTable().

2030 {
2032 
2033  /* We'll need the remote relation name as a literal. */
2034  initStringInfo(&relname);
2035  deparseRelation(&relname, rel);
2036 
2037  appendStringInfoString(buf, "SELECT pg_catalog.pg_relation_size(");
2038  deparseStringLiteral(buf, relname.data);
2039  appendStringInfo(buf, "::pg_catalog.regclass) / %d", BLCKSZ);
2040 }
NameData relname
Definition: pg_class.h:35
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
void deparseStringLiteral(StringInfo buf, const char *val)
Definition: deparse.c:2278
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2238

◆ deparseAnalyzeSql()

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

Definition at line 2049 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().

2050 {
2051  Oid relid = RelationGetRelid(rel);
2052  TupleDesc tupdesc = RelationGetDescr(rel);
2053  int i;
2054  char *colname;
2055  List *options;
2056  ListCell *lc;
2057  bool first = true;
2058 
2059  *retrieved_attrs = NIL;
2060 
2061  appendStringInfoString(buf, "SELECT ");
2062  for (i = 0; i < tupdesc->natts; i++)
2063  {
2064  /* Ignore dropped columns. */
2065  if (TupleDescAttr(tupdesc, i)->attisdropped)
2066  continue;
2067 
2068  if (!first)
2069  appendStringInfoString(buf, ", ");
2070  first = false;
2071 
2072  /* Use attribute name or column_name option. */
2073  colname = NameStr(TupleDescAttr(tupdesc, i)->attname);
2074  options = GetForeignColumnOptions(relid, i + 1);
2075 
2076  foreach(lc, options)
2077  {
2078  DefElem *def = (DefElem *) lfirst(lc);
2079 
2080  if (strcmp(def->defname, "column_name") == 0)
2081  {
2082  colname = defGetString(def);
2083  break;
2084  }
2085  }
2086 
2088 
2089  *retrieved_attrs = lappend_int(*retrieved_attrs, i + 1);
2090  }
2091 
2092  /* Don't generate bad syntax for zero-column relation. */
2093  if (first)
2094  appendStringInfoString(buf, "NULL");
2095 
2096  /*
2097  * Construct FROM clause
2098  */
2099  appendStringInfoString(buf, " FROM ");
2100  deparseRelation(buf, rel);
2101 }
#define NIL
Definition: pg_list.h:65
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10628
#define RelationGetDescr(relation)
Definition: rel.h:445
#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:40
char * defGetString(DefElem *def)
Definition: define.c:49
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
List * lappend_int(List *list, int datum)
Definition: list.c:340
static char ** options
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2238
#define lfirst(lc)
Definition: pg_list.h:190
int i
#define NameStr(name)
Definition: c.h:609
char * defname
Definition: parsenodes.h:730
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:419

◆ deparseDeleteSql()

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

Definition at line 1892 of file deparse.c.

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

Referenced by postgresPlanForeignModify().

1896 {
1897  appendStringInfoString(buf, "DELETE FROM ");
1898  deparseRelation(buf, rel);
1899  appendStringInfoString(buf, " WHERE ctid = $1");
1900 
1901  deparseReturningList(buf, rte, rtindex, rel,
1902  rel->trigdesc && rel->trigdesc->trig_delete_after_row,
1903  NIL, returningList, retrieved_attrs);
1904 }
#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:1972
TriggerDesc * trigdesc
Definition: rel.h:89
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
bool trig_delete_after_row
Definition: reltrigger.h:66
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2238

◆ 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 1921 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().

1928 {
1929  deparse_expr_cxt context;
1930 
1931  /* Set up context struct for recursion */
1932  context.root = root;
1933  context.foreignrel = foreignrel;
1934  context.scanrel = foreignrel;
1935  context.buf = buf;
1936  context.params_list = params_list;
1937 
1938  appendStringInfoString(buf, "DELETE FROM ");
1939  deparseRelation(buf, rel);
1940  if (foreignrel->reloptkind == RELOPT_JOINREL)
1941  appendStringInfo(buf, " %s%d", REL_ALIAS_PREFIX, rtindex);
1942 
1943  if (foreignrel->reloptkind == RELOPT_JOINREL)
1944  {
1945  List *ignore_conds = NIL;
1946 
1947  appendStringInfoString(buf, " USING ");
1948  deparseFromExprForRel(buf, root, foreignrel, true, rtindex,
1949  &ignore_conds, params_list);
1950  remote_conds = list_concat(remote_conds, ignore_conds);
1951  }
1952 
1953  if (remote_conds)
1954  {
1955  appendStringInfoString(buf, " WHERE ");
1956  appendConditions(remote_conds, &context);
1957  }
1958 
1959  if (foreignrel->reloptkind == RELOPT_JOINREL)
1960  deparseExplicitTargetList(returningList, true, retrieved_attrs,
1961  &context);
1962  else
1963  deparseReturningList(buf, planner_rt_fetch(rtindex, root),
1964  rtindex, rel, false,
1965  NIL, returningList, retrieved_attrs);
1966 }
#define NIL
Definition: pg_list.h:65
RelOptKind reloptkind
Definition: pathnodes.h:638
List ** params_list
Definition: deparse.c:104
List * list_concat(List *list1, const List *list2)
Definition: list.c:516
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:1972
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define planner_rt_fetch(rti, root)
Definition: pathnodes.h:371
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
static char * buf
Definition: pg_test_fsync.c:68
#define REL_ALIAS_PREFIX
Definition: deparse.c:107
static void deparseExplicitTargetList(List *tlist, bool is_returning, List **retrieved_attrs, deparse_expr_cxt *context)
Definition: deparse.c:1392
static void appendConditions(List *exprs, deparse_expr_cxt *context)
Definition: deparse.c:1321
StringInfo buf
Definition: deparse.c:103
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2238
PlannerInfo * root
Definition: deparse.c:98
static void deparseFromExprForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel, bool use_alias, Index ignore_rel, List **ignore_conds, List **params_list)
Definition: deparse.c:1469
RelOptInfo * scanrel
Definition: deparse.c:100
Definition: pg_list.h:50
RelOptInfo * foreignrel
Definition: deparse.c:99

◆ 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 1807 of file deparse.c.

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

Referenced by postgresPlanDirectModify().

1816 {
1817  deparse_expr_cxt context;
1818  int nestlevel;
1819  bool first;
1820  ListCell *lc;
1821  RangeTblEntry *rte = planner_rt_fetch(rtindex, root);
1822 
1823  /* Set up context struct for recursion */
1824  context.root = root;
1825  context.foreignrel = foreignrel;
1826  context.scanrel = foreignrel;
1827  context.buf = buf;
1828  context.params_list = params_list;
1829 
1830  appendStringInfoString(buf, "UPDATE ");
1831  deparseRelation(buf, rel);
1832  if (foreignrel->reloptkind == RELOPT_JOINREL)
1833  appendStringInfo(buf, " %s%d", REL_ALIAS_PREFIX, rtindex);
1834  appendStringInfoString(buf, " SET ");
1835 
1836  /* Make sure any constants in the exprs are printed portably */
1837  nestlevel = set_transmission_modes();
1838 
1839  first = true;
1840  foreach(lc, targetAttrs)
1841  {
1842  int attnum = lfirst_int(lc);
1843  TargetEntry *tle = get_tle_by_resno(targetlist, attnum);
1844 
1845  if (!tle)
1846  elog(ERROR, "attribute number %d not found in UPDATE targetlist",
1847  attnum);
1848 
1849  if (!first)
1850  appendStringInfoString(buf, ", ");
1851  first = false;
1852 
1853  deparseColumnRef(buf, rtindex, attnum, rte, false);
1854  appendStringInfoString(buf, " = ");
1855  deparseExpr((Expr *) tle->expr, &context);
1856  }
1857 
1858  reset_transmission_modes(nestlevel);
1859 
1860  if (foreignrel->reloptkind == RELOPT_JOINREL)
1861  {
1862  List *ignore_conds = NIL;
1863 
1864  appendStringInfoString(buf, " FROM ");
1865  deparseFromExprForRel(buf, root, foreignrel, true, rtindex,
1866  &ignore_conds, params_list);
1867  remote_conds = list_concat(remote_conds, ignore_conds);
1868  }
1869 
1870  if (remote_conds)
1871  {
1872  appendStringInfoString(buf, " WHERE ");
1873  appendConditions(remote_conds, &context);
1874  }
1875 
1876  if (foreignrel->reloptkind == RELOPT_JOINREL)
1877  deparseExplicitTargetList(returningList, true, retrieved_attrs,
1878  &context);
1879  else
1880  deparseReturningList(buf, rte, rtindex, rel, false,
1881  NIL, returningList, retrieved_attrs);
1882 }
#define NIL
Definition: pg_list.h:65
RelOptKind reloptkind
Definition: pathnodes.h:638
List ** params_list
Definition: deparse.c:104
int set_transmission_modes(void)
List * list_concat(List *list1, const List *list2)
Definition: list.c:516
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:1972
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define ERROR
Definition: elog.h:43
#define lfirst_int(lc)
Definition: pg_list.h:191
#define planner_rt_fetch(rti, root)
Definition: pathnodes.h:371
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
static char * buf
Definition: pg_test_fsync.c:68
#define REL_ALIAS_PREFIX
Definition: deparse.c:107
static void deparseExplicitTargetList(List *tlist, bool is_returning, List **retrieved_attrs, deparse_expr_cxt *context)
Definition: deparse.c:1392
static void appendConditions(List *exprs, deparse_expr_cxt *context)
Definition: deparse.c:1321
StringInfo buf
Definition: deparse.c:103
int16 attnum
Definition: pg_attribute.h:79
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2238
PlannerInfo * root
Definition: deparse.c:98
Expr * expr
Definition: primnodes.h:1393
void reset_transmission_modes(int nestlevel)
static void deparseExpr(Expr *expr, deparse_expr_cxt *context)
Definition: deparse.c:2313
static void deparseFromExprForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel, bool use_alias, Index ignore_rel, List **ignore_conds, List **params_list)
Definition: deparse.c:1469
#define elog(elevel,...)
Definition: elog.h:226
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)
RelOptInfo * scanrel
Definition: deparse.c:100
Definition: pg_list.h:50
RelOptInfo * foreignrel
Definition: deparse.c:99
static void deparseColumnRef(StringInfo buf, int varno, int varattno, RangeTblEntry *rte, bool qualify_col)
Definition: deparse.c:2110

◆ deparseInsertSql()

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

Definition at line 1691 of file deparse.c.

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

Referenced by postgresBeginForeignInsert(), and postgresPlanForeignModify().

1696 {
1697  AttrNumber pindex;
1698  bool first;
1699  ListCell *lc;
1700 
1701  appendStringInfoString(buf, "INSERT INTO ");
1702  deparseRelation(buf, rel);
1703 
1704  if (targetAttrs)
1705  {
1706  appendStringInfoChar(buf, '(');
1707 
1708  first = true;
1709  foreach(lc, targetAttrs)
1710  {
1711  int attnum = lfirst_int(lc);
1712 
1713  if (!first)
1714  appendStringInfoString(buf, ", ");
1715  first = false;
1716 
1717  deparseColumnRef(buf, rtindex, attnum, rte, false);
1718  }
1719 
1720  appendStringInfoString(buf, ") VALUES (");
1721 
1722  pindex = 1;
1723  first = true;
1724  foreach(lc, targetAttrs)
1725  {
1726  if (!first)
1727  appendStringInfoString(buf, ", ");
1728  first = false;
1729 
1730  appendStringInfo(buf, "$%d", pindex);
1731  pindex++;
1732  }
1733 
1734  appendStringInfoChar(buf, ')');
1735  }
1736  else
1737  appendStringInfoString(buf, " DEFAULT VALUES");
1738 
1739  if (doNothing)
1740  appendStringInfoString(buf, " ON CONFLICT DO NOTHING");
1741 
1742  deparseReturningList(buf, rte, rtindex, rel,
1743  rel->trigdesc && rel->trigdesc->trig_insert_after_row,
1744  withCheckOptionList, returningList, retrieved_attrs);
1745 }
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:1972
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define lfirst_int(lc)
Definition: pg_list.h:191
TriggerDesc * trigdesc
Definition: rel.h:89
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
bool trig_insert_after_row
Definition: reltrigger.h:56
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
int16 attnum
Definition: pg_attribute.h:79
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2238
int16 AttrNumber
Definition: attnum.h:21
static void deparseColumnRef(StringInfo buf, int varno, int varattno, RangeTblEntry *rte, bool qualify_col)
Definition: deparse.c:2110

◆ 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 981 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().

985 {
986  deparse_expr_cxt context;
987  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) rel->fdw_private;
988  List *quals;
989 
990  /*
991  * We handle relations for foreign tables, joins between those and upper
992  * relations.
993  */
994  Assert(IS_JOIN_REL(rel) || IS_SIMPLE_REL(rel) || IS_UPPER_REL(rel));
995 
996  /* Fill portions of context common to upper, join and base relation */
997  context.buf = buf;
998  context.root = root;
999  context.foreignrel = rel;
1000  context.scanrel = IS_UPPER_REL(rel) ? fpinfo->outerrel : rel;
1001  context.params_list = params_list;
1002 
1003  /* Construct SELECT clause */
1004  deparseSelectSql(tlist, is_subquery, retrieved_attrs, &context);
1005 
1006  /*
1007  * For upper relations, the WHERE clause is built from the remote
1008  * conditions of the underlying scan relation; otherwise, we can use the
1009  * supplied list of remote conditions directly.
1010  */
1011  if (IS_UPPER_REL(rel))
1012  {
1013  PgFdwRelationInfo *ofpinfo;
1014 
1015  ofpinfo = (PgFdwRelationInfo *) fpinfo->outerrel->fdw_private;
1016  quals = ofpinfo->remote_conds;
1017  }
1018  else
1019  quals = remote_conds;
1020 
1021  /* Construct FROM and WHERE clauses */
1022  deparseFromExpr(quals, &context);
1023 
1024  if (IS_UPPER_REL(rel))
1025  {
1026  /* Append GROUP BY clause */
1027  appendGroupByClause(tlist, &context);
1028 
1029  /* Append HAVING clause */
1030  if (remote_conds)
1031  {
1032  appendStringInfoString(buf, " HAVING ");
1033  appendConditions(remote_conds, &context);
1034  }
1035  }
1036 
1037  /* Add ORDER BY clause if we found any useful pathkeys */
1038  if (pathkeys)
1039  appendOrderByClause(pathkeys, has_final_sort, &context);
1040 
1041  /* Add LIMIT clause if necessary */
1042  if (has_limit)
1043  appendLimitClause(&context);
1044 
1045  /* Add any necessary FOR UPDATE/SHARE. */
1046  deparseLockingClause(&context);
1047 }
static void appendGroupByClause(List *tlist, deparse_expr_cxt *context)
Definition: deparse.c:3131
List ** params_list
Definition: deparse.c:104
#define IS_JOIN_REL(rel)
Definition: pathnodes.h:619
static void appendLimitClause(deparse_expr_cxt *context)
Definition: deparse.c:3222
RelOptInfo * outerrel
Definition: postgres_fdw.h:98
#define IS_SIMPLE_REL(rel)
Definition: pathnodes.h:614
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
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:3168
static void deparseSelectSql(List *tlist, bool is_subquery, List **retrieved_attrs, deparse_expr_cxt *context)
Definition: deparse.c:1063
static void appendConditions(List *exprs, deparse_expr_cxt *context)
Definition: deparse.c:1321
StringInfo buf
Definition: deparse.c:103
void * fdw_private
Definition: pathnodes.h:695
PlannerInfo * root
Definition: deparse.c:98
#define Assert(condition)
Definition: c.h:732
static void deparseFromExpr(List *quals, deparse_expr_cxt *context)
Definition: deparse.c:1121
#define IS_UPPER_REL(rel)
Definition: pathnodes.h:624
static void deparseLockingClause(deparse_expr_cxt *context)
Definition: deparse.c:1231
RelOptInfo * scanrel
Definition: deparse.c:100
Definition: pg_list.h:50
RelOptInfo * foreignrel
Definition: deparse.c:99

◆ deparseStringLiteral()

void deparseStringLiteral ( StringInfo  buf,
const char *  val 
)

Definition at line 2278 of file deparse.c.

References appendStringInfoChar(), ESCAPE_STRING_SYNTAX, and SQL_STR_DOUBLE.

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

2279 {
2280  const char *valptr;
2281 
2282  /*
2283  * Rather than making assumptions about the remote server's value of
2284  * standard_conforming_strings, always use E'foo' syntax if there are any
2285  * backslashes. This will fail on remote servers before 8.1, but those
2286  * are long out of support.
2287  */
2288  if (strchr(val, '\\') != NULL)
2290  appendStringInfoChar(buf, '\'');
2291  for (valptr = val; *valptr; valptr++)
2292  {
2293  char ch = *valptr;
2294 
2295  if (SQL_STR_DOUBLE(ch, true))
2296  appendStringInfoChar(buf, ch);
2297  appendStringInfoChar(buf, ch);
2298  }
2299  appendStringInfoChar(buf, '\'');
2300 }
#define ESCAPE_STRING_SYNTAX
Definition: c.h:1086
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
#define SQL_STR_DOUBLE(ch, escape_backslash)
Definition: c.h:1083
long val
Definition: informix.c:684

◆ deparseUpdateSql()

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

Definition at line 1755 of file deparse.c.

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

Referenced by postgresPlanForeignModify().

1760 {
1761  AttrNumber pindex;
1762  bool first;
1763  ListCell *lc;
1764 
1765  appendStringInfoString(buf, "UPDATE ");
1766  deparseRelation(buf, rel);
1767  appendStringInfoString(buf, " SET ");
1768 
1769  pindex = 2; /* ctid is always the first param */
1770  first = true;
1771  foreach(lc, targetAttrs)
1772  {
1773  int attnum = lfirst_int(lc);
1774 
1775  if (!first)
1776  appendStringInfoString(buf, ", ");
1777  first = false;
1778 
1779  deparseColumnRef(buf, rtindex, attnum, rte, false);
1780  appendStringInfo(buf, " = $%d", pindex);
1781  pindex++;
1782  }
1783  appendStringInfoString(buf, " WHERE ctid = $1");
1784 
1785  deparseReturningList(buf, rte, rtindex, rel,
1786  rel->trigdesc && rel->trigdesc->trig_update_after_row,
1787  withCheckOptionList, returningList, retrieved_attrs);
1788 }
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:1972
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define lfirst_int(lc)
Definition: pg_list.h:191
TriggerDesc * trigdesc
Definition: rel.h:89
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
bool trig_update_after_row
Definition: reltrigger.h:61
int16 attnum
Definition: pg_attribute.h:79
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2238
int16 AttrNumber
Definition: attnum.h:21
static void deparseColumnRef(StringInfo buf, int varno, int varattno, RangeTblEntry *rte, bool qualify_col)
Definition: deparse.c:2110

◆ ExtractConnectionOptions()

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

Definition at line 297 of file option.c.

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

Referenced by connect_pg_server().

299 {
300  ListCell *lc;
301  int i;
302 
303  /* Build our options lists if we didn't yet. */
305 
306  i = 0;
307  foreach(lc, defelems)
308  {
309  DefElem *d = (DefElem *) lfirst(lc);
310 
311  if (is_libpq_option(d->defname))
312  {
313  keywords[i] = d->defname;
314  values[i] = defGetString(d);
315  i++;
316  }
317  }
318  return i;
319 }
char * defGetString(DefElem *def)
Definition: define.c:49
#define lfirst(lc)
Definition: pg_list.h:190
static Datum values[MAXATTR]
Definition: bootstrap.c:167
int i
static bool is_libpq_option(const char *keyword)
Definition: option.c:276
char * defname
Definition: parsenodes.h:730
static void InitPgFdwOptions(void)
Definition: option.c:155

◆ ExtractExtensionList()

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

Definition at line 328 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().

329 {
330  List *extensionOids = NIL;
331  List *extlist;
332  ListCell *lc;
333 
334  /* SplitIdentifierString scribbles on its input, so pstrdup first */
335  if (!SplitIdentifierString(pstrdup(extensionsString), ',', &extlist))
336  {
337  /* syntax error in name list */
338  ereport(ERROR,
339  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
340  errmsg("parameter \"%s\" must be a list of extension names",
341  "extensions")));
342  }
343 
344  foreach(lc, extlist)
345  {
346  const char *extension_name = (const char *) lfirst(lc);
347  Oid extension_oid = get_extension_oid(extension_name, true);
348 
349  if (OidIsValid(extension_oid))
350  {
351  extensionOids = lappend_oid(extensionOids, extension_oid);
352  }
353  else if (warnOnMissing)
354  {
356  (errcode(ERRCODE_UNDEFINED_OBJECT),
357  errmsg("extension \"%s\" is not installed",
358  extension_name)));
359  }
360  }
361 
362  list_free(extlist);
363  return extensionOids;
364 }
#define NIL
Definition: pg_list.h:65
char * pstrdup(const char *in)
Definition: mcxt.c:1186
int errcode(int sqlerrcode)
Definition: elog.c:570
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:358
#define OidIsValid(objectId)
Definition: c.h:638
#define ERROR
Definition: elog.h:43
bool SplitIdentifierString(char *rawstring, char separator, List **namelist)
Definition: varlena.c:3644
#define ereport(elevel, rest)
Definition: elog.h:141
#define WARNING
Definition: elog.h:40
#define lfirst(lc)
Definition: pg_list.h:190
Oid get_extension_oid(const char *extname, bool missing_ok)
Definition: extension.c:138
int errmsg(const char *fmt,...)
Definition: elog.c:784
void list_free(List *list)
Definition: list.c:1377
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 6513 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().

6516 {
6517  ListCell *lc1;
6518  int i;
6519 
6520  i = 0;
6521  foreach(lc1, target->exprs)
6522  {
6523  Expr *expr = (Expr *) lfirst(lc1);
6524  Index sgref = get_pathtarget_sortgroupref(target, i);
6525  ListCell *lc2;
6526 
6527  /* Ignore non-sort expressions */
6528  if (sgref == 0 ||
6530  root->parse->sortClause) == NULL)
6531  {
6532  i++;
6533  continue;
6534  }
6535 
6536  /* We ignore binary-compatible relabeling on both ends */
6537  while (expr && IsA(expr, RelabelType))
6538  expr = ((RelabelType *) expr)->arg;
6539 
6540  /* Locate an EquivalenceClass member matching this expr, if any */
6541  foreach(lc2, ec->ec_members)
6542  {
6544  Expr *em_expr;
6545 
6546  /* Don't match constants */
6547  if (em->em_is_const)
6548  continue;
6549 
6550  /* Ignore child members */
6551  if (em->em_is_child)
6552  continue;
6553 
6554  /* Match if same expression (after stripping relabel) */
6555  em_expr = em->em_expr;
6556  while (em_expr && IsA(em_expr, RelabelType))
6557  em_expr = ((RelabelType *) em_expr)->arg;
6558 
6559  if (equal(em_expr, expr))
6560  return em->em_expr;
6561  }
6562 
6563  i++;
6564  }
6565 
6566  elog(ERROR, "could not find pathkey item to sort");
6567  return NULL; /* keep compiler quiet */
6568 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
Query * parse
Definition: pathnodes.h:177
List * sortClause
Definition: parsenodes.h:158
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3008
#define ERROR
Definition: elog.h:43
List * exprs
Definition: pathnodes.h:1044
SortGroupClause * get_sortgroupref_clause_noerr(Index sortref, List *clauses)
Definition: tlist.c:465
unsigned int Index
Definition: c.h:475
#define get_pathtarget_sortgroupref(target, colno)
Definition: pathnodes.h:1051
#define lfirst(lc)
Definition: pg_list.h:190
#define elog(elevel,...)
Definition: elog.h:226
int i
void * arg
List * ec_members
Definition: pathnodes.h:934

◆ find_em_expr_for_rel()

Expr* find_em_expr_for_rel ( EquivalenceClass ec,
RelOptInfo rel 
)

Definition at line 6484 of file postgres_fdw.c.

References bms_is_empty(), bms_is_subset(), EquivalenceClass::ec_members, EquivalenceMember::em_expr, EquivalenceMember::em_relids, lfirst, and RelOptInfo::relids.

Referenced by appendOrderByClause(), and get_useful_pathkeys_for_relation().

6485 {
6486  ListCell *lc_em;
6487 
6488  foreach(lc_em, ec->ec_members)
6489  {
6490  EquivalenceMember *em = lfirst(lc_em);
6491 
6492  if (bms_is_subset(em->em_relids, rel->relids) &&
6493  !bms_is_empty(em->em_relids))
6494  {
6495  /*
6496  * If there is more than one equivalence member whose Vars are
6497  * taken entirely from this relation, we'll be content to choose
6498  * any one of those.
6499  */
6500  return em->em_expr;
6501  }
6502  }
6503 
6504  /* We didn't find any suitable equivalence class expression */
6505  return NULL;
6506 }
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:315
Relids relids
Definition: pathnodes.h:641
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:701
#define lfirst(lc)
Definition: pg_list.h:190
List * ec_members
Definition: pathnodes.h:934

◆ get_jointype_name()

const char* get_jointype_name ( JoinType  jointype)

Definition at line 1355 of file deparse.c.

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

Referenced by deparseFromExprForRel(), and foreign_join_ok().

1356 {
1357  switch (jointype)
1358  {
1359  case JOIN_INNER:
1360  return "INNER";
1361 
1362  case JOIN_LEFT:
1363  return "LEFT";
1364 
1365  case JOIN_RIGHT:
1366  return "RIGHT";
1367 
1368  case JOIN_FULL:
1369  return "FULL";
1370 
1371  default:
1372  /* Shouldn't come here, but protect from buggy code. */
1373  elog(ERROR, "unsupported join type %d", jointype);
1374  }
1375 
1376  /* Keep compiler happy */
1377  return NULL;
1378 }
#define ERROR
Definition: elog.h:43
#define elog(elevel,...)
Definition: elog.h:226

◆ GetConnection()

PGconn* GetConnection ( UserMapping user,
bool  will_prep_stmt 
)

Definition at line 107 of file connection.c.

References begin_remote_xact(), CacheMemoryContext, CacheRegisterSyscacheCallback(), ConnCacheEntry::changing_xact_state, ConnCacheEntry::conn, connect_pg_server(), DEBUG3, disconnect_pg_server(), elog, HASHCTL::entrysize, FOREIGNSERVEROID, GetForeignServer(), GetSysCacheHashValue1, HASH_BLOBS, HASH_CONTEXT, hash_create(), HASH_ELEM, HASH_ENTER, hash_search(), ConnCacheEntry::have_error, ConnCacheEntry::have_prep_stmt, HASHCTL::hcxt, ConnCacheEntry::invalidated, ConnCacheEntry::key, HASHCTL::keysize, ConnCacheEntry::mapping_hashvalue, MemSet, ObjectIdGetDatum, pgfdw_inval_callback(), pgfdw_reject_incomplete_xact_state_change(), pgfdw_subxact_callback(), pgfdw_xact_callback(), RegisterSubXactCallback(), RegisterXactCallback(), ConnCacheEntry::server_hashvalue, ForeignServer::serverid, UserMapping::serverid, ForeignServer::servername, UserMapping::umid, UserMapping::userid, USERMAPPINGOID, ConnCacheEntry::xact_depth, and xact_got_connection.

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

108 {
109  bool found;
110  ConnCacheEntry *entry;
112 
113  /* First time through, initialize connection cache hashtable */
114  if (ConnectionHash == NULL)
115  {
116  HASHCTL ctl;
117 
118  MemSet(&ctl, 0, sizeof(ctl));
119  ctl.keysize = sizeof(ConnCacheKey);
120  ctl.entrysize = sizeof(ConnCacheEntry);
121  /* allocate ConnectionHash in the cache context */
122  ctl.hcxt = CacheMemoryContext;
123  ConnectionHash = hash_create("postgres_fdw connections", 8,
124  &ctl,
126 
127  /*
128  * Register some callback functions that manage connection cleanup.
129  * This should be done just once in each backend.
130  */
137  }
138 
139  /* Set flag that we did GetConnection during the current transaction */
140  xact_got_connection = true;
141 
142  /* Create hash key for the entry. Assume no pad bytes in key struct */
143  key = user->umid;
144 
145  /*
146  * Find or create cached entry for requested connection.
147  */
148  entry = hash_search(ConnectionHash, &key, HASH_ENTER, &found);
149  if (!found)
150  {
151  /*
152  * We need only clear "conn" here; remaining fields will be filled
153  * later when "conn" is set.
154  */
155  entry->conn = NULL;
156  }
157 
158  /* Reject further use of connections which failed abort cleanup. */
160 
161  /*
162  * If the connection needs to be remade due to invalidation, disconnect as
163  * soon as we're out of all transactions.
164  */
165  if (entry->conn != NULL && entry->invalidated && entry->xact_depth == 0)
166  {
167  elog(DEBUG3, "closing connection %p for option changes to take effect",
168  entry->conn);
169  disconnect_pg_server(entry);
170  }
171 
172  /*
173  * We don't check the health of cached connection here, because it would
174  * require some overhead. Broken connection will be detected when the
175  * connection is actually used.
176  */
177 
178  /*
179  * If cache entry doesn't have a connection, we have to establish a new
180  * connection. (If connect_pg_server throws an error, the cache entry
181  * will remain in a valid empty state, ie conn == NULL.)
182  */
183  if (entry->conn == NULL)
184  {
185  ForeignServer *server = GetForeignServer(user->serverid);
186 
187  /* Reset all transient state fields, to be sure all are clean */
188  entry->xact_depth = 0;
189  entry->have_prep_stmt = false;
190  entry->have_error = false;
191  entry->changing_xact_state = false;
192  entry->invalidated = false;
193  entry->server_hashvalue =
195  ObjectIdGetDatum(server->serverid));
196  entry->mapping_hashvalue =
198  ObjectIdGetDatum(user->umid));
199 
200  /* Now try to make the connection */
201  entry->conn = connect_pg_server(server, user);
202 
203  elog(DEBUG3, "new postgres_fdw connection %p for server \"%s\" (user mapping oid %u, userid %u)",
204  entry->conn, server->servername, user->umid, user->userid);
205  }
206 
207  /*
208  * Start a new transaction or subtransaction if needed.
209  */
210  begin_remote_xact(entry);
211 
212  /* Remember if caller will prepare statements */
213  entry->have_prep_stmt |= will_prep_stmt;
214 
215  return entry->conn;
216 }
Oid umid
Definition: foreign.h:47
#define HASH_CONTEXT
Definition: hsearch.h:93
#define HASH_ELEM
Definition: hsearch.h:87
MemoryContext hcxt
Definition: hsearch.h:78
#define DEBUG3
Definition: elog.h:23
struct ConnCacheEntry ConnCacheEntry
Size entrysize
Definition: hsearch.h:73
#define MemSet(start, val, len)
Definition: c.h:955
bool have_prep_stmt
Definition: connection.c:55
#define GetSysCacheHashValue1(cacheId, key1)
Definition: syscache.h:201
uint32 server_hashvalue
Definition: connection.c:59
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
Oid userid
Definition: foreign.h:48
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
bool changing_xact_state
Definition: connection.c:57
bool invalidated
Definition: connection.c:58
static void pgfdw_inval_callback(Datum arg, int cacheid, uint32 hashvalue)
Definition: connection.c:952
#define HASH_BLOBS
Definition: hsearch.h:88
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1426
static void pgfdw_xact_callback(XactEvent event, void *arg)
Definition: connection.c:651
static HTAB * ConnectionHash
Definition: connection.c:66
ForeignServer * GetForeignServer(Oid serverid)
Definition: foreign.c:109
uintptr_t Datum
Definition: postgres.h:367
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
void RegisterSubXactCallback(SubXactCallback callback, void *arg)
Definition: xact.c:3532
Size keysize
Definition: hsearch.h:72
uint32 mapping_hashvalue
Definition: connection.c:60
PGconn * conn
Definition: connection.c:51
static void disconnect_pg_server(ConnCacheEntry *entry)
Definition: connection.c:308
void RegisterXactCallback(XactCallback callback, void *arg)
Definition: xact.c:3477
static void pgfdw_reject_incomplete_xact_state_change(ConnCacheEntry *entry)
Definition: connection.c:988
static bool xact_got_connection
Definition: connection.c:73
Oid serverid
Definition: foreign.h:49
char * servername
Definition: foreign.h:39
#define elog(elevel,...)
Definition: elog.h:226
static void pgfdw_subxact_callback(SubXactEvent event, SubTransactionId mySubid, SubTransactionId parentSubid, void *arg)
Definition: connection.c:838
static void begin_remote_xact(ConnCacheEntry *entry)
Definition: connection.c:417
Oid ConnCacheKey
Definition: connection.c:46
Oid serverid
Definition: foreign.h:36
MemoryContext CacheMemoryContext
Definition: mcxt.c:47
static PGconn * connect_pg_server(ForeignServer *server, UserMapping *user)
Definition: connection.c:222

◆ GetCursorNumber()

unsigned int GetCursorNumber ( PGconn conn)

Definition at line 481 of file connection.c.

References cursor_number.

Referenced by postgresAcquireSampleRowsFunc(), and postgresBeginForeignScan().

482 {
483  return ++cursor_number;
484 }
static unsigned int cursor_number
Definition: connection.c:69

◆ GetPrepStmtNumber()

unsigned int GetPrepStmtNumber ( PGconn conn)

Definition at line 495 of file connection.c.

References prep_stmt_number.

Referenced by prepare_foreign_modify().

496 {
497  return ++prep_stmt_number;
498 }
static unsigned int prep_stmt_number
Definition: connection.c:70

◆ is_builtin()

bool is_builtin ( Oid  objectId)

Definition at line 155 of file shippable.c.

References FirstGenbkiObjectId.

Referenced by deparse_type_name(), and is_shippable().

156 {
157  return (objectId < FirstGenbkiObjectId);
158 }
#define FirstGenbkiObjectId
Definition: transam.h:139

◆ is_foreign_expr()

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

Definition at line 232 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().

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

◆ is_foreign_param()

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

Definition at line 857 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().

860 {
861  if (expr == NULL)
862  return false;
863 
864  switch (nodeTag(expr))
865  {
866  case T_Var:
867  {
868  /* It would have to be sent unless it's a foreign Var */
869  Var *var = (Var *) expr;
870  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) (baserel->fdw_private);
871  Relids relids;
872 
873  if (IS_UPPER_REL(baserel))
874  relids = fpinfo->outerrel->relids;
875  else
876  relids = baserel->relids;
877 
878  if (bms_is_member(var->varno, relids) && var->varlevelsup == 0)
879  return false; /* foreign Var, so not a param */
880  else
881  return true; /* it'd have to be a param */
882  break;
883  }
884  case T_Param:
885  /* Params always have to be sent to the foreign server */
886  return true;
887  default:
888  break;
889  }
890  return false;
891 }
Index varlevelsup
Definition: primnodes.h:177
Definition: primnodes.h:167
RelOptInfo * outerrel
Definition: postgres_fdw.h:98
Relids relids
Definition: pathnodes.h:641
Index varno
Definition: primnodes.h:170
Definition: nodes.h:151
void * fdw_private
Definition: pathnodes.h:695
#define IS_UPPER_REL(rel)
Definition: pathnodes.h:624
#define nodeTag(nodeptr)
Definition: nodes.h:530
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:427
Definition: nodes.h:153

◆ is_shippable()

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

Definition at line 165 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().

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

Definition at line 508 of file connection.c.

References ERROR, pgfdw_get_result(), pgfdw_report_error(), and PQsendQuery().

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

509 {
510  /*
511  * Submit a query. Since we don't use non-blocking mode, this also can
512  * block. But its risk is relatively small, so we ignore that for now.
513  */
514  if (!PQsendQuery(conn, query))
515  pgfdw_report_error(ERROR, NULL, conn, false, query);
516 
517  /* Wait for the result. */
518  return pgfdw_get_result(conn, query);
519 }
int PQsendQuery(PGconn *conn, const char *query)
Definition: fe-exec.c:1235
#define ERROR
Definition: elog.h:43
void pgfdw_report_error(int elevel, PGresult *res, PGconn *conn, bool clear, const char *sql)
Definition: connection.c:597
PGresult * pgfdw_get_result(PGconn *conn, const char *query)
Definition: connection.c:532

◆ pgfdw_get_result()

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

Definition at line 532 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(), pgfdw_exec_query(), and prepare_foreign_modify().

533 {
534  PGresult *volatile last_res = NULL;
535 
536  /* In what follows, do not leak any PGresults on an error. */
537  PG_TRY();
538  {
539  for (;;)
540  {
541  PGresult *res;
542 
543  while (PQisBusy(conn))
544  {
545  int wc;
546 
547  /* Sleep until there's something to do */
551  PQsocket(conn),
552  -1L, PG_WAIT_EXTENSION);
554 
556 
557  /* Data available in socket? */
558  if (wc & WL_SOCKET_READABLE)
559  {
560  if (!PQconsumeInput(conn))
561  pgfdw_report_error(ERROR, NULL, conn, false, query);
562  }
563  }
564 
565  res = PQgetResult(conn);
566  if (res == NULL)
567  break; /* query is complete */
568 
569  PQclear(last_res);
570  last_res = res;
571  }
572  }
573  PG_CATCH();
574  {
575  PQclear(last_res);
576  PG_RE_THROW();
577  }
578  PG_END_TRY();
579 
580  return last_res;
581 }
#define WL_SOCKET_READABLE
Definition: latch.h:125
void ResetLatch(Latch *latch)
Definition: latch.c:519
#define ERROR
Definition: elog.h:43
int WaitLatchOrSocket(Latch *latch, int wakeEvents, pgsocket sock, long timeout, uint32 wait_event_info)
Definition: latch.c:369
void pgfdw_report_error(int elevel, PGresult *res, PGconn *conn, bool clear, const char *sql)
Definition: connection.c:597
#define PG_WAIT_EXTENSION
Definition: pgstat.h:759
int PQconsumeInput(PGconn *conn)
Definition: fe-exec.c:1705
void PQclear(PGresult *res)
Definition: fe-exec.c:695
#define PG_CATCH()
Definition: elog.h:310
int PQisBusy(PGconn *conn)
Definition: fe-exec.c:1755
#define PG_RE_THROW()
Definition: elog.h:331
struct Latch * MyLatch
Definition: globals.c:54
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99
#define PG_TRY()
Definition: elog.h:301
#define WL_LATCH_SET
Definition: latch.h:124
int PQsocket(const PGconn *conn)
Definition: fe-connect.c:6614
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:1779
#define PG_END_TRY()
Definition: elog.h:317
#define WL_EXIT_ON_PM_DEATH
Definition: latch.h:129

◆ pgfdw_report_error()

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

Definition at line 597 of file connection.c.

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

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

599 {
600  /* If requested, PGresult must be released before leaving this function. */
601  PG_TRY();
602  {
603  char *diag_sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE);
604  char *message_primary = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY);
605  char *message_detail = PQresultErrorField(res, PG_DIAG_MESSAGE_DETAIL);
606  char *message_hint = PQresultErrorField(res, PG_DIAG_MESSAGE_HINT);
607  char *message_context = PQresultErrorField(res, PG_DIAG_CONTEXT);
608  int sqlstate;
609 
610  if (diag_sqlstate)
611  sqlstate = MAKE_SQLSTATE(diag_sqlstate[0],
612  diag_sqlstate[1],
613  diag_sqlstate[2],
614  diag_sqlstate[3],
615  diag_sqlstate[4]);
616  else
617  sqlstate = ERRCODE_CONNECTION_FAILURE;
618 
619  /*
620  * If we don't get a message from the PGresult, try the PGconn. This
621  * is needed because for connection-level failures, PQexec may just
622  * return NULL, not a PGresult at all.
623  */
624  if (message_primary == NULL)
625  message_primary = pchomp(PQerrorMessage(conn));
626 
627  ereport(elevel,
628  (errcode(sqlstate),
629  message_primary ? errmsg_internal("%s", message_primary) :
630  errmsg("could not obtain message string for remote error"),
631  message_detail ? errdetail_internal("%s", message_detail) : 0,
632  message_hint ? errhint("%s", message_hint) : 0,
633  message_context ? errcontext("%s", message_context) : 0,
634  sql ? errcontext("remote SQL command: %s", sql) : 0));
635  }
636  PG_CATCH();
637  {
638  if (clear)
639  PQclear(res);
640  PG_RE_THROW();
641  }
642  PG_END_TRY();
643  if (clear)
644  PQclear(res);
645 }
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6596
int errhint(const char *fmt,...)
Definition: elog.c:974
#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:62
int errcode(int sqlerrcode)
Definition: elog.c:570
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
int errdetail_internal(const char *fmt,...)
Definition: elog.c:887
char * pchomp(const char *in)
Definition: mcxt.c:1214
#define ereport(elevel, rest)
Definition: elog.h:141
static int elevel
Definition: vacuumlazy.c:143
#define PG_DIAG_MESSAGE_HINT
Definition: postgres_ext.h:60
void PQclear(PGresult *res)
Definition: fe-exec.c:695
int errmsg_internal(const char *fmt,...)
Definition: elog.c:814
#define PG_CATCH()
Definition: elog.h:310
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:2755
#define PG_RE_THROW()
Definition: elog.h:331
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define errcontext
Definition: elog.h:183
#define PG_TRY()
Definition: elog.h:301
#define PG_END_TRY()
Definition: elog.h:317
#define PG_DIAG_CONTEXT
Definition: postgres_ext.h:64

◆ ReleaseConnection()

void ReleaseConnection ( PGconn conn)

Definition at line 460 of file connection.c.

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

461 {
462  /*
463  * Currently, we don't actually track connection references because all
464  * cleanup is managed on a transaction or subtransaction basis instead. So
465  * there's nothing to do here.
466  */
467 }

◆ reset_transmission_modes()

void reset_transmission_modes ( int  nestlevel)

Definition at line 3447 of file postgres_fdw.c.

References AtEOXact_GUC().

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

3448 {
3449  AtEOXact_GUC(true, nestlevel);
3450 }
void AtEOXact_GUC(bool isCommit, int nestLevel)
Definition: guc.c:5729

◆ set_transmission_modes()

int set_transmission_modes ( void  )

Definition at line 3419 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().

3420 {
3421  int nestlevel = NewGUCNestLevel();
3422 
3423  /*
3424  * The values set here should match what pg_dump does. See also
3425  * configure_remote_session in connection.c.
3426  */
3427  if (DateStyle != USE_ISO_DATES)
3428  (void) set_config_option("datestyle", "ISO",
3430  GUC_ACTION_SAVE, true, 0, false);
3432  (void) set_config_option("intervalstyle", "postgres",
3434  GUC_ACTION_SAVE, true, 0, false);
3435  if (extra_float_digits < 3)
3436  (void) set_config_option("extra_float_digits", "3",
3438  GUC_ACTION_SAVE, true, 0, false);
3439 
3440  return nestlevel;
3441 }
int IntervalStyle
Definition: globals.c:117
#define USE_ISO_DATES
Definition: miscadmin.h:214
int extra_float_digits
Definition: float.c:42
int DateStyle
Definition: globals.c:115
int NewGUCNestLevel(void)
Definition: guc.c:5715
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:6722
#define INTSTYLE_POSTGRES
Definition: miscadmin.h:234