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

Go to the source code of this file.

Data Structures

struct  PgFdwRelationInfo
 

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 938 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().

939 {
940  List *tlist = NIL;
941  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
942  ListCell *lc;
943 
944  /*
945  * For an upper relation, we have already built the target list while
946  * checking shippability, so just return that.
947  */
948  if (IS_UPPER_REL(foreignrel))
949  return fpinfo->grouped_tlist;
950 
951  /*
952  * We require columns specified in foreignrel->reltarget->exprs and those
953  * required for evaluating the local conditions.
954  */
955  tlist = add_to_flat_tlist(tlist,
956  pull_var_clause((Node *) foreignrel->reltarget->exprs,
958  foreach(lc, fpinfo->local_conds)
959  {
960  RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
961 
962  tlist = add_to_flat_tlist(tlist,
963  pull_var_clause((Node *) rinfo->clause,
965  }
966 
967  return tlist;
968 }
#define NIL
Definition: pg_list.h:65
#define PVC_RECURSE_PLACEHOLDERS
Definition: optimizer.h:177
Definition: nodes.h:527
List * pull_var_clause(Node *node, int flags)
Definition: var.c:535
#define lfirst_node(type, lc)
Definition: pg_list.h:172
Expr * clause
Definition: pathnodes.h:1991
List * exprs
Definition: pathnodes.h:1078
void * fdw_private
Definition: pathnodes.h:720
List * add_to_flat_tlist(List *tlist, List *exprs)
Definition: tlist.c:154
#define IS_UPPER_REL(rel)
Definition: pathnodes.h:649
Definition: pg_list.h:50
struct PathTarget * reltarget
Definition: pathnodes.h:677

◆ classifyConditions()

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

Definition at line 204 of file deparse.c.

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

Referenced by estimate_path_cost_size(), and postgresGetForeignRelSize().

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

◆ deparseAnalyzeSizeSql()

void deparseAnalyzeSizeSql ( StringInfo  buf,
Relation  rel 
)

Definition at line 2043 of file deparse.c.

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

Referenced by postgresAnalyzeForeignTable().

2044 {
2046 
2047  /* We'll need the remote relation name as a literal. */
2048  initStringInfo(&relname);
2049  deparseRelation(&relname, rel);
2050 
2051  appendStringInfoString(buf, "SELECT pg_catalog.pg_relation_size(");
2052  deparseStringLiteral(buf, relname.data);
2053  appendStringInfo(buf, "::pg_catalog.regclass) / %d", BLCKSZ);
2054 }
NameData relname
Definition: pg_class.h:38
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
void deparseStringLiteral(StringInfo buf, const char *val)
Definition: deparse.c:2292
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2252

◆ deparseAnalyzeSql()

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

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

2064 {
2065  Oid relid = RelationGetRelid(rel);
2066  TupleDesc tupdesc = RelationGetDescr(rel);
2067  int i;
2068  char *colname;
2069  List *options;
2070  ListCell *lc;
2071  bool first = true;
2072 
2073  *retrieved_attrs = NIL;
2074 
2075  appendStringInfoString(buf, "SELECT ");
2076  for (i = 0; i < tupdesc->natts; i++)
2077  {
2078  /* Ignore dropped columns. */
2079  if (TupleDescAttr(tupdesc, i)->attisdropped)
2080  continue;
2081 
2082  if (!first)
2083  appendStringInfoString(buf, ", ");
2084  first = false;
2085 
2086  /* Use attribute name or column_name option. */
2087  colname = NameStr(TupleDescAttr(tupdesc, i)->attname);
2088  options = GetForeignColumnOptions(relid, i + 1);
2089 
2090  foreach(lc, options)
2091  {
2092  DefElem *def = (DefElem *) lfirst(lc);
2093 
2094  if (strcmp(def->defname, "column_name") == 0)
2095  {
2096  colname = defGetString(def);
2097  break;
2098  }
2099  }
2100 
2102 
2103  *retrieved_attrs = lappend_int(*retrieved_attrs, i + 1);
2104  }
2105 
2106  /* Don't generate bad syntax for zero-column relation. */
2107  if (first)
2108  appendStringInfoString(buf, "NULL");
2109 
2110  /*
2111  * Construct FROM clause
2112  */
2113  appendStringInfoString(buf, " FROM ");
2114  deparseRelation(buf, rel);
2115 }
#define NIL
Definition: pg_list.h:65
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10934
#define RelationGetDescr(relation)
Definition: rel.h:483
#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:176
List * lappend_int(List *list, int datum)
Definition: list.c:339
static char ** options
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2252
#define lfirst(lc)
Definition: pg_list.h:169
int i
#define NameStr(name)
Definition: c.h:677
char * defname
Definition: parsenodes.h:733
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:457

◆ deparseDeleteSql()

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

Definition at line 1906 of file deparse.c.

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

Referenced by postgresPlanForeignModify().

1910 {
1911  appendStringInfoString(buf, "DELETE FROM ");
1912  deparseRelation(buf, rel);
1913  appendStringInfoString(buf, " WHERE ctid = $1");
1914 
1915  deparseReturningList(buf, rte, rtindex, rel,
1916  rel->trigdesc && rel->trigdesc->trig_delete_after_row,
1917  NIL, returningList, retrieved_attrs);
1918 }
#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:1986
TriggerDesc * trigdesc
Definition: rel.h:116
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
bool trig_delete_after_row
Definition: reltrigger.h:67
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2252

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

1942 {
1943  deparse_expr_cxt context;
1944 
1945  /* Set up context struct for recursion */
1946  context.root = root;
1947  context.foreignrel = foreignrel;
1948  context.scanrel = foreignrel;
1949  context.buf = buf;
1950  context.params_list = params_list;
1951 
1952  appendStringInfoString(buf, "DELETE FROM ");
1953  deparseRelation(buf, rel);
1954  if (foreignrel->reloptkind == RELOPT_JOINREL)
1955  appendStringInfo(buf, " %s%d", REL_ALIAS_PREFIX, rtindex);
1956 
1957  if (foreignrel->reloptkind == RELOPT_JOINREL)
1958  {
1959  List *ignore_conds = NIL;
1960 
1961  appendStringInfoString(buf, " USING ");
1962  deparseFromExprForRel(buf, root, foreignrel, true, rtindex,
1963  &ignore_conds, params_list);
1964  remote_conds = list_concat(remote_conds, ignore_conds);
1965  }
1966 
1967  if (remote_conds)
1968  {
1969  appendStringInfoString(buf, " WHERE ");
1970  appendConditions(remote_conds, &context);
1971  }
1972 
1973  if (foreignrel->reloptkind == RELOPT_JOINREL)
1974  deparseExplicitTargetList(returningList, true, retrieved_attrs,
1975  &context);
1976  else
1977  deparseReturningList(buf, planner_rt_fetch(rtindex, root),
1978  rtindex, rel, false,
1979  NIL, returningList, retrieved_attrs);
1980 }
#define NIL
Definition: pg_list.h:65
RelOptKind reloptkind
Definition: pathnodes.h:663
List ** params_list
Definition: deparse.c:102
List * list_concat(List *list1, const List *list2)
Definition: list.c:515
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:1986
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define planner_rt_fetch(rti, root)
Definition: pathnodes.h:377
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:68
#define REL_ALIAS_PREFIX
Definition: deparse.c:105
static void deparseExplicitTargetList(List *tlist, bool is_returning, List **retrieved_attrs, deparse_expr_cxt *context)
Definition: deparse.c:1406
static void appendConditions(List *exprs, deparse_expr_cxt *context)
Definition: deparse.c:1335
StringInfo buf
Definition: deparse.c:101
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2252
PlannerInfo * root
Definition: deparse.c:96
static void deparseFromExprForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel, bool use_alias, Index ignore_rel, List **ignore_conds, List **params_list)
Definition: deparse.c:1483
RelOptInfo * scanrel
Definition: deparse.c:98
Definition: pg_list.h:50
RelOptInfo * foreignrel
Definition: deparse.c:97

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

1830 {
1831  deparse_expr_cxt context;
1832  int nestlevel;
1833  bool first;
1834  ListCell *lc;
1835  RangeTblEntry *rte = planner_rt_fetch(rtindex, root);
1836 
1837  /* Set up context struct for recursion */
1838  context.root = root;
1839  context.foreignrel = foreignrel;
1840  context.scanrel = foreignrel;
1841  context.buf = buf;
1842  context.params_list = params_list;
1843 
1844  appendStringInfoString(buf, "UPDATE ");
1845  deparseRelation(buf, rel);
1846  if (foreignrel->reloptkind == RELOPT_JOINREL)
1847  appendStringInfo(buf, " %s%d", REL_ALIAS_PREFIX, rtindex);
1848  appendStringInfoString(buf, " SET ");
1849 
1850  /* Make sure any constants in the exprs are printed portably */
1851  nestlevel = set_transmission_modes();
1852 
1853  first = true;
1854  foreach(lc, targetAttrs)
1855  {
1856  int attnum = lfirst_int(lc);
1857  TargetEntry *tle = get_tle_by_resno(targetlist, attnum);
1858 
1859  if (!tle)
1860  elog(ERROR, "attribute number %d not found in UPDATE targetlist",
1861  attnum);
1862 
1863  if (!first)
1864  appendStringInfoString(buf, ", ");
1865  first = false;
1866 
1867  deparseColumnRef(buf, rtindex, attnum, rte, false);
1868  appendStringInfoString(buf, " = ");
1869  deparseExpr((Expr *) tle->expr, &context);
1870  }
1871 
1872  reset_transmission_modes(nestlevel);
1873 
1874  if (foreignrel->reloptkind == RELOPT_JOINREL)
1875  {
1876  List *ignore_conds = NIL;
1877 
1878  appendStringInfoString(buf, " FROM ");
1879  deparseFromExprForRel(buf, root, foreignrel, true, rtindex,
1880  &ignore_conds, params_list);
1881  remote_conds = list_concat(remote_conds, ignore_conds);
1882  }
1883 
1884  if (remote_conds)
1885  {
1886  appendStringInfoString(buf, " WHERE ");
1887  appendConditions(remote_conds, &context);
1888  }
1889 
1890  if (foreignrel->reloptkind == RELOPT_JOINREL)
1891  deparseExplicitTargetList(returningList, true, retrieved_attrs,
1892  &context);
1893  else
1894  deparseReturningList(buf, rte, rtindex, rel, false,
1895  NIL, returningList, retrieved_attrs);
1896 }
#define NIL
Definition: pg_list.h:65
RelOptKind reloptkind
Definition: pathnodes.h:663
List ** params_list
Definition: deparse.c:102
int set_transmission_modes(void)
List * list_concat(List *list1, const List *list2)
Definition: list.c:515
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:1986
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define ERROR
Definition: elog.h:43
#define lfirst_int(lc)
Definition: pg_list.h:170
#define planner_rt_fetch(rti, root)
Definition: pathnodes.h:377
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:68
#define REL_ALIAS_PREFIX
Definition: deparse.c:105
static void deparseExplicitTargetList(List *tlist, bool is_returning, List **retrieved_attrs, deparse_expr_cxt *context)
Definition: deparse.c:1406
static void appendConditions(List *exprs, deparse_expr_cxt *context)
Definition: deparse.c:1335
StringInfo buf
Definition: deparse.c:101
int16 attnum
Definition: pg_attribute.h:79
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2252
PlannerInfo * root
Definition: deparse.c:96
Expr * expr
Definition: primnodes.h:1422
void reset_transmission_modes(int nestlevel)
static void deparseExpr(Expr *expr, deparse_expr_cxt *context)
Definition: deparse.c:2327
static void deparseFromExprForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel, bool use_alias, Index ignore_rel, List **ignore_conds, List **params_list)
Definition: deparse.c:1483
#define elog(elevel,...)
Definition: elog.h:228
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)
RelOptInfo * scanrel
Definition: deparse.c:98
Definition: pg_list.h:50
RelOptInfo * foreignrel
Definition: deparse.c:97
static void deparseColumnRef(StringInfo buf, int varno, int varattno, RangeTblEntry *rte, bool qualify_col)
Definition: deparse.c:2124

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

1710 {
1711  AttrNumber pindex;
1712  bool first;
1713  ListCell *lc;
1714 
1715  appendStringInfoString(buf, "INSERT INTO ");
1716  deparseRelation(buf, rel);
1717 
1718  if (targetAttrs)
1719  {
1720  appendStringInfoChar(buf, '(');
1721 
1722  first = true;
1723  foreach(lc, targetAttrs)
1724  {
1725  int attnum = lfirst_int(lc);
1726 
1727  if (!first)
1728  appendStringInfoString(buf, ", ");
1729  first = false;
1730 
1731  deparseColumnRef(buf, rtindex, attnum, rte, false);
1732  }
1733 
1734  appendStringInfoString(buf, ") VALUES (");
1735 
1736  pindex = 1;
1737  first = true;
1738  foreach(lc, targetAttrs)
1739  {
1740  if (!first)
1741  appendStringInfoString(buf, ", ");
1742  first = false;
1743 
1744  appendStringInfo(buf, "$%d", pindex);
1745  pindex++;
1746  }
1747 
1748  appendStringInfoChar(buf, ')');
1749  }
1750  else
1751  appendStringInfoString(buf, " DEFAULT VALUES");
1752 
1753  if (doNothing)
1754  appendStringInfoString(buf, " ON CONFLICT DO NOTHING");
1755 
1756  deparseReturningList(buf, rte, rtindex, rel,
1757  rel->trigdesc && rel->trigdesc->trig_insert_after_row,
1758  withCheckOptionList, returningList, retrieved_attrs);
1759 }
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:1986
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define lfirst_int(lc)
Definition: pg_list.h:170
TriggerDesc * trigdesc
Definition: rel.h:116
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
bool trig_insert_after_row
Definition: reltrigger.h:57
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
int16 attnum
Definition: pg_attribute.h:79
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2252
int16 AttrNumber
Definition: attnum.h:21
static void deparseColumnRef(StringInfo buf, int varno, int varattno, RangeTblEntry *rte, bool qualify_col)
Definition: deparse.c:2124

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

999 {
1000  deparse_expr_cxt context;
1001  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) rel->fdw_private;
1002  List *quals;
1003 
1004  /*
1005  * We handle relations for foreign tables, joins between those and upper
1006  * relations.
1007  */
1008  Assert(IS_JOIN_REL(rel) || IS_SIMPLE_REL(rel) || IS_UPPER_REL(rel));
1009 
1010  /* Fill portions of context common to upper, join and base relation */
1011  context.buf = buf;
1012  context.root = root;
1013  context.foreignrel = rel;
1014  context.scanrel = IS_UPPER_REL(rel) ? fpinfo->outerrel : rel;
1015  context.params_list = params_list;
1016 
1017  /* Construct SELECT clause */
1018  deparseSelectSql(tlist, is_subquery, retrieved_attrs, &context);
1019 
1020  /*
1021  * For upper relations, the WHERE clause is built from the remote
1022  * conditions of the underlying scan relation; otherwise, we can use the
1023  * supplied list of remote conditions directly.
1024  */
1025  if (IS_UPPER_REL(rel))
1026  {
1027  PgFdwRelationInfo *ofpinfo;
1028 
1029  ofpinfo = (PgFdwRelationInfo *) fpinfo->outerrel->fdw_private;
1030  quals = ofpinfo->remote_conds;
1031  }
1032  else
1033  quals = remote_conds;
1034 
1035  /* Construct FROM and WHERE clauses */
1036  deparseFromExpr(quals, &context);
1037 
1038  if (IS_UPPER_REL(rel))
1039  {
1040  /* Append GROUP BY clause */
1041  appendGroupByClause(tlist, &context);
1042 
1043  /* Append HAVING clause */
1044  if (remote_conds)
1045  {
1046  appendStringInfoString(buf, " HAVING ");
1047  appendConditions(remote_conds, &context);
1048  }
1049  }
1050 
1051  /* Add ORDER BY clause if we found any useful pathkeys */
1052  if (pathkeys)
1053  appendOrderByClause(pathkeys, has_final_sort, &context);
1054 
1055  /* Add LIMIT clause if necessary */
1056  if (has_limit)
1057  appendLimitClause(&context);
1058 
1059  /* Add any necessary FOR UPDATE/SHARE. */
1060  deparseLockingClause(&context);
1061 }
static void appendGroupByClause(List *tlist, deparse_expr_cxt *context)
Definition: deparse.c:3138
List ** params_list
Definition: deparse.c:102
#define IS_JOIN_REL(rel)
Definition: pathnodes.h:644
static void appendLimitClause(deparse_expr_cxt *context)
Definition: deparse.c:3229
RelOptInfo * outerrel
Definition: postgres_fdw.h:100
#define IS_SIMPLE_REL(rel)
Definition: pathnodes.h:639
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:68
static void appendOrderByClause(List *pathkeys, bool has_final_sort, deparse_expr_cxt *context)
Definition: deparse.c:3175
static void deparseSelectSql(List *tlist, bool is_subquery, List **retrieved_attrs, deparse_expr_cxt *context)
Definition: deparse.c:1077
static void appendConditions(List *exprs, deparse_expr_cxt *context)
Definition: deparse.c:1335
StringInfo buf
Definition: deparse.c:101
void * fdw_private
Definition: pathnodes.h:720
PlannerInfo * root
Definition: deparse.c:96
#define Assert(condition)
Definition: c.h:800
static void deparseFromExpr(List *quals, deparse_expr_cxt *context)
Definition: deparse.c:1135
#define IS_UPPER_REL(rel)
Definition: pathnodes.h:649
static void deparseLockingClause(deparse_expr_cxt *context)
Definition: deparse.c:1245
RelOptInfo * scanrel
Definition: deparse.c:98
Definition: pg_list.h:50
RelOptInfo * foreignrel
Definition: deparse.c:97

