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

Go to the source code of this file.

Data Structures

struct  PgFdwRelationInfo
 
struct  PgFdwConnState
 

Typedefs

typedef struct PgFdwRelationInfo PgFdwRelationInfo
 
typedef struct PgFdwConnState PgFdwConnState
 

Functions

int set_transmission_modes (void)
 
void reset_transmission_modes (int nestlevel)
 
void process_pending_request (AsyncRequest *areq)
 
PGconnGetConnection (UserMapping *user, bool will_prep_stmt, PgFdwConnState **state)
 
void ReleaseConnection (PGconn *conn)
 
unsigned int GetCursorNumber (PGconn *conn)
 
unsigned int GetPrepStmtNumber (PGconn *conn)
 
void do_sql_command (PGconn *conn, const char *sql)
 
PGresultpgfdw_get_result (PGconn *conn, const char *query)
 
PGresultpgfdw_exec_query (PGconn *conn, const char *query, PgFdwConnState *state)
 
void pgfdw_report_error (int elevel, PGresult *res, PGconn *conn, bool clear, const char *sql)
 
int ExtractConnectionOptions (List *defelems, const char **keywords, const char **values)
 
ListExtractExtensionList (const char *extensionsString, bool warnOnMissing)
 
char * process_pgfdw_appname (const char *appname)
 
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)
 
bool is_foreign_pathkey (PlannerInfo *root, RelOptInfo *baserel, PathKey *pathkey)
 
void deparseInsertSql (StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, List *targetAttrs, bool doNothing, List *withCheckOptionList, List *returningList, List **retrieved_attrs, int *values_end_len)
 
void rebuildInsertSql (StringInfo buf, Relation rel, char *orig_query, List *target_attrs, int values_end_len, int num_params, int num_rows)
 
void deparseUpdateSql (StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, List *targetAttrs, List *withCheckOptionList, List *returningList, List **retrieved_attrs)
 
void deparseDirectUpdateSql (StringInfo buf, PlannerInfo *root, Index rtindex, Relation rel, RelOptInfo *foreignrel, List *targetlist, List *targetAttrs, List *remote_conds, List **params_list, List *returningList, List **retrieved_attrs)
 
void deparseDeleteSql (StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, List *returningList, List **retrieved_attrs)
 
void deparseDirectDeleteSql (StringInfo buf, PlannerInfo *root, Index rtindex, Relation rel, RelOptInfo *foreignrel, List *remote_conds, List **params_list, List *returningList, List **retrieved_attrs)
 
void deparseAnalyzeSizeSql (StringInfo buf, Relation rel)
 
void deparseAnalyzeSql (StringInfo buf, Relation rel, List **retrieved_attrs)
 
void deparseTruncateSql (StringInfo buf, List *rels, DropBehavior behavior, bool restart_seqs)
 
void deparseStringLiteral (StringInfo buf, const char *val)
 
EquivalenceMemberfind_em_for_rel (PlannerInfo *root, EquivalenceClass *ec, RelOptInfo *rel)
 
EquivalenceMemberfind_em_for_rel_target (PlannerInfo *root, 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 has_final_sort, bool has_limit, bool is_subquery, List **retrieved_attrs, List **params_list)
 
const char * get_jointype_name (JoinType jointype)
 
bool is_builtin (Oid objectId)
 
bool is_shippable (Oid objectId, Oid classId, PgFdwRelationInfo *fpinfo)
 

Variables

char * pgfdw_application_name
 

Typedef Documentation

◆ PgFdwConnState

◆ PgFdwRelationInfo

Function Documentation

◆ build_tlist_to_deparse()

List* build_tlist_to_deparse ( RelOptInfo foreignrel)

Definition at line 1102 of file deparse.c.

