PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
postgres_fdw.h File Reference
#include "foreign/foreign.h"
#include "lib/stringinfo.h"
#include "nodes/relation.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)
 
void deparseInsertSql (StringInfo buf, PlannerInfo *root, Index rtindex, Relation rel, List *targetAttrs, bool doNothing, List *returningList, List **retrieved_attrs)
 
void deparseUpdateSql (StringInfo buf, PlannerInfo *root, Index rtindex, Relation rel, List *targetAttrs, List *returningList, List **retrieved_attrs)
 
void deparseDirectUpdateSql (StringInfo buf, PlannerInfo *root, Index rtindex, Relation rel, List *targetlist, List *targetAttrs, List *remote_conds, List **params_list, List *returningList, List **retrieved_attrs)
 
void deparseDeleteSql (StringInfo buf, PlannerInfo *root, Index rtindex, Relation rel, List *returningList, List **retrieved_attrs)
 
void deparseDirectDeleteSql (StringInfo buf, PlannerInfo *root, Index rtindex, Relation rel, 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)
 
Listbuild_tlist_to_deparse (RelOptInfo *foreignrel)
 
void deparseSelectStmtForRel (StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel, List *tlist, List *remote_conds, List *pathkeys, 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

Function Documentation

List* build_tlist_to_deparse ( RelOptInfo foreignrel)

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

869 {
870  List *tlist = NIL;
871  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
872  ListCell *lc;
873 
874  /*
875  * For an upper relation, we have already built the target list while
876  * checking shippability, so just return that.
877  */
878  if (IS_UPPER_REL(foreignrel))
879  return fpinfo->grouped_tlist;
880 
881  /*
882  * We require columns specified in foreignrel->reltarget->exprs and those
883  * required for evaluating the local conditions.
884  */
885  tlist = add_to_flat_tlist(tlist,
886  pull_var_clause((Node *) foreignrel->reltarget->exprs,
888  foreach(lc, fpinfo->local_conds)
889  {
890  RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
891 
892  tlist = add_to_flat_tlist(tlist,
893  pull_var_clause((Node *) rinfo->clause,
895  }
896 
897  return tlist;
898 }
#define NIL
Definition: pg_list.h:69
#define IS_UPPER_REL(rel)
Definition: relation.h:513
Definition: nodes.h:509
List * pull_var_clause(Node *node, int flags)
Definition: var.c:535
#define PVC_RECURSE_PLACEHOLDERS
Definition: var.h:26
#define lfirst_node(type, lc)
Definition: pg_list.h:109
Expr * clause
Definition: relation.h:1747
List * exprs
Definition: relation.h:884
void * fdw_private
Definition: relation.h:577
List * add_to_flat_tlist(List *tlist, List *exprs)
Definition: tlist.c:135
Definition: pg_list.h:45
struct PathTarget * reltarget
Definition: relation.h:536
void classifyConditions ( PlannerInfo root,
RelOptInfo baserel,
List input_conds,
List **  remote_conds,
List **  local_conds 
)

Definition at line 200 of file deparse.c.

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

Referenced by estimate_path_cost_size(), and postgresGetForeignRelSize().

205 {
206  ListCell *lc;
207 
208  *remote_conds = NIL;
209  *local_conds = NIL;
210 
211  foreach(lc, input_conds)
212  {
214 
215  if (is_foreign_expr(root, baserel, ri->clause))
216  *remote_conds = lappend(*remote_conds, ri);
217  else
218  *local_conds = lappend(*local_conds, ri);
219  }
220 }
#define NIL
Definition: pg_list.h:69
#define lfirst_node(type, lc)
Definition: pg_list.h:109
List * lappend(List *list, void *datum)
Definition: list.c:128
Expr * clause
Definition: relation.h:1747
bool is_foreign_expr(PlannerInfo *root, RelOptInfo *baserel, Expr *expr)
Definition: deparse.c:226
void deparseAnalyzeSizeSql ( StringInfo  buf,
Relation  rel 
)

Definition at line 1818 of file deparse.c.

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

Referenced by postgresAnalyzeForeignTable().

1819 {
1820  StringInfoData relname;
1821 
1822  /* We'll need the remote relation name as a literal. */
1823  initStringInfo(&relname);
1824  deparseRelation(&relname, rel);
1825 
1826  appendStringInfoString(buf, "SELECT pg_catalog.pg_relation_size(");
1827  deparseStringLiteral(buf, relname.data);
1828  appendStringInfo(buf, "::pg_catalog.regclass) / %d", BLCKSZ);
1829 }
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
void deparseStringLiteral(StringInfo buf, const char *val)
Definition: deparse.c:2084
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2044
void deparseAnalyzeSql ( StringInfo  buf,
Relation  rel,
List **  retrieved_attrs 
)

Definition at line 1838 of file deparse.c.

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

Referenced by postgresAcquireSampleRowsFunc().

1839 {
1840  Oid relid = RelationGetRelid(rel);
1841  TupleDesc tupdesc = RelationGetDescr(rel);
1842  int i;
1843  char *colname;
1844  List *options;
1845  ListCell *lc;
1846  bool first = true;
1847 
1848  *retrieved_attrs = NIL;
1849 
1850  appendStringInfoString(buf, "SELECT ");
1851  for (i = 0; i < tupdesc->natts; i++)
1852  {
1853  /* Ignore dropped columns. */
1854  if (tupdesc->attrs[i]->attisdropped)
1855  continue;
1856 
1857  if (!first)
1858  appendStringInfoString(buf, ", ");
1859  first = false;
1860 
1861  /* Use attribute name or column_name option. */
1862  colname = NameStr(tupdesc->attrs[i]->attname);
1863  options = GetForeignColumnOptions(relid, i + 1);
1864 
1865  foreach(lc, options)
1866  {
1867  DefElem *def = (DefElem *) lfirst(lc);
1868 
1869  if (strcmp(def->defname, "column_name") == 0)
1870  {
1871  colname = defGetString(def);
1872  break;
1873  }
1874  }
1875 
1877 
1878  *retrieved_attrs = lappend_int(*retrieved_attrs, i + 1);
1879  }
1880 
1881  /* Don't generate bad syntax for zero-column relation. */
1882  if (first)
1883  appendStringInfoString(buf, "NULL");
1884 
1885  /*
1886  * Construct FROM clause
1887  */
1888  appendStringInfoString(buf, " FROM ");
1889  deparseRelation(buf, rel);
1890 }
#define NIL
Definition: pg_list.h:69
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10404
#define RelationGetDescr(relation)
Definition: rel.h:428
Form_pg_attribute * attrs
Definition: tupdesc.h:74
unsigned int Oid
Definition: postgres_ext.h:31
int natts
Definition: tupdesc.h:73
List * GetForeignColumnOptions(Oid relid, AttrNumber attnum)
Definition: foreign.c:254
char * defGetString(DefElem *def)
Definition: define.c:49
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
List * lappend_int(List *list, int datum)
Definition: list.c:146
static char ** options
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2044
#define lfirst(lc)
Definition: pg_list.h:106
int i
#define NameStr(name)
Definition: c.h:499
char * defname
Definition: parsenodes.h:719
Definition: pg_list.h:45
#define RelationGetRelid(relation)
Definition: rel.h:416
void deparseDeleteSql ( StringInfo  buf,
PlannerInfo root,
Index  rtindex,
Relation  rel,
List returningList,
List **  retrieved_attrs 
)

Definition at line 1721 of file deparse.c.

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

Referenced by postgresPlanForeignModify().

1725 {
1726  appendStringInfoString(buf, "DELETE FROM ");
1727  deparseRelation(buf, rel);
1728  appendStringInfoString(buf, " WHERE ctid = $1");
1729 
1730  deparseReturningList(buf, root, rtindex, rel,
1731  rel->trigdesc && rel->trigdesc->trig_delete_after_row,
1732  returningList, retrieved_attrs);
1733 }
TriggerDesc * trigdesc
Definition: rel.h:120
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
bool trig_delete_after_row
Definition: reltrigger.h:66
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2044
static void deparseReturningList(StringInfo buf, PlannerInfo *root, Index rtindex, Relation rel, bool trig_after_row, List *returningList, List **retrieved_attrs)
Definition: deparse.c:1777
void deparseDirectDeleteSql ( StringInfo  buf,
PlannerInfo root,
Index  rtindex,
Relation  rel,
List remote_conds,
List **  params_list,
List returningList,
List **  retrieved_attrs 
)

Definition at line 1743 of file deparse.c.

References appendConditions(), appendStringInfo(), appendStringInfoString(), buf, deparse_expr_cxt::buf, deparseRelation(), deparseReturningList(), deparse_expr_cxt::foreignrel, deparse_expr_cxt::params_list, deparse_expr_cxt::root, deparse_expr_cxt::scanrel, and PlannerInfo::simple_rel_array.

Referenced by postgresPlanDirectModify().

1749 {
1750  RelOptInfo *baserel = root->simple_rel_array[rtindex];
1751  deparse_expr_cxt context;
1752 
1753  /* Set up context struct for recursion */
1754  context.root = root;
1755  context.foreignrel = baserel;
1756  context.scanrel = baserel;
1757  context.buf = buf;
1758  context.params_list = params_list;
1759 
1760  appendStringInfoString(buf, "DELETE FROM ");
1761  deparseRelation(buf, rel);
1762 
1763  if (remote_conds)
1764  {
1765  appendStringInfo(buf, " WHERE ");
1766  appendConditions(remote_conds, &context);
1767  }
1768 
1769  deparseReturningList(buf, root, rtindex, rel, false,
1770  returningList, retrieved_attrs);
1771 }
List ** params_list
Definition: deparse.c:105
struct RelOptInfo ** simple_rel_array
Definition: relation.h:179
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:66
static void appendConditions(List *exprs, deparse_expr_cxt *context)
Definition: deparse.c:1277
StringInfo buf
Definition: deparse.c:104
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2044
PlannerInfo * root
Definition: deparse.c:99
static void deparseReturningList(StringInfo buf, PlannerInfo *root, Index rtindex, Relation rel, bool trig_after_row, List *returningList, List **retrieved_attrs)
Definition: deparse.c:1777
RelOptInfo * scanrel
Definition: deparse.c:101
RelOptInfo * foreignrel
Definition: deparse.c:100
void deparseDirectUpdateSql ( StringInfo  buf,
PlannerInfo root,
Index  rtindex,
Relation  rel,
List targetlist,
List targetAttrs,
List remote_conds,
List **  params_list,
List returningList,
List **  retrieved_attrs 
)

Definition at line 1653 of file deparse.c.

References appendConditions(), appendStringInfo(), appendStringInfoString(), buf, deparse_expr_cxt::buf, deparseColumnRef(), deparseExpr(), deparseRelation(), deparseReturningList(), elog, ERROR, TargetEntry::expr, deparse_expr_cxt::foreignrel, get_tle_by_resno(), lfirst_int, deparse_expr_cxt::params_list, reset_transmission_modes(), deparse_expr_cxt::root, deparse_expr_cxt::scanrel, set_transmission_modes(), and PlannerInfo::simple_rel_array.

Referenced by postgresPlanDirectModify().

1661 {
1662  RelOptInfo *baserel = root->simple_rel_array[rtindex];
1663  deparse_expr_cxt context;
1664  int nestlevel;
1665  bool first;
1666  ListCell *lc;
1667 
1668  /* Set up context struct for recursion */
1669  context.root = root;
1670  context.foreignrel = baserel;
1671  context.scanrel = baserel;
1672  context.buf = buf;
1673  context.params_list = params_list;
1674 
1675  appendStringInfoString(buf, "UPDATE ");
1676  deparseRelation(buf, rel);
1677  appendStringInfoString(buf, " SET ");
1678 
1679  /* Make sure any constants in the exprs are printed portably */
1680  nestlevel = set_transmission_modes();
1681 
1682  first = true;
1683  foreach(lc, targetAttrs)
1684  {
1685  int attnum = lfirst_int(lc);
1686  TargetEntry *tle = get_tle_by_resno(targetlist, attnum);
1687 
1688  if (!tle)
1689  elog(ERROR, "attribute number %d not found in UPDATE targetlist",
1690  attnum);
1691 
1692  if (!first)
1693  appendStringInfoString(buf, ", ");
1694  first = false;
1695 
1696  deparseColumnRef(buf, rtindex, attnum, root, false);
1697  appendStringInfoString(buf, " = ");
1698  deparseExpr((Expr *) tle->expr, &context);
1699  }
1700 
1701  reset_transmission_modes(nestlevel);
1702 
1703  if (remote_conds)
1704  {
1705  appendStringInfo(buf, " WHERE ");
1706  appendConditions(remote_conds, &context);
1707  }
1708 
1709  deparseReturningList(buf, root, rtindex, rel, false,
1710  returningList, retrieved_attrs);
1711 }
List ** params_list
Definition: deparse.c:105
int set_transmission_modes(void)
static void deparseColumnRef(StringInfo buf, int varno, int varattno, PlannerInfo *root, bool qualify_col)
Definition: deparse.c:1899
struct RelOptInfo ** simple_rel_array
Definition: relation.h:179
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:107
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:66
static void appendConditions(List *exprs, deparse_expr_cxt *context)
Definition: deparse.c:1277
StringInfo buf
Definition: deparse.c:104
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2044
PlannerInfo * root
Definition: deparse.c:99
Expr * expr
Definition: primnodes.h:1368
void reset_transmission_modes(int nestlevel)
static void deparseExpr(Expr *expr, deparse_expr_cxt *context)
Definition: deparse.c:2119
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)
static void deparseReturningList(StringInfo buf, PlannerInfo *root, Index rtindex, Relation rel, bool trig_after_row, List *returningList, List **retrieved_attrs)
Definition: deparse.c:1777
#define elog
Definition: elog.h:219
RelOptInfo * scanrel
Definition: deparse.c:101
RelOptInfo * foreignrel
Definition: deparse.c:100
void deparseInsertSql ( StringInfo  buf,
PlannerInfo root,
Index  rtindex,
Relation  rel,
List targetAttrs,
bool  doNothing,
List returningList,
List **  retrieved_attrs 
)

Definition at line 1548 of file deparse.c.

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

Referenced by postgresPlanForeignModify().

1552 {
1553  AttrNumber pindex;
1554  bool first;
1555  ListCell *lc;
1556 
1557  appendStringInfoString(buf, "INSERT INTO ");
1558  deparseRelation(buf, rel);
1559 
1560  if (targetAttrs)
1561  {
1562  appendStringInfoChar(buf, '(');
1563 
1564  first = true;
1565  foreach(lc, targetAttrs)
1566  {
1567  int attnum = lfirst_int(lc);
1568 
1569  if (!first)
1570  appendStringInfoString(buf, ", ");
1571  first = false;
1572 
1573  deparseColumnRef(buf, rtindex, attnum, root, false);
1574  }
1575 
1576  appendStringInfoString(buf, ") VALUES (");
1577 
1578  pindex = 1;
1579  first = true;
1580  foreach(lc, targetAttrs)
1581  {
1582  if (!first)
1583  appendStringInfoString(buf, ", ");
1584  first = false;
1585 
1586  appendStringInfo(buf, "$%d", pindex);
1587  pindex++;
1588  }
1589 
1590  appendStringInfoChar(buf, ')');
1591  }
1592  else
1593  appendStringInfoString(buf, " DEFAULT VALUES");
1594 
1595  if (doNothing)
1596  appendStringInfoString(buf, " ON CONFLICT DO NOTHING");
1597 
1598  deparseReturningList(buf, root, rtindex, rel,
1599  rel->trigdesc && rel->trigdesc->trig_insert_after_row,
1600  returningList, retrieved_attrs);
1601 }
static void deparseColumnRef(StringInfo buf, int varno, int varattno, PlannerInfo *root, bool qualify_col)
Definition: deparse.c:1899
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define lfirst_int(lc)
Definition: pg_list.h:107
TriggerDesc * trigdesc
Definition: rel.h:120
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
bool trig_insert_after_row
Definition: reltrigger.h:56
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2044
static void deparseReturningList(StringInfo buf, PlannerInfo *root, Index rtindex, Relation rel, bool trig_after_row, List *returningList, List **retrieved_attrs)
Definition: deparse.c:1777
int16 AttrNumber
Definition: attnum.h:21
void deparseSelectStmtForRel ( StringInfo  buf,
PlannerInfo root,
RelOptInfo foreignrel,
List tlist,
List remote_conds,
List pathkeys,
bool  is_subquery,
List **  retrieved_attrs,
List **  params_list 
)

Definition at line 925 of file deparse.c.

References appendConditions(), appendGroupByClause(), appendOrderByClause(), appendStringInfo(), 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, deparse_expr_cxt::root, and deparse_expr_cxt::scanrel.

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

929 {
930  deparse_expr_cxt context;
931  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) rel->fdw_private;
932  List *quals;
933 
934  /*
935  * We handle relations for foreign tables, joins between those and upper
936  * relations.
937  */
938  Assert(IS_JOIN_REL(rel) || IS_SIMPLE_REL(rel) || IS_UPPER_REL(rel));
939 
940  /* Fill portions of context common to upper, join and base relation */
941  context.buf = buf;
942  context.root = root;
943  context.foreignrel = rel;
944  context.scanrel = IS_UPPER_REL(rel) ? fpinfo->outerrel : rel;
945  context.params_list = params_list;
946 
947  /* Construct SELECT clause */
948  deparseSelectSql(tlist, is_subquery, retrieved_attrs, &context);
949 
950  /*
951  * For upper relations, the WHERE clause is built from the remote
952  * conditions of the underlying scan relation; otherwise, we can use the
953  * supplied list of remote conditions directly.
954  */
955  if (IS_UPPER_REL(rel))
956  {
957  PgFdwRelationInfo *ofpinfo;
958 
959  ofpinfo = (PgFdwRelationInfo *) fpinfo->outerrel->fdw_private;
960  quals = ofpinfo->remote_conds;
961  }
962  else
963  quals = remote_conds;
964 
965  /* Construct FROM and WHERE clauses */
966  deparseFromExpr(quals, &context);
967 
968  if (IS_UPPER_REL(rel))
969  {
970  /* Append GROUP BY clause */
971  appendGroupByClause(tlist, &context);
972 
973  /* Append HAVING clause */
974  if (remote_conds)
975  {
976  appendStringInfo(buf, " HAVING ");
977  appendConditions(remote_conds, &context);
978  }
979  }
980 
981  /* Add ORDER BY clause if we found any useful pathkeys */
982  if (pathkeys)
983  appendOrderByClause(pathkeys, &context);
984 
985  /* Add any necessary FOR UPDATE/SHARE. */
986  deparseLockingClause(&context);
987 }
static void appendGroupByClause(List *tlist, deparse_expr_cxt *context)
Definition: deparse.c:2936
List ** params_list
Definition: deparse.c:105
#define IS_UPPER_REL(rel)
Definition: relation.h:513
#define IS_JOIN_REL(rel)
Definition: relation.h:510
RelOptInfo * outerrel
Definition: postgres_fdw.h:89
#define IS_SIMPLE_REL(rel)
Definition: relation.h:505
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
static void appendOrderByClause(List *pathkeys, deparse_expr_cxt *context)
Definition: deparse.c:2973
static char * buf
Definition: pg_test_fsync.c:66
static void deparseSelectSql(List *tlist, bool is_subquery, List **retrieved_attrs, deparse_expr_cxt *context)
Definition: deparse.c:1003
static void appendConditions(List *exprs, deparse_expr_cxt *context)
Definition: deparse.c:1277
StringInfo buf
Definition: deparse.c:104
void * fdw_private
Definition: relation.h:577
PlannerInfo * root
Definition: deparse.c:99
#define Assert(condition)
Definition: c.h:675
static void deparseFromExpr(List *quals, deparse_expr_cxt *context)
Definition: deparse.c:1061
static void deparseLockingClause(deparse_expr_cxt *context)
Definition: deparse.c:1187
RelOptInfo * scanrel
Definition: deparse.c:101
Definition: pg_list.h:45
RelOptInfo * foreignrel
Definition: deparse.c:100
void deparseStringLiteral ( StringInfo  buf,
const char *  val 
)

Definition at line 2084 of file deparse.c.

References appendStringInfoChar(), ESCAPE_STRING_SYNTAX, NULL, and SQL_STR_DOUBLE.

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

2085 {
2086  const char *valptr;
2087 
2088  /*
2089  * Rather than making assumptions about the remote server's value of
2090  * standard_conforming_strings, always use E'foo' syntax if there are any
2091  * backslashes. This will fail on remote servers before 8.1, but those
2092  * are long out of support.
2093  */
2094  if (strchr(val, '\\') != NULL)
2096  appendStringInfoChar(buf, '\'');
2097  for (valptr = val; *valptr; valptr++)
2098  {
2099  char ch = *valptr;
2100 
2101  if (SQL_STR_DOUBLE(ch, true))
2102  appendStringInfoChar(buf, ch);
2103  appendStringInfoChar(buf, ch);
2104  }
2105  appendStringInfoChar(buf, '\'');
2106 }
#define ESCAPE_STRING_SYNTAX
Definition: c.h:510
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
#define NULL
Definition: c.h:229
#define SQL_STR_DOUBLE(ch, escape_backslash)
Definition: c.h:507
long val
Definition: informix.c:689
void deparseUpdateSql ( StringInfo  buf,
PlannerInfo root,
Index  rtindex,
Relation  rel,
List targetAttrs,
List returningList,
List **  retrieved_attrs 
)

Definition at line 1611 of file deparse.c.

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

Referenced by postgresPlanForeignModify().

1615 {
1616  AttrNumber pindex;
1617  bool first;
1618  ListCell *lc;
1619 
1620  appendStringInfoString(buf, "UPDATE ");
1621  deparseRelation(buf, rel);
1622  appendStringInfoString(buf, " SET ");
1623 
1624  pindex = 2; /* ctid is always the first param */
1625  first = true;
1626  foreach(lc, targetAttrs)
1627  {
1628  int attnum = lfirst_int(lc);
1629 
1630  if (!first)
1631  appendStringInfoString(buf, ", ");
1632  first = false;
1633 
1634  deparseColumnRef(buf, rtindex, attnum, root, false);
1635  appendStringInfo(buf, " = $%d", pindex);
1636  pindex++;
1637  }
1638  appendStringInfoString(buf, " WHERE ctid = $1");
1639 
1640  deparseReturningList(buf, root, rtindex, rel,
1641  rel->trigdesc && rel->trigdesc->trig_update_after_row,
1642  returningList, retrieved_attrs);
1643 }
static void deparseColumnRef(StringInfo buf, int varno, int varattno, PlannerInfo *root, bool qualify_col)
Definition: deparse.c:1899
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define lfirst_int(lc)
Definition: pg_list.h:107
TriggerDesc * trigdesc
Definition: rel.h:120
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
bool trig_update_after_row
Definition: reltrigger.h:61
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2044
static void deparseReturningList(StringInfo buf, PlannerInfo *root, Index rtindex, Relation rel, bool trig_after_row, List *returningList, List **retrieved_attrs)
Definition: deparse.c:1777
int16 AttrNumber
Definition: attnum.h:21
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:106
static Datum values[MAXATTR]
Definition: bootstrap.c:163
int i
static bool is_libpq_option(const char *keyword)
Definition: option.c:276
char * defname
Definition: parsenodes.h:719
static void InitPgFdwOptions(void)
Definition: option.c:155
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:69
char * pstrdup(const char *in)
Definition: mcxt.c:1077
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
#define OidIsValid(objectId)
Definition: c.h:538
#define ERROR
Definition: elog.h:43
bool SplitIdentifierString(char *rawstring, char separator, List **namelist)
Definition: varlena.c:3260
#define ereport(elevel, rest)
Definition: elog.h:122
#define WARNING
Definition: elog.h:40
#define lfirst(lc)
Definition: pg_list.h:106
Oid get_extension_oid(const char *extname, bool missing_ok)
Definition: extension.c:135
int errmsg(const char *fmt,...)
Definition: elog.c:797
void list_free(List *list)
Definition: list.c:1133
Definition: pg_list.h:45
Expr* find_em_expr_for_rel ( EquivalenceClass ec,
RelOptInfo rel 
)

Definition at line 5153 of file postgres_fdw.c.

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

Referenced by appendOrderByClause(), and get_useful_pathkeys_for_relation().

5154 {
5155  ListCell *lc_em;
5156 
5157  foreach(lc_em, ec->ec_members)
5158  {
5159  EquivalenceMember *em = lfirst(lc_em);
5160 
5161  if (bms_is_subset(em->em_relids, rel->relids))
5162  {
5163  /*
5164  * If there is more than one equivalence member whose Vars are
5165  * taken entirely from this relation, we'll be content to choose
5166  * any one of those.
5167  */
5168  return em->em_expr;
5169  }
5170  }
5171 
5172  /* We didn't find any suitable equivalence class expression */
5173  return NULL;
5174 }
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:308
Relids relids
Definition: relation.h:525
Relids em_relids
Definition: relation.h:823
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
List * ec_members
Definition: relation.h:774
const char* get_jointype_name ( JoinType  jointype)

Definition at line 1311 of file deparse.c.

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

Referenced by deparseFromExprForRel(), and foreign_join_ok().

1312 {
1313  switch (jointype)
1314  {
1315  case JOIN_INNER:
1316  return "INNER";
1317 
1318  case JOIN_LEFT:
1319  return "LEFT";
1320 
1321  case JOIN_RIGHT:
1322  return "RIGHT";
1323 
1324  case JOIN_FULL:
1325  return "FULL";
1326 
1327  default:
1328  /* Shouldn't come here, but protect from buggy code. */
1329  elog(ERROR, "unsupported join type %d", jointype);
1330  }
1331 
1332  /* Keep compiler happy */
1333  return NULL;
1334 }
#define ERROR
Definition: elog.h:43
#define NULL
Definition: c.h:229
#define elog
Definition: elog.h:219
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, HASHCTL::keysize, ConnCacheEntry::mapping_hashvalue, MemSet, NULL, 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 dumpBlobs(), dumpDatabase(), dumpTableData_copy(), estimate_path_cost_size(), expand_schema_name_patterns(), expand_table_name_patterns(), getTables(), main(), postgresAcquireSampleRowsFunc(), postgresAnalyzeForeignTable(), postgresBeginDirectModify(), postgresBeginForeignModify(), postgresBeginForeignScan(), postgresImportForeignSchema(), setup_connection(), StartLogStreamer(), StreamLog(), and StreamLogicalLog().

108 {
109  bool found;
110  ConnCacheEntry *entry;
111  ConnCacheKey key;
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:58
#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:857
bool have_prep_stmt
Definition: connection.c:55
#define GetSysCacheHashValue1(cacheId, key1)
Definition: syscache.h:192
uint32 server_hashvalue
Definition: connection.c:59
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
Oid userid
Definition: foreign.h:59
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
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:951
#define HASH_BLOBS
Definition: hsearch.h:88
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1389
static void pgfdw_xact_callback(XactEvent event, void *arg)
Definition: connection.c:650
static HTAB * ConnectionHash
Definition: connection.c:66
ForeignServer * GetForeignServer(Oid serverid)
Definition: foreign.c:93
uintptr_t Datum
Definition: postgres.h:372
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:301
void RegisterSubXactCallback(SubXactCallback callback, void *arg)
Definition: xact.c:3361
Size keysize
Definition: hsearch.h:72
uint32 mapping_hashvalue
Definition: connection.c:60
PGconn * conn
Definition: connection.c:51
#define NULL
Definition: c.h:229
static void disconnect_pg_server(ConnCacheEntry *entry)
Definition: connection.c:308
void RegisterXactCallback(XactCallback callback, void *arg)
Definition: xact.c:3306
static void pgfdw_reject_incomplete_xact_state_change(ConnCacheEntry *entry)
Definition: connection.c:987
static bool xact_got_connection
Definition: connection.c:73
Oid serverid
Definition: foreign.h:60
char * servername
Definition: foreign.h:50
#define elog
Definition: elog.h:219
static void pgfdw_subxact_callback(SubXactEvent event, SubTransactionId mySubid, SubTransactionId parentSubid, void *arg)
Definition: connection.c:837
static void begin_remote_xact(ConnCacheEntry *entry)
Definition: connection.c:417
Oid ConnCacheKey
Definition: connection.c:46
Oid serverid
Definition: foreign.h:47
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
static PGconn * connect_pg_server(ForeignServer *server, UserMapping *user)
Definition: connection.c:222
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
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
bool is_builtin ( Oid  objectId)

Definition at line 155 of file shippable.c.

References FirstBootstrapObjectId.

Referenced by deparse_type_name(), and is_shippable().

156 {
157  return (objectId < FirstBootstrapObjectId);
158 }
#define FirstBootstrapObjectId
Definition: transam.h:93
bool is_foreign_expr ( PlannerInfo root,
RelOptInfo baserel,
Expr expr 
)

Definition at line 226 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 classifyConditions(), foreign_grouping_ok(), foreign_join_ok(), get_useful_pathkeys_for_relation(), postgresGetForeignPaths(), postgresGetForeignPlan(), and postgresPlanDirectModify().

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

Referenced by foreign_expr_walker().

166 {
167  ShippableCacheKey key;
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:69
bool is_builtin(Oid objectId)
Definition: shippable.c:155
ForeignServer * server
Definition: postgres_fdw.h:76
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
static void InitializeShippableCache(void)
Definition: shippable.c:93
static bool lookup_shippable(Oid objectId, Oid classId, PgFdwRelationInfo *fpinfo)
Definition: shippable.c:119
#define NULL
Definition: c.h:229
static HTAB * ShippableCacheHash
Definition: shippable.c:36
List * shippable_extensions
Definition: postgres_fdw.h:72
Oid serverid
Definition: foreign.h:47
PGresult* pgfdw_exec_query ( PGconn conn,
const char *  query 
)

Definition at line 508 of file connection.c.

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

Referenced by close_cursor(), fetch_more_data(), get_remote_estimate(), postgresAcquireSampleRowsFunc(), postgresAnalyzeForeignTable(), postgresEndForeignModify(), 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:1132
#define ERROR
Definition: elog.h:43
void pgfdw_report_error(int elevel, PGresult *res, PGconn *conn, bool clear, const char *sql)
Definition: connection.c:596
PGresult * pgfdw_get_result(PGconn *conn, const char *query)
Definition: connection.c:532
#define NULL
Definition: c.h:229
PGresult* pgfdw_get_result ( PGconn conn,
const char *  query 
)

Definition at line 532 of file connection.c.

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

Referenced by create_cursor(), do_sql_command(), execute_dml_stmt(), pgfdw_exec_query(), postgresExecForeignDelete(), postgresExecForeignInsert(), postgresExecForeignUpdate(), 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 */
550  PQsocket(conn),
551  -1L, PG_WAIT_EXTENSION);
553 
555 
556  /* Data available in socket? */
557  if (wc & WL_SOCKET_READABLE)
558  {
559  if (!PQconsumeInput(conn))
560  pgfdw_report_error(ERROR, NULL, conn, false, query);
561  }
562  }
563 
564  res = PQgetResult(conn);
565  if (res == NULL)
566  break; /* query is complete */
567 
568  PQclear(last_res);
569  last_res = res;
570  }
571  }
572  PG_CATCH();
573  {
574  PQclear(last_res);
575  PG_RE_THROW();
576  }
577  PG_END_TRY();
578 
579  return last_res;
580 }
#define WL_SOCKET_READABLE
Definition: latch.h:125
void ResetLatch(volatile Latch *latch)
Definition: latch.c:498
#define ERROR
Definition: elog.h:43
void pgfdw_report_error(int elevel, PGresult *res, PGconn *conn, bool clear, const char *sql)
Definition: connection.c:596
#define PG_WAIT_EXTENSION
Definition: pgstat.h:742
int PQconsumeInput(PGconn *conn)
Definition: fe-exec.c:1631
void PQclear(PGresult *res)
Definition: fe-exec.c:650
#define PG_CATCH()
Definition: elog.h:293
#define NULL
Definition: c.h:229
int WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock, long timeout, uint32 wait_event_info)
Definition: latch.c:356
int PQisBusy(PGconn *conn)
Definition: fe-exec.c:1681
#define PG_RE_THROW()
Definition: elog.h:314
struct Latch * MyLatch
Definition: globals.c:52
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
#define PG_TRY()
Definition: elog.h:284
#define WL_LATCH_SET
Definition: latch.h:124
int PQsocket(const PGconn *conn)
Definition: fe-connect.c:6115
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:1702
#define PG_END_TRY()
Definition: elog.h:300
void pgfdw_report_error ( int  elevel,
PGresult res,
PGconn conn,
bool  clear,
const char *  sql 
)