◆ deparseStringLiteral()

void deparseStringLiteral ( StringInfo  buf,
const char *  val 
)

Definition at line 2292 of file deparse.c.

References appendStringInfoChar(), ESCAPE_STRING_SYNTAX, and SQL_STR_DOUBLE.

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

2293 {
2294  const char *valptr;
2295 
2296  /*
2297  * Rather than making assumptions about the remote server's value of
2298  * standard_conforming_strings, always use E'foo' syntax if there are any
2299  * backslashes. This will fail on remote servers before 8.1, but those
2300  * are long out of support.
2301  */
2302  if (strchr(val, '\\') != NULL)
2304  appendStringInfoChar(buf, '\'');
2305  for (valptr = val; *valptr; valptr++)
2306  {
2307  char ch = *valptr;
2308 
2309  if (SQL_STR_DOUBLE(ch, true))
2310  appendStringInfoChar(buf, ch);
2311  appendStringInfoChar(buf, ch);
2312  }
2313  appendStringInfoChar(buf, '\'');
2314 }
#define ESCAPE_STRING_SYNTAX
Definition: c.h:1163
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
#define SQL_STR_DOUBLE(ch, escape_backslash)
Definition: c.h:1160
long val
Definition: informix.c:664

◆ deparseUpdateSql()

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