1103 {
1104  List *tlist = NIL;
1105  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
1106  ListCell *lc;
1107 
1108  /*
1109  * For an upper relation, we have already built the target list while
1110  * checking shippability, so just return that.
1111  */
1112  if (IS_UPPER_REL(foreignrel))
1113  return fpinfo->grouped_tlist;
1114 
1115  /*
1116  * We require columns specified in foreignrel->reltarget->exprs and those
1117  * required for evaluating the local conditions.
1118  */
1119  tlist = add_to_flat_tlist(tlist,
1120  pull_var_clause((Node *) foreignrel->reltarget->exprs,
1122  foreach(lc, fpinfo->local_conds)
1123  {
1124  RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
1125 
1126  tlist = add_to_flat_tlist(tlist,
1127  pull_var_clause((Node *) rinfo->clause,
1129  }
1130 
1131  return tlist;
1132 }
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
#define PVC_RECURSE_PLACEHOLDERS
Definition: optimizer.h:193
#define IS_UPPER_REL(rel)
Definition: pathnodes.h:673
#define lfirst_node(type, lc)
Definition: pg_list.h:174
#define NIL
Definition: pg_list.h:66
Definition: pg_list.h:52
Definition: nodes.h:575
List * exprs
Definition: pathnodes.h:1265
void * fdw_private
Definition: pathnodes.h:788
struct PathTarget * reltarget
Definition: pathnodes.h:715
Expr * clause
Definition: pathnodes.h:2234
List * add_to_flat_tlist(List *tlist, List *exprs)
Definition: tlist.c:121
List * pull_var_clause(Node *node, int flags)
Definition: var.c:604

References add_to_flat_tlist(), RestrictInfo::clause, PathTarget::exprs, RelOptInfo::fdw_private, PgFdwRelationInfo::grouped_tlist, if(), 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().

◆ classifyConditions()

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

Definition at line 211 of file deparse.c.

216 {
217  ListCell *lc;
218 
219  *remote_conds = NIL;
220  *local_conds = NIL;
221 
222  foreach(lc, input_conds)
223  {
225 
226  if (is_foreign_expr(root, baserel, ri->clause))
227  *remote_conds = lappend(*remote_conds, ri);
228  else
229  *local_conds = lappend(*local_conds, ri);
230  }
231 }
bool is_foreign_expr(PlannerInfo *root, RelOptInfo *baserel, Expr *expr)
Definition: deparse.c:237
List * lappend(List *list, void *datum)
Definition: list.c:338

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

Referenced by estimate_path_cost_size(), and postgresGetForeignRelSize().

◆ deparseAnalyzeSizeSql()

void deparseAnalyzeSizeSql ( StringInfo  buf,
Relation  rel 
)

Definition at line 2287 of file deparse.c.

2288 {
2290 
2291  /* We'll need the remote relation name as a literal. */
2293  deparseRelation(&relname, rel);
2294 
2295  appendStringInfoString(buf, "SELECT pg_catalog.pg_relation_size(");
2297  appendStringInfo(buf, "::pg_catalog.regclass) / %d", BLCKSZ);
2298 }
void deparseStringLiteral(StringInfo buf, const char *val)
Definition: deparse.c:2568
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2528
NameData relname
Definition: pg_class.h:38
static char * buf
Definition: pg_test_fsync.c:67
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
char data[NAMEDATALEN]
Definition: c.h:688

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

Referenced by postgresAnalyzeForeignTable().

◆ deparseAnalyzeSql()

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

Definition at line 2307 of file deparse.c.

2308 {
2309  Oid relid = RelationGetRelid(rel);
2310  TupleDesc tupdesc = RelationGetDescr(rel);
2311  int i;
2312  char *colname;
2313  List *options;
2314  ListCell *lc;
2315  bool first = true;
2316 
2317  *retrieved_attrs = NIL;
2318 
2319  appendStringInfoString(buf, "SELECT ");
2320  for (i = 0; i < tupdesc->natts; i++)
2321  {
2322  /* Ignore dropped columns. */
2323  if (TupleDescAttr(tupdesc, i)->attisdropped)
2324  continue;
2325 
2326  if (!first)
2327  appendStringInfoString(buf, ", ");
2328  first = false;
2329 
2330  /* Use attribute name or column_name option. */
2331  colname = NameStr(TupleDescAttr(tupdesc, i)->attname);
2332  options = GetForeignColumnOptions(relid, i + 1);
2333 
2334  foreach(lc, options)
2335  {
2336  DefElem *def = (DefElem *) lfirst(lc);
2337 
2338  if (strcmp(def->defname, "column_name") == 0)
2339  {
2340  colname = defGetString(def);
2341  break;
2342  }
2343  }
2344 
2346 
2347  *retrieved_attrs = lappend_int(*retrieved_attrs, i + 1);
2348  }
2349 
2350  /* Don't generate bad syntax for zero-column relation. */
2351  if (first)
2352  appendStringInfoString(buf, "NULL");
2353 
2354  /*
2355  * Construct FROM clause
2356  */
2357  appendStringInfoString(buf, " FROM ");
2358  deparseRelation(buf, rel);
2359 }
#define NameStr(name)
Definition: c.h:692
char * defGetString(DefElem *def)
Definition: define.c:49
List * GetForeignColumnOptions(Oid relid, AttrNumber attnum)
Definition: foreign.c:287
int i
Definition: isn.c:73
List * lappend_int(List *list, int datum)
Definition: list.c:356
NameData attname
Definition: pg_attribute.h:41
#define lfirst(lc)
Definition: pg_list.h:170
static char ** options
unsigned int Oid
Definition: postgres_ext.h:31
#define RelationGetRelid(relation)
Definition: rel.h:488
#define RelationGetDescr(relation)
Definition: rel.h:514
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:12189
char * defname
Definition: parsenodes.h:766
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92

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

Referenced by postgresAcquireSampleRowsFunc().

◆ deparseDeleteSql()

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

Definition at line 2150 of file deparse.c.

2154 {
2155  appendStringInfoString(buf, "DELETE FROM ");
2156  deparseRelation(buf, rel);
2157  appendStringInfoString(buf, " WHERE ctid = $1");
2158 
2159  deparseReturningList(buf, rte, rtindex, rel,
2160  rel->trigdesc && rel->trigdesc->trig_delete_after_row,
2161  NIL, returningList, retrieved_attrs);
2162 }
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:2230
TriggerDesc * trigdesc
Definition: rel.h:115
bool trig_delete_after_row
Definition: reltrigger.h:67

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

Referenced by postgresPlanForeignModify().

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

2186 {
2187  deparse_expr_cxt context;
2188 
2189  /* Set up context struct for recursion */
2190  context.root = root;
2191  context.foreignrel = foreignrel;
2192  context.scanrel = foreignrel;
2193  context.buf = buf;
2194  context.params_list = params_list;
2195 
2196  appendStringInfoString(buf, "DELETE FROM ");
2197  deparseRelation(buf, rel);
2198  if (foreignrel->reloptkind == RELOPT_JOINREL)
2199  appendStringInfo(buf, " %s%d", REL_ALIAS_PREFIX, rtindex);
2200 
2201  if (foreignrel->reloptkind == RELOPT_JOINREL)
2202  {
2203  List *ignore_conds = NIL;
2204 
2205  appendStringInfoString(buf, " USING ");
2206  deparseFromExprForRel(buf, root, foreignrel, true, rtindex,
2207  &ignore_conds, params_list);
2208  remote_conds = list_concat(remote_conds, ignore_conds);
2209  }
2210 
2211  if (remote_conds)
2212  {
2213  appendStringInfoString(buf, " WHERE ");
2214  appendConditions(remote_conds, &context);
2215  }
2216 
2217  if (foreignrel->reloptkind == RELOPT_JOINREL)
2218  deparseExplicitTargetList(returningList, true, retrieved_attrs,
2219  &context);
2220  else
2221  deparseReturningList(buf, planner_rt_fetch(rtindex, root),
2222  rtindex, rel, false,
2223  NIL, returningList, retrieved_attrs);
2224 }
#define REL_ALIAS_PREFIX
Definition: deparse.c:107
static void appendConditions(List *exprs, deparse_expr_cxt *context)
Definition: deparse.c:1499
static void deparseExplicitTargetList(List *tlist, bool is_returning, List **retrieved_attrs, deparse_expr_cxt *context)
Definition: deparse.c:1570
static void deparseFromExprForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel, bool use_alias, Index ignore_rel, List **ignore_conds, List **params_list)
Definition: deparse.c:1647
List * list_concat(List *list1, const List *list2)
Definition: list.c:560
#define planner_rt_fetch(rti, root)
Definition: pathnodes.h:397
@ RELOPT_JOINREL
Definition: pathnodes.h:651
RelOptKind reloptkind
Definition: pathnodes.h:687
PlannerInfo * root
Definition: deparse.c:98
List ** params_list
Definition: deparse.c:104
RelOptInfo * foreignrel
Definition: deparse.c:99
StringInfo buf
Definition: deparse.c:103
RelOptInfo * scanrel
Definition: deparse.c:100

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

Referenced by postgresPlanDirectModify().

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

2074 {
2075  deparse_expr_cxt context;
2076  int nestlevel;
2077  bool first;
2078  RangeTblEntry *rte = planner_rt_fetch(rtindex, root);
2079  ListCell *lc,
2080  *lc2;
2081 
2082  /* Set up context struct for recursion */
2083  context.root = root;
2084  context.foreignrel = foreignrel;
2085  context.scanrel = foreignrel;
2086  context.buf = buf;
2087  context.params_list = params_list;
2088 
2089  appendStringInfoString(buf, "UPDATE ");
2090  deparseRelation(buf, rel);
2091  if (foreignrel->reloptkind == RELOPT_JOINREL)
2092  appendStringInfo(buf, " %s%d", REL_ALIAS_PREFIX, rtindex);
2093  appendStringInfoString(buf, " SET ");
2094 
2095  /* Make sure any constants in the exprs are printed portably */
2096  nestlevel = set_transmission_modes();
2097 
2098  first = true;
2099  forboth(lc, targetlist, lc2, targetAttrs)
2100  {
2101  TargetEntry *tle = lfirst_node(TargetEntry, lc);
2102  int attnum = lfirst_int(lc2);
2103 
2104  /* update's new-value expressions shouldn't be resjunk */
2105  Assert(!tle->resjunk);
2106 
2107  if (!first)
2108  appendStringInfoString(buf, ", ");
2109  first = false;
2110 
2111  deparseColumnRef(buf, rtindex, attnum, rte, false);
2112  appendStringInfoString(buf, " = ");
2113  deparseExpr((Expr *) tle->expr, &context);
2114  }
2115 
2116  reset_transmission_modes(nestlevel);
2117 
2118  if (foreignrel->reloptkind == RELOPT_JOINREL)
2119  {
2120  List *ignore_conds = NIL;
2121 
2122  appendStringInfoString(buf, " FROM ");
2123  deparseFromExprForRel(buf, root, foreignrel, true, rtindex,
2124  &ignore_conds, params_list);
2125  remote_conds = list_concat(remote_conds, ignore_conds);
2126  }
2127 
2128  if (remote_conds)
2129  {
2130  appendStringInfoString(buf, " WHERE ");
2131  appendConditions(remote_conds, &context);
2132  }
2133 
2134  if (foreignrel->reloptkind == RELOPT_JOINREL)
2135  deparseExplicitTargetList(returningList, true, retrieved_attrs,
2136  &context);
2137  else
2138  deparseReturningList(buf, rte, rtindex, rel, false,
2139  NIL, returningList, retrieved_attrs);
2140 }
static void deparseExpr(Expr *expr, deparse_expr_cxt *context)
Definition: deparse.c:2603
static void deparseColumnRef(StringInfo buf, int varno, int varattno, RangeTblEntry *rte, bool qualify_col)
Definition: deparse.c:2400
Assert(fmt[strlen(fmt) - 1] !='\n')
int16 attnum
Definition: pg_attribute.h:83
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:465
#define lfirst_int(lc)
Definition: pg_list.h:171
void reset_transmission_modes(int nestlevel)
int set_transmission_modes(void)
Expr * expr
Definition: primnodes.h:1828
bool resjunk
Definition: primnodes.h:1835

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

Referenced by postgresPlanDirectModify().

◆ deparseInsertSql()

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

Definition at line 1872 of file deparse.c.

1877 {
1878  TupleDesc tupdesc = RelationGetDescr(rel);
1879  AttrNumber pindex;
1880  bool first;
1881  ListCell *lc;
1882 
1883  appendStringInfoString(buf, "INSERT INTO ");
1884  deparseRelation(buf, rel);
1885 
1886  if (targetAttrs)
1887  {
1888  appendStringInfoChar(buf, '(');
1889 
1890  first = true;
1891  foreach(lc, targetAttrs)
1892  {
1893  int attnum = lfirst_int(lc);
1894 
1895  if (!first)
1896  appendStringInfoString(buf, ", ");
1897  first = false;
1898 
1899  deparseColumnRef(buf, rtindex, attnum, rte, false);
1900  }
1901 
1902  appendStringInfoString(buf, ") VALUES (");
1903 
1904  pindex = 1;
1905  first = true;
1906  foreach(lc, targetAttrs)
1907  {
1908  int attnum = lfirst_int(lc);
1909  Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1);
1910 
1911  if (!first)
1912  appendStringInfoString(buf, ", ");
1913  first = false;
1914 
1915  if (attr->attgenerated)
1916  appendStringInfoString(buf, "DEFAULT");
1917  else
1918  {
1919  appendStringInfo(buf, "$%d", pindex);
1920  pindex++;
1921  }
1922  }
1923 
1924  appendStringInfoChar(buf, ')');
1925  }
1926  else
1927  appendStringInfoString(buf, " DEFAULT VALUES");
1928  *values_end_len = buf->len;
1929 
1930  if (doNothing)
1931  appendStringInfoString(buf, " ON CONFLICT DO NOTHING");
1932 
1933  deparseReturningList(buf, rte, rtindex, rel,
1934  rel->trigdesc && rel->trigdesc->trig_insert_after_row,
1935  withCheckOptionList, returningList, retrieved_attrs);
1936 }
int16 AttrNumber
Definition: attnum.h:21
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:207
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
bool trig_insert_after_row
Definition: reltrigger.h:57

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

Referenced by postgresBeginForeignInsert(), and postgresPlanForeignModify().

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

1163 {
1164  deparse_expr_cxt context;
1165  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) rel->fdw_private;
1166  List *quals;
1167 
1168  /*
1169  * We handle relations for foreign tables, joins between those and upper
1170  * relations.
1171  */
1172  Assert(IS_JOIN_REL(rel) || IS_SIMPLE_REL(rel) || IS_UPPER_REL(rel));
1173 
1174  /* Fill portions of context common to upper, join and base relation */
1175  context.buf = buf;
1176  context.root = root;
1177  context.foreignrel = rel;
1178  context.scanrel = IS_UPPER_REL(rel) ? fpinfo->outerrel : rel;
1179  context.params_list = params_list;
1180 
1181  /* Construct SELECT clause */
1182  deparseSelectSql(tlist, is_subquery, retrieved_attrs, &context);
1183 
1184  /*
1185  * For upper relations, the WHERE clause is built from the remote
1186  * conditions of the underlying scan relation; otherwise, we can use the
1187  * supplied list of remote conditions directly.
1188  */
1189  if (IS_UPPER_REL(rel))
1190  {
1191  PgFdwRelationInfo *ofpinfo;
1192 
1193  ofpinfo = (PgFdwRelationInfo *) fpinfo->outerrel->fdw_private;
1194  quals = ofpinfo->remote_conds;
1195  }
1196  else
1197  quals = remote_conds;
1198 
1199  /* Construct FROM and WHERE clauses */
1200  deparseFromExpr(quals, &context);
1201 
1202  if (IS_UPPER_REL(rel))
1203  {
1204  /* Append GROUP BY clause */
1205  appendGroupByClause(tlist, &context);
1206 
1207  /* Append HAVING clause */
1208  if (remote_conds)
1209  {
1210  appendStringInfoString(buf, " HAVING ");
1211  appendConditions(remote_conds, &context);
1212  }
1213  }
1214 
1215  /* Add ORDER BY clause if we found any useful pathkeys */
1216  if (pathkeys)
1217  appendOrderByClause(pathkeys, has_final_sort, &context);
1218 
1219  /* Add LIMIT clause if necessary */
1220  if (has_limit)
1221  appendLimitClause(&context);
1222 
1223  /* Add any necessary FOR UPDATE/SHARE. */
1224  deparseLockingClause(&context);
1225 }
static void appendGroupByClause(List *tlist, deparse_expr_cxt *context)
Definition: deparse.c:3581
static void deparseFromExpr(List *quals, deparse_expr_cxt *context)
Definition: deparse.c:1299
static void deparseLockingClause(deparse_expr_cxt *context)
Definition: deparse.c:1409
static void appendOrderByClause(List *pathkeys, bool has_final_sort, deparse_expr_cxt *context)
Definition: deparse.c:3622
static void appendLimitClause(deparse_expr_cxt *context)
Definition: deparse.c:3699
static void deparseSelectSql(List *tlist, bool is_subquery, List **retrieved_attrs, deparse_expr_cxt *context)
Definition: deparse.c:1241
#define IS_SIMPLE_REL(rel)
Definition: pathnodes.h:663
#define IS_JOIN_REL(rel)
Definition: pathnodes.h:668
RelOptInfo * outerrel
Definition: postgres_fdw.h:102

References appendConditions(), appendGroupByClause(), appendLimitClause(), appendOrderByClause(), appendStringInfoString(), Assert(), deparse_expr_cxt::buf, 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().

◆ deparseStringLiteral()

void deparseStringLiteral ( StringInfo  buf,
const char *  val 
)

Definition at line 2568 of file deparse.c.

2569 {
2570  const char *valptr;
2571 
2572  /*
2573  * Rather than making assumptions about the remote server's value of
2574  * standard_conforming_strings, always use E'foo' syntax if there are any
2575  * backslashes. This will fail on remote servers before 8.1, but those
2576  * are long out of support.
2577  */
2578  if (strchr(val, '\\') != NULL)
2580  appendStringInfoChar(buf, '\'');
2581  for (valptr = val; *valptr; valptr++)
2582  {
2583  char ch = *valptr;
2584 
2585  if (SQL_STR_DOUBLE(ch, true))
2588  }
2589  appendStringInfoChar(buf, '\'');
2590 }
#define ESCAPE_STRING_SYNTAX
Definition: c.h:1175
#define SQL_STR_DOUBLE(ch, escape_backslash)
Definition: c.h:1172
long val
Definition: informix.c:664

References appendStringInfoChar(), buf, ESCAPE_STRING_SYNTAX, SQL_STR_DOUBLE, and val.

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

◆ deparseTruncateSql()

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

Definition at line 2365 of file deparse.c.

2369 {
2370  ListCell *cell;
2371 
2372  appendStringInfoString(buf, "TRUNCATE ");
2373 
2374  foreach(cell, rels)
2375  {
2376  Relation rel = lfirst(cell);
2377 
2378  if (cell != list_head(rels))
2379  appendStringInfoString(buf, ", ");
2380 
2381  deparseRelation(buf, rel);
2382  }
2383 
2384  appendStringInfo(buf, " %s IDENTITY",
2385  restart_seqs ? "RESTART" : "CONTINUE");
2386 
2387  if (behavior == DROP_RESTRICT)
2388  appendStringInfoString(buf, " RESTRICT");
2389  else if (behavior == DROP_CASCADE)
2390  appendStringInfoString(buf, " CASCADE");
2391 }
@ DROP_CASCADE
Definition: parsenodes.h:2209
@ DROP_RESTRICT
Definition: parsenodes.h:2208
static ListCell * list_head(const List *l)
Definition: pg_list.h:126

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

Referenced by postgresExecForeignTruncate().

◆ deparseUpdateSql()

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

Definition at line 2005 of file deparse.c.

2010 {
2011  TupleDesc tupdesc = RelationGetDescr(rel);
2012  AttrNumber pindex;
2013  bool first;
2014  ListCell *lc;
2015 
2016  appendStringInfoString(buf, "UPDATE ");
2017  deparseRelation(buf, rel);
2018  appendStringInfoString(buf, " SET ");
2019 
2020  pindex = 2; /* ctid is always the first param */
2021  first = true;
2022  foreach(lc, targetAttrs)
2023  {
2024  int attnum = lfirst_int(lc);
2025  Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1);
2026 
2027  if (!first)
2028  appendStringInfoString(buf, ", ");
2029  first = false;
2030 
2031  deparseColumnRef(buf, rtindex, attnum, rte, false);
2032  if (attr->attgenerated)
2033  appendStringInfoString(buf, " = DEFAULT");
2034  else
2035  {
2036  appendStringInfo(buf, " = $%d", pindex);
2037  pindex++;
2038  }
2039  }
2040  appendStringInfoString(buf, " WHERE ctid = $1");
2041 
2042  deparseReturningList(buf, rte, rtindex, rel,
2043  rel->trigdesc && rel->trigdesc->trig_update_after_row,
2044  withCheckOptionList, returningList, retrieved_attrs);
2045 }
bool trig_update_after_row
Definition: reltrigger.h:62

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