Definition at line 596 of file connection.c.

References ereport, errcode(), errcontext, errdetail_internal(), errhint(), errmsg(), errmsg_internal(), MAKE_SQLSTATE, NULL, 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(), fetch_more_data(), get_remote_estimate(), pgfdw_exec_cleanup_query(), pgfdw_exec_query(), pgfdw_get_result(), postgresAcquireSampleRowsFunc(), postgresAnalyzeForeignTable(), postgresEndForeignModify(), postgresExecForeignDelete(), postgresExecForeignInsert(), postgresExecForeignUpdate(), postgresImportForeignSchema(), postgresReScanForeignScan(), and prepare_foreign_modify().

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

Definition at line 460 of file connection.c.

Referenced by estimate_path_cost_size(), postgresAcquireSampleRowsFunc(), postgresAnalyzeForeignTable(), postgresEndDirectModify(), postgresEndForeignModify(), 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 }
void reset_transmission_modes ( int  nestlevel)

Definition at line 3106 of file postgres_fdw.c.

References AtEOXact_GUC().

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

3107 {
3108  AtEOXact_GUC(true, nestlevel);
3109 }
void AtEOXact_GUC(bool isCommit, int nestLevel)
Definition: guc.c:5079
int set_transmission_modes ( void  )

Definition at line 3078 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(), appendOrderByClause(), convert_prep_stmt_params(), deparseDirectUpdateSql(), and process_query_params().

3079 {
3080  int nestlevel = NewGUCNestLevel();
3081 
3082  /*
3083  * The values set here should match what pg_dump does. See also
3084  * configure_remote_session in connection.c.
3085  */
3086  if (DateStyle != USE_ISO_DATES)
3087  (void) set_config_option("datestyle", "ISO",
3089  GUC_ACTION_SAVE, true, 0, false);
3091  (void) set_config_option("intervalstyle", "postgres",
3093  GUC_ACTION_SAVE, true, 0, false);
3094  if (extra_float_digits < 3)
3095  (void) set_config_option("extra_float_digits", "3",
3097  GUC_ACTION_SAVE, true, 0, false);
3098 
3099  return nestlevel;
3100 }
int IntervalStyle
Definition: globals.c:109
#define USE_ISO_DATES
Definition: miscadmin.h:211
int extra_float_digits
Definition: float.c:68
int DateStyle
Definition: globals.c:107
int NewGUCNestLevel(void)
Definition: guc.c:5065
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:5908
#define INTSTYLE_POSTGRES
Definition: miscadmin.h:231