Definition at line 1769 of file deparse.c.

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

Referenced by postgresPlanForeignModify().

1774 {
1775  AttrNumber pindex;
1776  bool first;
1777  ListCell *lc;
1778 
1779  appendStringInfoString(buf, "UPDATE ");
1780  deparseRelation(buf, rel);
1781  appendStringInfoString(buf, " SET ");
1782 
1783  pindex = 2; /* ctid is always the first param */
1784  first = true;
1785  foreach(lc, targetAttrs)
1786  {
1787  int attnum = lfirst_int(lc);
1788 
1789  if (!first)
1790  appendStringInfoString(buf, ", ");
1791  first = false;
1792 
1793  deparseColumnRef(buf, rtindex, attnum, rte, false);
1794  appendStringInfo(buf, " = $%d", pindex);
1795  pindex++;
1796  }
1797  appendStringInfoString(buf, " WHERE ctid = $1");
1798 
1799  deparseReturningList(buf, rte, rtindex, rel,
1800  rel->trigdesc && rel->trigdesc->trig_update_after_row,
1801  withCheckOptionList, returningList, retrieved_attrs);
1802 }
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:1986
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define lfirst_int(lc)
Definition: pg_list.h:170
TriggerDesc * trigdesc
Definition: rel.h:116
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
bool trig_update_after_row
Definition: reltrigger.h:62
int16 attnum
Definition: pg_attribute.h:79
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2252
int16 AttrNumber
Definition: attnum.h:21
static void deparseColumnRef(StringInfo buf, int varno, int varattno, RangeTblEntry *rte, bool qualify_col)
Definition: deparse.c:2124