Referenced by postgresPlanForeignModify().

◆ do_sql_command()

void do_sql_command ( PGconn conn,
const char *  sql 
)

Definition at line 638 of file connection.c.

639 {
641  do_sql_command_end(conn, sql, false);
642 }
static void do_sql_command_end(PGconn *conn, const char *sql, bool consume_input)
Definition: connection.c:652
static void do_sql_command_begin(PGconn *conn, const char *sql)
Definition: connection.c:645
PGconn * conn
Definition: streamutil.c:54

References conn, do_sql_command_begin(), and do_sql_command_end().

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

◆ ExtractConnectionOptions()

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

Definition at line 382 of file option.c.

384 {
385  ListCell *lc;
386  int i;
387 
388  /* Build our options lists if we didn't yet. */
390 
391  i = 0;
392  foreach(lc, defelems)
393  {
394  DefElem *d = (DefElem *) lfirst(lc);
395 
396  if (is_libpq_option(d->defname))
397  {
398  keywords[i] = d->defname;
399  values[i] = defGetString(d);
400  i++;
401  }
402  }
403  return i;
404 }
static Datum values[MAXATTR]
Definition: bootstrap.c:156
static bool is_libpq_option(const char *keyword)
Definition: option.c:361
static void InitPgFdwOptions(void)
Definition: option.c:219

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

Referenced by connect_pg_server().

◆ ExtractExtensionList()

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

Definition at line 413 of file option.c.

414 {
415  List *extensionOids = NIL;
416  List *extlist;
417  ListCell *lc;
418 
419  /* SplitIdentifierString scribbles on its input, so pstrdup first */
420  if (!SplitIdentifierString(pstrdup(extensionsString), ',', &extlist))
421  {
422  /* syntax error in name list */
423  ereport(ERROR,
424  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
425  errmsg("parameter \"%s\" must be a list of extension names",
426  "extensions")));
427  }
428 
429  foreach(lc, extlist)
430  {
431  const char *extension_name = (const char *) lfirst(lc);
432  Oid extension_oid = get_extension_oid(extension_name, true);
433 
434  if (OidIsValid(extension_oid))
435  {
436  extensionOids = lappend_oid(extensionOids, extension_oid);
437  }
438  else if (warnOnMissing)
439  {
441  (errcode(ERRCODE_UNDEFINED_OBJECT),
442  errmsg("extension \"%s\" is not installed",
443  extension_name)));
444  }
445  }
446 
447  list_free(extlist);
448  return extensionOids;
449 }
#define OidIsValid(objectId)
Definition: c.h:721
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define WARNING
Definition: elog.h:30
#define ERROR
Definition: elog.h:33
#define ereport(elevel,...)
Definition: elog.h:143
Oid get_extension_oid(const char *extname, bool missing_ok)
Definition: extension.c:140
List * lappend_oid(List *list, Oid datum)
Definition: list.c:374
void list_free(List *list)
Definition: list.c:1545
char * pstrdup(const char *in)
Definition: mcxt.c:1305
bool SplitIdentifierString(char *rawstring, char separator, List **namelist)
Definition: varlena.c:3715

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