◆ ExtractConnectionOptions()

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

Definition at line 333 of file option.c.

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

Referenced by connect_pg_server().

335 {
336  ListCell *lc;
337  int i;
338 
339  /* Build our options lists if we didn't yet. */
341 
342  i = 0;
343  foreach(lc, defelems)
344  {
345  DefElem *d = (DefElem *) lfirst(lc);
346 
347  if (is_libpq_option(d->defname))
348  {
349  keywords[i] = d->defname;
350  values[i] = defGetString(d);
351  i++;
352  }
353  }
354  return i;
355 }
char * defGetString(DefElem *def)
Definition: define.c:49
#define lfirst(lc)
Definition: pg_list.h:169
static Datum values[MAXATTR]
Definition: bootstrap.c:165
int i
static bool is_libpq_option(const char *keyword)
Definition: option.c:312
char * defname
Definition: parsenodes.h:733
static void InitPgFdwOptions(void)
Definition: option.c:181

◆ ExtractExtensionList()

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

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

365 {
366  List *extensionOids = NIL;
367  List *extlist;
368  ListCell *lc;
369 
370  /* SplitIdentifierString scribbles on its input, so pstrdup first */
371  if (!SplitIdentifierString(pstrdup(extensionsString), ',', &extlist))
372  {
373  /* syntax error in name list */
374  ereport(ERROR,
375  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
376  errmsg("parameter \"%s\" must be a list of extension names",
377  "extensions")));
378  }
379 
380  foreach(lc, extlist)
381  {
382  const char *extension_name = (const char *) lfirst(lc);
383  Oid extension_oid = get_extension_oid(extension_name, true);
384 
385  if (OidIsValid(extension_oid))
386  {
387  extensionOids = lappend_oid(extensionOids, extension_oid);
388  }
389  else if (warnOnMissing)
390  {
392  (errcode(ERRCODE_UNDEFINED_OBJECT),
393  errmsg("extension \"%s\" is not installed",
394  extension_name)));
395  }
396  }
397 
398  list_free(extlist);
399  return extensionOids;
400 }
#define NIL
Definition: pg_list.h:65
char * pstrdup(const char *in)
Definition: mcxt.c:1187
int errcode(int sqlerrcode)
Definition: elog.c:691
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:357
#define OidIsValid(objectId)
Definition: c.h:706
#define ERROR
Definition: elog.h:43
bool SplitIdentifierString(char *rawstring, char separator, List **namelist)
Definition: varlena.c:3716
#define WARNING
Definition: elog.h:40
#define ereport(elevel,...)
Definition: elog.h:155
#define lfirst(lc)
Definition: pg_list.h:169
Oid get_extension_oid(const char *extname, bool missing_ok)
Definition: extension.c:140
int errmsg(const char *fmt,...)
Definition: elog.c:902
void list_free(List *list)
Definition: list.c:1376
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 6524 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().