◆ find_em_for_rel()

EquivalenceMember* find_em_for_rel ( PlannerInfo root,
EquivalenceClass ec,
RelOptInfo rel 
)

Definition at line 7403 of file postgres_fdw.c.

7404 {
7405  ListCell *lc;
7406 
7407  foreach(lc, ec->ec_members)
7408  {
7410 
7411  /*
7412  * Note we require !bms_is_empty, else we'd accept constant
7413  * expressions which are not suitable for the purpose.
7414  */
7415  if (bms_is_subset(em->em_relids, rel->relids) &&
7416  !bms_is_empty(em->em_relids) &&
7417  is_foreign_expr(root, rel, em->em_expr))
7418  return em;
7419  }
7420 
7421  return NULL;
7422 }
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:315
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:703
Relids relids
Definition: pathnodes.h:693

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

Referenced by appendOrderByClause(), get_useful_pathkeys_for_relation(), and is_foreign_pathkey().

◆ find_em_for_rel_target()

EquivalenceMember* find_em_for_rel_target ( PlannerInfo root,
EquivalenceClass ec,
RelOptInfo rel 
)

Definition at line 7436 of file postgres_fdw.c.

7438 {
7439  PathTarget *target = rel->reltarget;
7440  ListCell *lc1;
7441  int i;
7442 
7443  i = 0;
7444  foreach(lc1, target->exprs)
7445  {
7446  Expr *expr = (Expr *) lfirst(lc1);
7447  Index sgref = get_pathtarget_sortgroupref(target, i);
7448  ListCell *lc2;
7449 
7450  /* Ignore non-sort expressions */
7451  if (sgref == 0 ||
7453  root->parse->sortClause) == NULL)
7454  {
7455  i++;
7456  continue;
7457  }
7458 
7459  /* We ignore binary-compatible relabeling on both ends */
7460  while (expr && IsA(expr, RelabelType))
7461  expr = ((RelabelType *) expr)->arg;
7462 
7463  /* Locate an EquivalenceClass member matching this expr, if any */
7464  foreach(lc2, ec->ec_members)
7465  {
7467  Expr *em_expr;
7468 
7469  /* Don't match constants */
7470  if (em->em_is_const)
7471  continue;
7472 
7473  /* Ignore child members */
7474  if (em->em_is_child)
7475  continue;
7476 
7477  /* Match if same expression (after stripping relabel) */
7478  em_expr = em->em_expr;
7479  while (em_expr && IsA(em_expr, RelabelType))
7480  em_expr = ((RelabelType *) em_expr)->arg;
7481 
7482  if (!equal(em_expr, expr))
7483  continue;
7484 
7485  /* Check that expression (including relabels!) is shippable */
7486  if (is_foreign_expr(root, rel, em->em_expr))
7487  return em;
7488  }
7489 
7490  i++;
7491  }
7492 
7493  return NULL;
7494 }
unsigned int Index
Definition: c.h:560
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3580
#define IsA(nodeptr, _type_)
Definition: nodes.h:625
#define get_pathtarget_sortgroupref(target, colno)
Definition: pathnodes.h:1281
void * arg
Query * parse
Definition: pathnodes.h:162
List * sortClause
Definition: parsenodes.h:175
SortGroupClause * get_sortgroupref_clause_noerr(Index sortref, List *clauses)
Definition: tlist.c:432

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