6527 {
6528  ListCell *lc1;
6529  int i;
6530 
6531  i = 0;
6532  foreach(lc1, target->exprs)
6533  {
6534  Expr *expr = (Expr *) lfirst(lc1);
6535  Index sgref = get_pathtarget_sortgroupref(target, i);
6536  ListCell *lc2;
6537 
6538  /* Ignore non-sort expressions */
6539  if (sgref == 0 ||
6541  root->parse->sortClause) == NULL)
6542  {
6543  i++;
6544  continue;
6545  }
6546 
6547  /* We ignore binary-compatible relabeling on both ends */
6548  while (expr && IsA(expr, RelabelType))
6549  expr = ((RelabelType *) expr)->arg;
6550 
6551  /* Locate an EquivalenceClass member matching this expr, if any */
6552  foreach(lc2, ec->ec_members)
6553  {
6555  Expr *em_expr;
6556 
6557  /* Don't match constants */
6558  if (em->em_is_const)
6559  continue;
6560 
6561  /* Ignore child members */
6562  if (em->em_is_child)
6563  continue;
6564 
6565  /* Match if same expression (after stripping relabel) */
6566  em_expr = em->em_expr;
6567  while (em_expr && IsA(em_expr, RelabelType))
6568  em_expr = ((RelabelType *) em_expr)->arg;
6569 
6570  if (equal(em_expr, expr))
6571  return em->em_expr;
6572  }
6573 
6574  i++;
6575  }
6576 
6577  elog(ERROR, "could not find pathkey item to sort");
6578  return NULL; /* keep compiler quiet */
6579 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:578
Query * parse
Definition: pathnodes.h:173
List * sortClause
Definition: parsenodes.h:158
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3028
#define ERROR
Definition: elog.h:43
List * exprs
Definition: pathnodes.h:1078
SortGroupClause * get_sortgroupref_clause_noerr(Index sortref, List *clauses)
Definition: tlist.c:465
unsigned int Index
Definition: c.h:537
#define get_pathtarget_sortgroupref(target, colno)
Definition: pathnodes.h:1085
#define lfirst(lc)
Definition: pg_list.h:169
#define elog(elevel,...)
Definition: elog.h:228
int i
void * arg
List * ec_members
Definition: pathnodes.h:968

◆ find_em_expr_for_rel()

Expr* find_em_expr_for_rel ( EquivalenceClass ec,
RelOptInfo rel 
)

Definition at line 776 of file equivclass.c.

Referenced by appendOrderByClause(), and get_useful_pathkeys_for_relation().

777 {
778  ListCell *lc_em;
779 
780  foreach(lc_em, ec->ec_members)
781  {
782  EquivalenceMember *em = lfirst(lc_em);
783 
784  if (bms_is_subset(em->em_relids, rel->relids) &&
785  !bms_is_empty(em->em_relids))
786  {
787  /*
788  * If there is more than one equivalence member whose Vars are
789  * taken entirely from this relation, we'll be content to choose
790  * any one of those.
791  */
792  return em->em_expr;
793  }
794  }
795 
796  /* We didn't find any suitable equivalence class expression */
797  return NULL;
798 }
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:315
Relids relids
Definition: pathnodes.h:666
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:701
#define lfirst(lc)
Definition: pg_list.h:169
List * ec_members
Definition: pathnodes.h:968

◆ get_jointype_name()

const char* get_jointype_name ( JoinType  jointype)

Definition at line 1369 of file deparse.c.

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

Referenced by deparseFromExprForRel(), and foreign_join_ok().

1370 {
1371  switch (jointype)
1372  {
1373  case JOIN_INNER:
1374  return "INNER";
1375 
1376  case JOIN_LEFT:
1377  return "LEFT";
1378 
1379  case JOIN_RIGHT:
1380  return "RIGHT";
1381 
1382  case JOIN_FULL:
1383  return "FULL";
1384 
1385  default:
1386  /* Shouldn't come here, but protect from buggy code. */
1387  elog(ERROR, "unsupported join type %d", jointype);
1388  }
1389 
1390  /* Keep compiler happy */
1391  return NULL;
1392 }
#define ERROR
Definition: elog.h:43
#define elog(elevel,...)
Definition: elog.h:228

◆ GetConnection()

PGconn* GetConnection ( UserMapping user,
bool  will_prep_stmt 
)

Definition at line 109 of file connection.c.

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

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

110 {
111  bool found;
112  bool retry = false;
113  ConnCacheEntry *entry;
116 
117  /* First time through, initialize connection cache hashtable */
118  if (ConnectionHash == NULL)
119  {
120  HASHCTL ctl;
121 
122  MemSet(&ctl, 0, sizeof(ctl));
123  ctl.keysize = sizeof(ConnCacheKey);
124  ctl.entrysize = sizeof(ConnCacheEntry);
125  /* allocate ConnectionHash in the cache context */
126  ctl.hcxt = CacheMemoryContext;
127  ConnectionHash = hash_create("postgres_fdw connections", 8,
128  &ctl,
130 
131  /*
132  * Register some callback functions that manage connection cleanup.
133  * This should be done just once in each backend.
134  */
141  }
142 
143  /* Set flag that we did GetConnection during the current transaction */
144  xact_got_connection = true;
145 
146  /* Create hash key for the entry. Assume no pad bytes in key struct */
147  key = user->umid;
148 
149  /*
150  * Find or create cached entry for requested connection.
151  */
152  entry = hash_search(ConnectionHash, &key, HASH_ENTER, &found);
153  if (!found)
154  {
155  /*
156  * We need only clear "conn" here; remaining fields will be filled
157  * later when "conn" is set.
158  */
159  entry->conn = NULL;
160  }
161 
162  /* Reject further use of connections which failed abort cleanup. */
164 
165  /*
166  * If the connection needs to be remade due to invalidation, disconnect as
167  * soon as we're out of all transactions.
168  */
169  if (entry->conn != NULL && entry->invalidated && entry->xact_depth == 0)
170  {
171  elog(DEBUG3, "closing connection %p for option changes to take effect",
172  entry->conn);
173  disconnect_pg_server(entry);
174  }
175 
176  /*
177  * If cache entry doesn't have a connection, we have to establish a new
178  * connection. (If connect_pg_server throws an error, the cache entry
179  * will remain in a valid empty state, ie conn == NULL.)
180  */
181  if (entry->conn == NULL)
182  make_new_connection(entry, user);
183 
184  /*
185  * We check the health of the cached connection here when starting a new
186  * remote transaction. If a broken connection is detected, we try to
187  * reestablish a new connection later.
188  */
189  PG_TRY();
190  {
191  /* Start a new transaction or subtransaction if needed. */
192  begin_remote_xact(entry);
193  }
194  PG_CATCH();
195  {
197  ErrorData *errdata = CopyErrorData();
198 
199  /*
200  * If connection failure is reported when starting a new remote
201  * transaction (not subtransaction), new connection will be
202  * reestablished later.
203  *
204  * After a broken connection is detected in libpq, any error other
205  * than connection failure (e.g., out-of-memory) can be thrown
206  * somewhere between return from libpq and the expected ereport() call
207  * in pgfdw_report_error(). In this case, since PQstatus() indicates
208  * CONNECTION_BAD, checking only PQstatus() causes the false detection
209  * of connection failure. To avoid this, we also verify that the
210  * error's sqlstate is ERRCODE_CONNECTION_FAILURE. Note that also
211  * checking only the sqlstate can cause another false detection
212  * because pgfdw_report_error() may report ERRCODE_CONNECTION_FAILURE
213  * for any libpq-originated error condition.
214  */
215  if (errdata->sqlerrcode != ERRCODE_CONNECTION_FAILURE ||
216  PQstatus(entry->conn) != CONNECTION_BAD ||
217  entry->xact_depth > 0)
218  {
219  MemoryContextSwitchTo(ecxt);
220  PG_RE_THROW();
221  }
222 
223  /* Clean up the error state */
224  FlushErrorState();
225  FreeErrorData(errdata);
226  errdata = NULL;
227 
228  retry = true;
229  }
230  PG_END_TRY();
231 
232  /*
233  * If a broken connection is detected, disconnect it, reestablish a new
234  * connection and retry a new remote transaction. If connection failure is
235  * reported again, we give up getting a connection.
236  */
237  if (retry)
238  {
239  Assert(entry->xact_depth == 0);
240 
241  ereport(DEBUG3,
242  (errmsg_internal("could not start remote transaction on connection %p",
243  entry->conn)),
244  errdetail_internal("%s", pchomp(PQerrorMessage(entry->conn))));
245 
246  elog(DEBUG3, "closing connection %p to reestablish a new one",
247  entry->conn);
248  disconnect_pg_server(entry);
249 
250  if (entry->conn == NULL)
251  make_new_connection(entry, user);
252 
253  begin_remote_xact(entry);
254  }
255 
256  /* Remember if caller will prepare statements */
257  entry->have_prep_stmt |= will_prep_stmt;
258 
259  return entry->conn;
260 }
Oid umid
Definition: foreign.h:47
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6669
#define HASH_CONTEXT
Definition: hsearch.h:91
#define HASH_ELEM
Definition: hsearch.h:85
MemoryContext hcxt
Definition: hsearch.h:77
int sqlerrcode
Definition: elog.h:378
#define DEBUG3
Definition: elog.h:23
struct ConnCacheEntry ConnCacheEntry
ErrorData * CopyErrorData(void)
Definition: elog.c:1552
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Size entrysize
Definition: hsearch.h:72
#define MemSet(start, val, len)
Definition: c.h:1004
bool have_prep_stmt
Definition: connection.c:56
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:919
void FlushErrorState(void)
Definition: elog.c:1646
int errdetail_internal(const char *fmt,...)
Definition: elog.c:1062
char * pchomp(const char *in)
Definition: mcxt.c:1215
void FreeErrorData(ErrorData *edata)
Definition: elog.c:1608
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
bool invalidated
Definition: connection.c:59
static void pgfdw_inval_callback(Datum arg, int cacheid, uint32 hashvalue)
Definition: connection.c:1087
#define HASH_BLOBS
Definition: hsearch.h:86
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1434
static void pgfdw_xact_callback(XactEvent event, void *arg)
Definition: connection.c:786
static HTAB * ConnectionHash
Definition: connection.c:67
uintptr_t Datum
Definition: postgres.h:367
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:326
void RegisterSubXactCallback(SubXactCallback callback, void *arg)
Definition: xact.c:3584
Size keysize
Definition: hsearch.h:71
#define ereport(elevel,...)
Definition: elog.h:155
int errmsg_internal(const char *fmt,...)
Definition: elog.c:989
#define PG_CATCH()
Definition: elog.h:319
PGconn * conn
Definition: connection.c:52
static void disconnect_pg_server(ConnCacheEntry *entry)
Definition: connection.c:417
#define Assert(condition)
Definition: c.h:800
void RegisterXactCallback(XactCallback callback, void *arg)
Definition: xact.c:3529
static void pgfdw_reject_incomplete_xact_state_change(ConnCacheEntry *entry)
Definition: connection.c:1123
static bool xact_got_connection
Definition: connection.c:74
#define PG_RE_THROW()
Definition: elog.h:350
static void make_new_connection(ConnCacheEntry *entry, UserMapping *user)
Definition: connection.c:267
#define elog(elevel,...)
Definition: elog.h:228
static void pgfdw_subxact_callback(SubXactEvent event, SubTransactionId mySubid, SubTransactionId parentSubid, void *arg)
Definition: connection.c:973
ConnStatusType PQstatus(const PGconn *conn)
Definition: fe-connect.c:6616
#define PG_TRY()
Definition: elog.h:309
static void begin_remote_xact(ConnCacheEntry *entry)
Definition: connection.c:551
Oid ConnCacheKey
Definition: connection.c:47
#define PG_END_TRY()
Definition: elog.h:334
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ GetCursorNumber()

unsigned int GetCursorNumber ( PGconn conn)

Definition at line 615 of file connection.c.

References cursor_number.

Referenced by postgresAcquireSampleRowsFunc(), and postgresBeginForeignScan().

616 {
617  return ++cursor_number;
618 }
static unsigned int cursor_number
Definition: connection.c:70

◆ GetPrepStmtNumber()

unsigned int GetPrepStmtNumber ( PGconn conn)

Definition at line 629 of file connection.c.

References prep_stmt_number.

Referenced by prepare_foreign_modify().

630 {
631  return ++prep_stmt_number;
632 }
static unsigned int prep_stmt_number
Definition: connection.c:71

◆ is_builtin()

bool is_builtin ( Oid  objectId)

Definition at line 153 of file shippable.c.

References FirstGenbkiObjectId.

Referenced by deparse_type_name(), and is_shippable().

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

◆ is_foreign_expr()

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

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

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

◆ is_foreign_param()

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

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

874 {
875  if (expr == NULL)
876  return false;
877 
878  switch (nodeTag(expr))
879  {
880  case T_Var:
881  {
882  /* It would have to be sent unless it's a foreign Var */
883  Var *var = (Var *) expr;
884  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) (baserel->fdw_private);
885  Relids relids;
886 
887  if (IS_UPPER_REL(baserel))
888  relids = fpinfo->outerrel->relids;
889  else
890  relids = baserel->relids;
891 
892  if (bms_is_member(var->varno, relids) && var->varlevelsup == 0)
893  return false; /* foreign Var, so not a param */
894  else
895  return true; /* it'd have to be a param */
896  break;
897  }
898  case T_Param:
899  /* Params always have to be sent to the foreign server */
900  return true;
901  default:
902  break;
903  }
904  return false;
905 }
Index varlevelsup
Definition: primnodes.h:191
Definition: primnodes.h:181
RelOptInfo * outerrel
Definition: postgres_fdw.h:100
Relids relids
Definition: pathnodes.h:666
Index varno
Definition: primnodes.h:184
Definition: nodes.h:153
void * fdw_private
Definition: pathnodes.h:720
#define IS_UPPER_REL(rel)
Definition: pathnodes.h:649
#define nodeTag(nodeptr)
Definition: nodes.h:532
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:427
Definition: nodes.h:155