Referenced by add_foreign_ordered_paths(), and appendOrderByClause().

◆ get_jointype_name()

const char* get_jointype_name ( JoinType  jointype)

Definition at line 1533 of file deparse.c.

1534 {
1535  switch (jointype)
1536  {
1537  case JOIN_INNER:
1538  return "INNER";
1539 
1540  case JOIN_LEFT:
1541  return "LEFT";
1542 
1543  case JOIN_RIGHT:
1544  return "RIGHT";
1545 
1546  case JOIN_FULL:
1547  return "FULL";
1548 
1549  default:
1550  /* Shouldn't come here, but protect from buggy code. */
1551  elog(ERROR, "unsupported join type %d", jointype);
1552  }
1553 
1554  /* Keep compiler happy */
1555  return NULL;
1556 }
@ JOIN_FULL
Definition: nodes.h:752
@ JOIN_INNER
Definition: nodes.h:750
@ JOIN_RIGHT
Definition: nodes.h:753
@ JOIN_LEFT
Definition: nodes.h:751

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

Referenced by deparseFromExprForRel(), and foreign_join_ok().

◆ GetConnection()

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

Definition at line 134 of file connection.c.

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

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

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

◆ GetCursorNumber()

unsigned int GetCursorNumber ( PGconn conn)

Definition at line 745 of file connection.c.

746 {
747  return ++cursor_number;
748 }
static unsigned int cursor_number
Definition: connection.c:77

References cursor_number.

Referenced by postgresAcquireSampleRowsFunc(), and postgresBeginForeignScan().

◆ GetPrepStmtNumber()

unsigned int GetPrepStmtNumber ( PGconn conn)

Definition at line 759 of file connection.c.

760 {
761  return ++prep_stmt_number;
762 }
static unsigned int prep_stmt_number
Definition: connection.c:78

References prep_stmt_number.

Referenced by prepare_foreign_modify().

◆ is_builtin()

bool is_builtin ( Oid  objectId)

Definition at line 152 of file shippable.c.

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

References FirstGenbkiObjectId.

Referenced by deparse_type_name(), and is_shippable().

◆ is_foreign_expr()

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

Definition at line 237 of file deparse.c.

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

References foreign_loc_cxt::collation, contain_mutable_functions(), FDW_COLLATE_NONE, FDW_COLLATE_UNSAFE, RelOptInfo::fdw_private, foreign_expr_walker(), foreign_glob_cxt::foreignrel, if(), 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(), classifyConditions(), find_em_for_rel(), find_em_for_rel_target(), foreign_grouping_ok(), foreign_join_ok(), postgresGetForeignPaths(), postgresGetForeignPlan(), and postgresPlanDirectModify().

◆ is_foreign_param()

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

Definition at line 1008 of file deparse.c.

1011 {
1012  if (expr == NULL)
1013  return false;
1014 
1015  switch (nodeTag(expr))
1016  {
1017  case T_Var:
1018  {
1019  /* It would have to be sent unless it's a foreign Var */
1020  Var *var = (Var *) expr;
1021  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) (baserel->fdw_private);
1022  Relids relids;
1023 
1024  if (IS_UPPER_REL(baserel))
1025  relids = fpinfo->outerrel->relids;
1026  else
1027  relids = baserel->relids;
1028 
1029  if (bms_is_member(var->varno, relids) && var->varlevelsup == 0)
1030  return false; /* foreign Var, so not a param */
1031  else
1032  return true; /* it'd have to be a param */
1033  break;
1034  }
1035  case T_Param:
1036  /* Params always have to be sent to the foreign server */
1037  return true;
1038  default:
1039  break;
1040  }
1041  return false;
1042 }
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:427
#define nodeTag(nodeptr)
Definition: nodes.h:579
@ T_Param
Definition: nodes.h:159
@ T_Var
Definition: nodes.h:157
Definition: primnodes.h:209
int varno
Definition: primnodes.h:216
Index varlevelsup
Definition: primnodes.h:234

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

Referenced by foreign_grouping_ok().

◆ is_foreign_pathkey()

bool is_foreign_pathkey ( PlannerInfo root,
RelOptInfo baserel,
PathKey pathkey 
)

Definition at line 1049 of file deparse.c.

1052 {
1053  EquivalenceClass *pathkey_ec = pathkey->pk_eclass;
1054  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) baserel->fdw_private;
1055 
1056  /*
1057  * is_foreign_expr would detect volatile expressions as well, but checking
1058  * ec_has_volatile here saves some cycles.
1059  */
1060  if (pathkey_ec->ec_has_volatile)
1061  return false;
1062 
1063  /* can't push down the sort if the pathkey's opfamily is not shippable */
1064  if (!is_shippable(pathkey->pk_opfamily, OperatorFamilyRelationId, fpinfo))
1065  return false;
1066 
1067  /* can push if a suitable EC member exists */
1068  return (find_em_for_rel(root, pathkey_ec, baserel) != NULL);
1069 }
EquivalenceMember * find_em_for_rel(PlannerInfo *root, EquivalenceClass *ec, RelOptInfo *rel)
bool is_shippable(Oid objectId, Oid classId, PgFdwRelationInfo *fpinfo)
Definition: shippable.c:162
EquivalenceClass * pk_eclass
Definition: pathnodes.h:1209
Oid pk_opfamily
Definition: pathnodes.h:1210

References EquivalenceClass::ec_has_volatile, RelOptInfo::fdw_private, find_em_for_rel(), if(), is_shippable(), PathKey::pk_eclass, and PathKey::pk_opfamily.

Referenced by get_useful_pathkeys_for_relation().

◆ is_shippable()

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

Definition at line 162 of file shippable.c.

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

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

Referenced by add_foreign_ordered_paths(), foreign_expr_walker(), get_useful_pathkeys_for_relation(), and is_foreign_pathkey().

◆ pgfdw_exec_query()

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

Definition at line 772 of file connection.c.