◆ is_shippable()

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

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

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

◆ pgfdw_exec_query()

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

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

643 {
644  /*
645  * Submit a query. Since we don't use non-blocking mode, this also can
646  * block. But its risk is relatively small, so we ignore that for now.
647  */
648  if (!PQsendQuery(conn, query))
649  pgfdw_report_error(ERROR, NULL, conn, false, query);
650 
651  /* Wait for the result. */
652  return pgfdw_get_result(conn, query);
653 }
int PQsendQuery(PGconn *conn, const char *query)
Definition: fe-exec.c:1234
#define ERROR
Definition: elog.h:43
void pgfdw_report_error(int elevel, PGresult *res, PGconn *conn, bool clear, const char *sql)
Definition: connection.c:731
PGresult * pgfdw_get_result(PGconn *conn, const char *query)
Definition: connection.c:666

◆ pgfdw_get_result()

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

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

667 {
668  PGresult *volatile last_res = NULL;
669 
670  /* In what follows, do not leak any PGresults on an error. */
671  PG_TRY();
672  {
673  for (;;)
674  {
675  PGresult *res;
676 
677  while (PQisBusy(conn))
678  {
679  int wc;
680 
681  /* Sleep until there's something to do */
685  PQsocket(conn),
686  -1L, PG_WAIT_EXTENSION);
688 
690 
691  /* Data available in socket? */
692  if (wc & WL_SOCKET_READABLE)
693  {
694  if (!PQconsumeInput(conn))
695  pgfdw_report_error(ERROR, NULL, conn, false, query);
696  }
697  }
698 
699  res = PQgetResult(conn);
700  if (res == NULL)
701  break; /* query is complete */
702 
703  PQclear(last_res);
704  last_res = res;
705  }
706  }
707  PG_CATCH();
708  {
709  PQclear(last_res);
710  PG_RE_THROW();
711  }
712  PG_END_TRY();
713 
714  return last_res;
715 }
#define WL_SOCKET_READABLE
Definition: latch.h:125
void ResetLatch(Latch *latch)
Definition: latch.c:588
#define ERROR
Definition: elog.h:43
int WaitLatchOrSocket(Latch *latch, int wakeEvents, pgsocket sock, long timeout, uint32 wait_event_info)
Definition: latch.c:438
void pgfdw_report_error(int elevel, PGresult *res, PGconn *conn, bool clear, const char *sql)
Definition: connection.c:731
#define PG_WAIT_EXTENSION
Definition: pgstat.h:860
int PQconsumeInput(PGconn *conn)
Definition: fe-exec.c:1704
void PQclear(PGresult *res)
Definition: fe-exec.c:694
#define PG_CATCH()
Definition: elog.h:319
int PQisBusy(PGconn *conn)
Definition: fe-exec.c:1754
#define PG_RE_THROW()
Definition: elog.h:350
struct Latch * MyLatch
Definition: globals.c:54
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99
#define PG_TRY()
Definition: elog.h:309
#define WL_LATCH_SET
Definition: latch.h:124
int PQsocket(const PGconn *conn)
Definition: fe-connect.c:6687
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:1778
#define PG_END_TRY()
Definition: elog.h:334
#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 731 of file connection.c.

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