773 {
774  /* First, process a pending asynchronous request, if any. */
775  if (state && state->pendingAreq)
776  process_pending_request(state->pendingAreq);
777 
778  /*
779  * Submit a query. Since we don't use non-blocking mode, this also can
780  * block. But its risk is relatively small, so we ignore that for now.
781  */
782  if (!PQsendQuery(conn, query))
783  pgfdw_report_error(ERROR, NULL, conn, false, query);
784 
785  /* Wait for the result. */
786  return pgfdw_get_result(conn, query);
787 }
PGresult * pgfdw_get_result(PGconn *conn, const char *query)
Definition: connection.c:800
void pgfdw_report_error(int elevel, PGresult *res, PGconn *conn, bool clear, const char *sql)
Definition: connection.c:865
int PQsendQuery(PGconn *conn, const char *query)
Definition: fe-exec.c:1421

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

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

◆ pgfdw_get_result()

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

Definition at line 800 of file connection.c.

801 {
802  PGresult *volatile last_res = NULL;
803 
804  /* In what follows, do not leak any PGresults on an error. */
805  PG_TRY();
806  {
807  for (;;)
808  {
809  PGresult *res;
810 
811  while (PQisBusy(conn))
812  {
813  int wc;
814 
815  /* Sleep until there's something to do */
819  PQsocket(conn),
820  -1L, PG_WAIT_EXTENSION);
822 
824 
825  /* Data available in socket? */
826  if (wc & WL_SOCKET_READABLE)
827  {
828  if (!PQconsumeInput(conn))
829  pgfdw_report_error(ERROR, NULL, conn, false, query);
830  }
831  }
832 
833  res = PQgetResult(conn);
834  if (res == NULL)
835  break; /* query is complete */
836 
837  PQclear(last_res);
838  last_res = res;
839  }
840  }
841  PG_CATCH();
842  {
843  PQclear(last_res);
844  PG_RE_THROW();
845  }
846  PG_END_TRY();
847 
848  return last_res;
849 }
int PQsocket(const PGconn *conn)
Definition: fe-connect.c:6861
int PQconsumeInput(PGconn *conn)
Definition: fe-exec.c:2024
int PQisBusy(PGconn *conn)
Definition: fe-exec.c:2071
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:2102
struct Latch * MyLatch
Definition: globals.c:58
int WaitLatchOrSocket(Latch *latch, int wakeEvents, pgsocket sock, long timeout, uint32 wait_event_info)
Definition: latch.c:524
void ResetLatch(Latch *latch)
Definition: latch.c:683
#define WL_SOCKET_READABLE
Definition: latch.h:126
#define WL_EXIT_ON_PM_DEATH
Definition: latch.h:130
#define WL_LATCH_SET
Definition: latch.h:125
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:121
#define PG_WAIT_EXTENSION
Definition: wait_event.h:23

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

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

◆ pgfdw_report_error()

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

Definition at line 865 of file connection.c.

867 {
868  /* If requested, PGresult must be released before leaving this function. */
869  PG_TRY();
870  {
871  char *diag_sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE);
872  char *message_primary = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY);
873  char *message_detail = PQresultErrorField(res, PG_DIAG_MESSAGE_DETAIL);
874  char *message_hint = PQresultErrorField(res, PG_DIAG_MESSAGE_HINT);
875  char *message_context = PQresultErrorField(res, PG_DIAG_CONTEXT);
876  int sqlstate;
877 
878  if (diag_sqlstate)
879  sqlstate = MAKE_SQLSTATE(diag_sqlstate[0],
880  diag_sqlstate[1],
881  diag_sqlstate[2],
882  diag_sqlstate[3],
883  diag_sqlstate[4]);
884  else
885  sqlstate = ERRCODE_CONNECTION_FAILURE;
886 
887  /*
888  * If we don't get a message from the PGresult, try the PGconn. This
889  * is needed because for connection-level failures, PQexec may just
890  * return NULL, not a PGresult at all.
891  */
892  if (message_primary == NULL)
893  message_primary = pchomp(PQerrorMessage(conn));
894 
895  ereport(elevel,
896  (errcode(sqlstate),
897  (message_primary != NULL && message_primary[0] != '\0') ?
898  errmsg_internal("%s", message_primary) :
899  errmsg("could not obtain message string for remote error"),
900  message_detail ? errdetail_internal("%s", message_detail) : 0,
901  message_hint ? errhint("%s", message_hint) : 0,
902  message_context ? errcontext("%s", message_context) : 0,
903  sql ? errcontext("remote SQL command: %s", sql) : 0));
904  }
905  PG_FINALLY();
906  {
907  if (clear)
908  PQclear(res);
909  }
910  PG_END_TRY();
911 }
int errhint(const char *fmt,...)
Definition: elog.c:1151
#define errcontext
Definition: elog.h:190
#define PG_FINALLY()
Definition: elog.h:316
#define MAKE_SQLSTATE(ch1, ch2, ch3, ch4, ch5)
Definition: elog.h:50
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:3400
#define PG_DIAG_MESSAGE_HINT
Definition: postgres_ext.h:60
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
#define PG_DIAG_MESSAGE_PRIMARY
Definition: postgres_ext.h:58
#define PG_DIAG_MESSAGE_DETAIL
Definition: postgres_ext.h:59
#define PG_DIAG_CONTEXT
Definition: postgres_ext.h:64

References conn, 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(), PQresultErrorField(), and res.

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

◆ process_pending_request()

void process_pending_request ( AsyncRequest areq)

Definition at line 7076 of file postgres_fdw.c.

7077 {
7078  ForeignScanState *node = (ForeignScanState *) areq->requestee;
7079  PgFdwScanState *fsstate = (PgFdwScanState *) node->fdw_state;
7080 
7081  /* The request would have been pending for a callback */
7082  Assert(areq->callback_pending);
7083 
7084  /* The request should be currently in-process */
7085  Assert(fsstate->conn_state->pendingAreq == areq);
7086 
7087  fetch_more_data(node);
7088 
7089  /*
7090  * If we didn't get any tuples, must be end of data; complete the request
7091  * now. Otherwise, we postpone completing the request until we are called
7092  * from postgresForeignAsyncConfigureWait()/postgresForeignAsyncNotify().
7093  */
7094  if (fsstate->next_tuple >= fsstate->num_tuples)
7095  {
7096  /* Unlike AsyncNotify, we unset callback_pending ourselves */
7097  areq->callback_pending = false;
7098  /* Mark the request as complete */
7099  ExecAsyncRequestDone(areq, NULL);
7100  /* Unlike AsyncNotify, we call ExecAsyncResponse ourselves */
7101  ExecAsyncResponse(areq);
7102  }
7103 }
void ExecAsyncResponse(AsyncRequest *areq)
Definition: execAsync.c:117
void ExecAsyncRequestDone(AsyncRequest *areq, TupleTableSlot *result)
Definition: execAsync.c:137
static void fetch_more_data(ForeignScanState *node)
bool callback_pending
Definition: execnodes.h:572
struct PlanState * requestee
Definition: execnodes.h:570

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

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

◆ process_pgfdw_appname()

char* process_pgfdw_appname ( const char *  appname)

Definition at line 459 of file option.c.

460 {
461  const char *p;
463 
464  Assert(MyProcPort != NULL);
465 
467 
468  for (p = appname; *p != '\0'; p++)
469  {
470  if (*p != '%')
471  {
472  /* literal char, just copy */
474  continue;
475  }
476 
477  /* must be a '%', so skip to the next char */
478  p++;
479  if (*p == '\0')
480  break; /* format error - ignore it */
481  else if (*p == '%')
482  {
483  /* string contains %% */
484  appendStringInfoChar(&buf, '%');
485  continue;
486  }
487 
488  /* process the option */
489  switch (*p)
490  {
491  case 'a':
493  break;
494  case 'c':
495  appendStringInfo(&buf, "%lx.%x", (long) (MyStartTime), MyProcPid);
496  break;
497  case 'C':
499  break;
500  case 'd':
502  break;
503  case 'p':
504  appendStringInfo(&buf, "%d", MyProcPid);
505  break;
506  case 'u':
508  break;
509  default:
510  /* format error - ignore it */
511  break;
512  }
513  }
514 
515  return buf.data;
516 }
int MyProcPid
Definition: globals.c:44
struct Port * MyProcPort
Definition: globals.c:47
pg_time_t MyStartTime
Definition: globals.c:45
char * cluster_name
Definition: guc.c:653
char * application_name
Definition: guc.c:661
char * user_name
Definition: libpq-be.h:145
char * database_name
Definition: libpq-be.h:144

References appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), application_name, Assert(), buf, cluster_name, Port::database_name, initStringInfo(), MyProcPid, MyProcPort, MyStartTime, and Port::user_name.

Referenced by connect_pg_server().

◆ rebuildInsertSql()

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

Definition at line 1945 of file deparse.c.

1949 {
1950  TupleDesc tupdesc = RelationGetDescr(rel);
1951  int i;
1952  int pindex;
1953  bool first;
1954  ListCell *lc;
1955 
1956  /* Make sure the values_end_len is sensible */
1957  Assert((values_end_len > 0) && (values_end_len <= strlen(orig_query)));
1958 
1959  /* Copy up to the end of the first record from the original query */
1960  appendBinaryStringInfo(buf, orig_query, values_end_len);
1961 
1962  /*
1963  * Add records to VALUES clause (we already have parameters for the first
1964  * row, so start at the right offset).
1965  */
1966  pindex = num_params + 1;
1967  for (i = 0; i < num_rows; i++)
1968  {
1969  appendStringInfoString(buf, ", (");
1970 
1971  first = true;
1972  foreach(lc, target_attrs)
1973  {
1974  int attnum = lfirst_int(lc);
1975  Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1);
1976 
1977  if (!first)
1978  appendStringInfoString(buf, ", ");
1979  first = false;
1980 
1981  if (attr->attgenerated)
1982  appendStringInfoString(buf, "DEFAULT");
1983  else
1984  {
1985  appendStringInfo(buf, "$%d", pindex);
1986  pindex++;
1987  }
1988  }
1989 
1990  appendStringInfoChar(buf, ')');
1991  }
1992 
1993  /* Copy stuff after VALUES clause from the original query */
1994  appendStringInfoString(buf, orig_query + values_end_len);
1995 }
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:227

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

Referenced by execute_foreign_modify().

◆ ReleaseConnection()

void ReleaseConnection ( PGconn conn)

Definition at line 724 of file connection.c.

725 {
726  /*
727  * Currently, we don't actually track connection references because all
728  * cleanup is managed on a transaction or subtransaction basis instead. So
729  * there's nothing to do here.
730  */
731 }

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

◆ reset_transmission_modes()

void reset_transmission_modes ( int  nestlevel)

Definition at line 3906 of file postgres_fdw.c.

3907 {
3908  AtEOXact_GUC(true, nestlevel);
3909 }
void AtEOXact_GUC(bool isCommit, int nestLevel)
Definition: guc.c:6489

References AtEOXact_GUC().

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

◆ set_transmission_modes()

int set_transmission_modes ( void  )

Definition at line 3878 of file postgres_fdw.c.

3879 {
3880  int nestlevel = NewGUCNestLevel();
3881 
3882  /*
3883  * The values set here should match what pg_dump does. See also
3884  * configure_remote_session in connection.c.
3885  */
3886  if (DateStyle != USE_ISO_DATES)
3887  (void) set_config_option("datestyle", "ISO",
3889  GUC_ACTION_SAVE, true, 0, false);
3891  (void) set_config_option("intervalstyle", "postgres",
3893  GUC_ACTION_SAVE, true, 0, false);
3894  if (extra_float_digits < 3)
3895  (void) set_config_option("extra_float_digits", "3",
3897  GUC_ACTION_SAVE, true, 0, false);
3898 
3899  return nestlevel;
3900 }
int extra_float_digits
Definition: float.c:43
int DateStyle
Definition: globals.c:119
int IntervalStyle
Definition: globals.c:121
int NewGUCNestLevel(void)
Definition: guc.c:6475
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:7562
@ GUC_ACTION_SAVE
Definition: guc.h:200
@ PGC_S_SESSION
Definition: guc.h:123
@ PGC_USERSET
Definition: guc.h:76
#define USE_ISO_DATES
Definition: miscadmin.h:230
#define INTSTYLE_POSTGRES
Definition: miscadmin.h:250

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

Variable Documentation

◆ pgfdw_application_name

char* pgfdw_application_name
extern

Definition at line 52 of file option.c.

Referenced by _PG_init(), and connect_pg_server().