Referenced by close_cursor(), create_cursor(), 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().

733 {
734  /* If requested, PGresult must be released before leaving this function. */
735  PG_TRY();
736  {
737  char *diag_sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE);
738  char *message_primary = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY);
739  char *message_detail = PQresultErrorField(res, PG_DIAG_MESSAGE_DETAIL);
740  char *message_hint = PQresultErrorField(res, PG_DIAG_MESSAGE_HINT);
741  char *message_context = PQresultErrorField(res, PG_DIAG_CONTEXT);
742  int sqlstate;
743 
744  if (diag_sqlstate)
745  sqlstate = MAKE_SQLSTATE(diag_sqlstate[0],
746  diag_sqlstate[1],
747  diag_sqlstate[2],
748  diag_sqlstate[3],
749  diag_sqlstate[4]);
750  else
751  sqlstate = ERRCODE_CONNECTION_FAILURE;
752 
753  /*
754  * If we don't get a message from the PGresult, try the PGconn. This
755  * is needed because for connection-level failures, PQexec may just
756  * return NULL, not a PGresult at all.
757  */
758  if (message_primary == NULL)
759  message_primary = pchomp(PQerrorMessage(conn));
760 
761  ereport(elevel,
762  (errcode(sqlstate),
763  message_primary ? errmsg_internal("%s", message_primary) :
764  errmsg("could not obtain message string for remote error"),
765  message_detail ? errdetail_internal("%s", message_detail) : 0,
766  message_hint ? errhint("%s", message_hint) : 0,
767  message_context ? errcontext("%s", message_context) : 0,
768  sql ? errcontext("remote SQL command: %s", sql) : 0));
769  }
770  PG_FINALLY();
771  {
772  if (clear)
773  PQclear(res);
774  }
775  PG_END_TRY();
776 }
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6669
int errhint(const char *fmt,...)
Definition: elog.c:1149
#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:691
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
int errdetail_internal(const char *fmt,...)
Definition: elog.c:1062
char * pchomp(const char *in)
Definition: mcxt.c:1215
static int elevel
Definition: vacuumlazy.c:333
#define PG_FINALLY()
Definition: elog.h:326
#define PG_DIAG_MESSAGE_HINT
Definition: postgres_ext.h:60
#define ereport(elevel,...)
Definition: elog.h:155
void PQclear(PGresult *res)
Definition: fe-exec.c:694
int errmsg_internal(const char *fmt,...)
Definition: elog.c:989
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:2754
int errmsg(const char *fmt,...)
Definition: elog.c:902
#define errcontext
Definition: elog.h:199
#define PG_TRY()
Definition: elog.h:309
#define PG_END_TRY()
Definition: elog.h:334
#define PG_DIAG_CONTEXT
Definition: postgres_ext.h:64

◆ ReleaseConnection()

void ReleaseConnection ( PGconn conn)

Definition at line 594 of file connection.c.

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

595 {
596  /*
597  * Currently, we don't actually track connection references because all
598  * cleanup is managed on a transaction or subtransaction basis instead. So
599  * there's nothing to do here.
600  */
601 }

◆ reset_transmission_modes()

void reset_transmission_modes ( int  nestlevel)

Definition at line 3494 of file postgres_fdw.c.

References AtEOXact_GUC().

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

3495 {
3496  AtEOXact_GUC(true, nestlevel);
3497 }
void AtEOXact_GUC(bool isCommit, int nestLevel)
Definition: guc.c:5962

◆ set_transmission_modes()

int set_transmission_modes ( void  )

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

3467 {
3468  int nestlevel = NewGUCNestLevel();
3469 
3470  /*
3471  * The values set here should match what pg_dump does. See also
3472  * configure_remote_session in connection.c.
3473  */
3474  if (DateStyle != USE_ISO_DATES)
3475  (void) set_config_option("datestyle", "ISO",
3477  GUC_ACTION_SAVE, true, 0, false);
3479  (void) set_config_option("intervalstyle", "postgres",
3481  GUC_ACTION_SAVE, true, 0, false);
3482  if (extra_float_digits < 3)
3483  (void) set_config_option("extra_float_digits", "3",
3485  GUC_ACTION_SAVE, true, 0, false);
3486 
3487  return nestlevel;
3488 }
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:5948
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:7012
#define INTSTYLE_POSTGRES
Definition: miscadmin.h:234