PostgreSQL Source Code git master
Loading...
Searching...
No Matches
postgres_fdw.h File Reference
#include "foreign/foreign.h"
#include "lib/stringinfo.h"
#include "libpq/libpq-be-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
 
typedef enum PgFdwSamplingMethod PgFdwSamplingMethod
 

Enumerations

enum  PgFdwSamplingMethod {
  ANALYZE_SAMPLE_OFF , ANALYZE_SAMPLE_AUTO , ANALYZE_SAMPLE_RANDOM , ANALYZE_SAMPLE_SYSTEM ,
  ANALYZE_SAMPLE_BERNOULLI
}
 

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)
 
PGresultpgfdw_exec_query (PGconn *conn, const char *query, PgFdwConnState *state)
 
pg_noreturn void pgfdw_report_error (PGresult *res, PGconn *conn, const char *sql)
 
void pgfdw_report (int elevel, PGresult *res, PGconn *conn, const char *sql)
 
int ExtractConnectionOptions (List *defelems, const char **keywords, const char **values)
 
ListExtractExtensionList (const char *extensionsString, bool warnOnMissing)
 
charprocess_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 deparseAnalyzeInfoSql (StringInfo buf, Relation rel)
 
void deparseAnalyzeSql (StringInfo buf, Relation rel, PgFdwSamplingMethod sample_method, double sample_frac, 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 *rel, List *tlist, List *remote_conds, List *pathkeys, bool has_final_sort, bool has_limit, bool is_subquery, List **retrieved_attrs, List **params_list)
 
const charget_jointype_name (JoinType jointype)
 
bool is_builtin (Oid objectId)
 
bool is_shippable (Oid objectId, Oid classId, PgFdwRelationInfo *fpinfo)
 

Variables

charpgfdw_application_name
 

Typedef Documentation

◆ PgFdwConnState

◆ PgFdwRelationInfo

◆ PgFdwSamplingMethod

Enumeration Type Documentation

◆ PgFdwSamplingMethod

Enumerator
ANALYZE_SAMPLE_OFF 
ANALYZE_SAMPLE_AUTO 
ANALYZE_SAMPLE_RANDOM 
ANALYZE_SAMPLE_SYSTEM 
ANALYZE_SAMPLE_BERNOULLI 

Definition at line 145 of file postgres_fdw.h.

146{
147 ANALYZE_SAMPLE_OFF, /* no remote sampling */
148 ANALYZE_SAMPLE_AUTO, /* choose by server version */
149 ANALYZE_SAMPLE_RANDOM, /* remote random() */
150 ANALYZE_SAMPLE_SYSTEM, /* TABLESAMPLE system */
151 ANALYZE_SAMPLE_BERNOULLI, /* TABLESAMPLE bernoulli */
PgFdwSamplingMethod
@ ANALYZE_SAMPLE_AUTO
@ ANALYZE_SAMPLE_OFF
@ ANALYZE_SAMPLE_BERNOULLI
@ ANALYZE_SAMPLE_SYSTEM
@ ANALYZE_SAMPLE_RANDOM

Function Documentation

◆ build_tlist_to_deparse()

List * build_tlist_to_deparse ( RelOptInfo foreignrel)
extern

Definition at line 1209 of file deparse.c.

1210{
1211 List *tlist = NIL;
1212 PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
1213 ListCell *lc;
1214
1215 /*
1216 * For an upper relation, we have already built the target list while
1217 * checking shippability, so just return that.
1218 */
1219 if (IS_UPPER_REL(foreignrel))
1220 return fpinfo->grouped_tlist;
1221
1222 /*
1223 * We require columns specified in foreignrel->reltarget->exprs and those
1224 * required for evaluating the local conditions.
1225 */
1226 tlist = add_to_flat_tlist(tlist,
1227 pull_var_clause((Node *) foreignrel->reltarget->exprs,
1229 foreach(lc, fpinfo->local_conds)
1230 {
1232
1233 tlist = add_to_flat_tlist(tlist,
1234 pull_var_clause((Node *) rinfo->clause,
1236 }
1237
1238 return tlist;
1239}
#define PVC_RECURSE_PLACEHOLDERS
Definition optimizer.h:202
#define IS_UPPER_REL(rel)
Definition pathnodes.h:999
#define lfirst_node(type, lc)
Definition pg_list.h:176
#define NIL
Definition pg_list.h:68
static int fb(int x)
Definition pg_list.h:54
Definition nodes.h:135
List * exprs
Definition pathnodes.h:1878
struct PathTarget * reltarget
Definition pathnodes.h:1045
Expr * clause
Definition pathnodes.h:2901
List * add_to_flat_tlist(List *tlist, List *exprs)
Definition tlist.c:141
List * pull_var_clause(Node *node, int flags)
Definition var.c:653

References add_to_flat_tlist(), RestrictInfo::clause, PathTarget::exprs, fb(), IS_UPPER_REL, lfirst_node, 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 
)
extern

Definition at line 218 of file deparse.c.

223{
224 ListCell *lc;
225
226 *remote_conds = NIL;
227 *local_conds = NIL;
228
229 foreach(lc, input_conds)
230 {
232
233 if (is_foreign_expr(root, baserel, ri->clause))
234 *remote_conds = lappend(*remote_conds, ri);
235 else
236 *local_conds = lappend(*local_conds, ri);
237 }
238}
bool is_foreign_expr(PlannerInfo *root, RelOptInfo *baserel, Expr *expr)
Definition deparse.c:244
List * lappend(List *list, void *datum)
Definition list.c:339
tree ctl root
Definition radixtree.h:1857

References fb(), is_foreign_expr(), lappend(), lfirst_node, NIL, and root.

Referenced by estimate_path_cost_size(), and postgresGetForeignRelSize().

◆ deparseAnalyzeInfoSql()

void deparseAnalyzeInfoSql ( StringInfo  buf,
Relation  rel 
)
extern

Definition at line 2552 of file deparse.c.

2553{
2555
2556 /* We'll need the remote relation name as a literal. */
2558 deparseRelation(&relname, rel);
2559
2560 appendStringInfoString(buf, "SELECT relpages, reltuples, relkind FROM pg_catalog.pg_class WHERE oid = ");
2562 appendStringInfoString(buf, "::pg_catalog.regclass");
2563}
void deparseStringLiteral(StringInfo buf, const char *val)
Definition deparse.c:2880
static void deparseRelation(StringInfo buf, Relation rel)
Definition deparse.c:2840
NameData relname
Definition pg_class.h:40
static char buf[DEFAULT_XLOG_SEG_SIZE]
void appendStringInfoString(StringInfo str, const char *s)
Definition stringinfo.c:230
void initStringInfo(StringInfo str)
Definition stringinfo.c:97
char data[NAMEDATALEN]
Definition c.h:831

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

Referenced by fetch_relstats(), and postgresGetAnalyzeInfoForForeignTable().

◆ deparseAnalyzeSizeSql()

void deparseAnalyzeSizeSql ( StringInfo  buf,
Relation  rel 
)
extern

Definition at line 2530 of file deparse.c.

2531{
2533
2534 /* We'll need the remote relation name as a literal. */
2536 deparseRelation(&relname, rel);
2537
2538 appendStringInfoString(buf, "SELECT pg_catalog.pg_relation_size(");
2540 appendStringInfo(buf, "::pg_catalog.regclass) / %d", BLCKSZ);
2541}
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition stringinfo.c:145

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

Referenced by postgresAnalyzeForeignTable().

◆ deparseAnalyzeSql()

void deparseAnalyzeSql ( StringInfo  buf,
Relation  rel,
PgFdwSamplingMethod  sample_method,
double  sample_frac,
List **  retrieved_attrs 
)
extern

Definition at line 2592 of file deparse.c.

2595{
2596 Oid relid = RelationGetRelid(rel);
2597 TupleDesc tupdesc = RelationGetDescr(rel);
2598 int i;
2599 char *colname;
2600 List *options;
2601 ListCell *lc;
2602 bool first = true;
2603
2604 *retrieved_attrs = NIL;
2605
2606 appendStringInfoString(buf, "SELECT ");
2607 for (i = 0; i < tupdesc->natts; i++)
2608 {
2609 /* Ignore dropped columns. */
2610 if (TupleDescAttr(tupdesc, i)->attisdropped)
2611 continue;
2612
2613 if (!first)
2615 first = false;
2616
2617 /* Use attribute name or column_name option. */
2618 colname = NameStr(TupleDescAttr(tupdesc, i)->attname);
2619 options = GetForeignColumnOptions(relid, i + 1);
2620
2621 foreach(lc, options)
2622 {
2623 DefElem *def = (DefElem *) lfirst(lc);
2624
2625 if (strcmp(def->defname, "column_name") == 0)
2626 {
2627 colname = defGetString(def);
2628 break;
2629 }
2630 }
2631
2633
2634 *retrieved_attrs = lappend_int(*retrieved_attrs, i + 1);
2635 }
2636
2637 /* Don't generate bad syntax for zero-column relation. */
2638 if (first)
2639 appendStringInfoString(buf, "NULL");
2640
2641 /*
2642 * Construct FROM clause, and perhaps WHERE clause too, depending on the
2643 * selected sampling method.
2644 */
2645 appendStringInfoString(buf, " FROM ");
2646 deparseRelation(buf, rel);
2647
2648 switch (sample_method)
2649 {
2650 case ANALYZE_SAMPLE_OFF:
2651 /* nothing to do here */
2652 break;
2653
2655 appendStringInfo(buf, " WHERE pg_catalog.random() < %f", sample_frac);
2656 break;
2657
2659 appendStringInfo(buf, " TABLESAMPLE SYSTEM(%f)", (100.0 * sample_frac));
2660 break;
2661
2663 appendStringInfo(buf, " TABLESAMPLE BERNOULLI(%f)", (100.0 * sample_frac));
2664 break;
2665
2667 /* should have been resolved into actual method */
2668 elog(ERROR, "unexpected sampling method");
2669 break;
2670 }
2671}
#define NameStr(name)
Definition c.h:835
char * defGetString(DefElem *def)
Definition define.c:34
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
List * GetForeignColumnOptions(Oid relid, AttrNumber attnum)
Definition foreign.c:324
int i
Definition isn.c:77
List * lappend_int(List *list, int datum)
Definition list.c:357
NameData attname
#define lfirst(lc)
Definition pg_list.h:172
unsigned int Oid
#define RelationGetRelid(relation)
Definition rel.h:516
#define RelationGetDescr(relation)
Definition rel.h:542
const char * quote_identifier(const char *ident)
char * defname
Definition parsenodes.h:860
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:178

References ANALYZE_SAMPLE_AUTO, ANALYZE_SAMPLE_BERNOULLI, ANALYZE_SAMPLE_OFF, ANALYZE_SAMPLE_RANDOM, ANALYZE_SAMPLE_SYSTEM, appendStringInfo(), appendStringInfoString(), attname, buf, defGetString(), DefElem::defname, deparseRelation(), elog, ERROR, fb(), GetForeignColumnOptions(), i, lappend_int(), lfirst, NameStr, TupleDescData::natts, NIL, 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 
)
extern

Definition at line 2393 of file deparse.c.

2397{
2398 appendStringInfoString(buf, "DELETE FROM ");
2399 deparseRelation(buf, rel);
2400 appendStringInfoString(buf, " WHERE ctid = $1");
2401
2402 deparseReturningList(buf, rte, rtindex, rel,
2404 NIL, returningList, retrieved_attrs);
2405}
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:2473
TriggerDesc * trigdesc
Definition rel.h:117
bool trig_delete_after_row
Definition reltrigger.h:67

References appendStringInfoString(), buf, deparseRelation(), deparseReturningList(), fb(), 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 
)
extern

Definition at line 2422 of file deparse.c.

2429{
2430 deparse_expr_cxt context;
2432
2433 /* Set up context struct for recursion */
2434 context.root = root;
2435 context.foreignrel = foreignrel;
2436 context.scanrel = foreignrel;
2437 context.buf = buf;
2438 context.params_list = params_list;
2439
2440 appendStringInfoString(buf, "DELETE FROM ");
2441 deparseRelation(buf, rel);
2442 if (foreignrel->reloptkind == RELOPT_JOINREL)
2443 appendStringInfo(buf, " %s%d", REL_ALIAS_PREFIX, rtindex);
2444
2445 if (foreignrel->reloptkind == RELOPT_JOINREL)
2446 {
2448
2449 appendStringInfoString(buf, " USING ");
2450 deparseFromExprForRel(buf, root, foreignrel, true, rtindex,
2451 &ignore_conds, &additional_conds, params_list);
2452 remote_conds = list_concat(remote_conds, ignore_conds);
2453 }
2454
2455 appendWhereClause(remote_conds, additional_conds, &context);
2456
2457 if (additional_conds != NIL)
2459
2460 if (foreignrel->reloptkind == RELOPT_JOINREL)
2461 deparseExplicitTargetList(returningList, true, retrieved_attrs,
2462 &context);
2463 else
2465 rtindex, rel, false,
2466 NIL, returningList, retrieved_attrs);
2467}
#define REL_ALIAS_PREFIX
Definition deparse.c:109
static void deparseExplicitTargetList(List *tlist, bool is_returning, List **retrieved_attrs, deparse_expr_cxt *context)
Definition deparse.c:1712
static void deparseFromExprForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel, bool use_alias, Index ignore_rel, List **ignore_conds, List **additional_conds, List **params_list)
Definition deparse.c:1792
static void appendWhereClause(List *exprs, List *additional_conds, deparse_expr_cxt *context)
Definition deparse.c:1639
List * list_concat(List *list1, const List *list2)
Definition list.c:561
void list_free_deep(List *list)
Definition list.c:1560
#define planner_rt_fetch(rti, root)
Definition pathnodes.h:704
@ RELOPT_JOINREL
Definition pathnodes.h:978
RelOptKind reloptkind
Definition pathnodes.h:1015
PlannerInfo * root
Definition deparse.c:100
List ** params_list
Definition deparse.c:106
RelOptInfo * foreignrel
Definition deparse.c:101
StringInfo buf
Definition deparse.c:105
RelOptInfo * scanrel
Definition deparse.c:102

References appendStringInfo(), appendStringInfoString(), appendWhereClause(), deparse_expr_cxt::buf, buf, deparseExplicitTargetList(), deparseFromExprForRel(), deparseRelation(), deparseReturningList(), fb(), deparse_expr_cxt::foreignrel, list_concat(), list_free_deep(), NIL, deparse_expr_cxt::params_list, planner_rt_fetch, REL_ALIAS_PREFIX, RELOPT_JOINREL, RelOptInfo::reloptkind, deparse_expr_cxt::root, 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 
)
extern

Definition at line 2307 of file deparse.c.

2316{
2317 deparse_expr_cxt context;
2318 int nestlevel;
2319 bool first;
2321 ListCell *lc,
2322 *lc2;
2324
2325 /* Set up context struct for recursion */
2326 context.root = root;
2327 context.foreignrel = foreignrel;
2328 context.scanrel = foreignrel;
2329 context.buf = buf;
2330 context.params_list = params_list;
2331
2332 appendStringInfoString(buf, "UPDATE ");
2333 deparseRelation(buf, rel);
2334 if (foreignrel->reloptkind == RELOPT_JOINREL)
2335 appendStringInfo(buf, " %s%d", REL_ALIAS_PREFIX, rtindex);
2336 appendStringInfoString(buf, " SET ");
2337
2338 /* Make sure any constants in the exprs are printed portably */
2340
2341 first = true;
2342 forboth(lc, targetlist, lc2, targetAttrs)
2343 {
2345 int attnum = lfirst_int(lc2);
2346
2347 /* update's new-value expressions shouldn't be resjunk */
2348 Assert(!tle->resjunk);
2349
2350 if (!first)
2352 first = false;
2353
2354 deparseColumnRef(buf, rtindex, attnum, rte, false);
2356 deparseExpr((Expr *) tle->expr, &context);
2357 }
2358
2360
2361 if (foreignrel->reloptkind == RELOPT_JOINREL)
2362 {
2364
2365
2366 appendStringInfoString(buf, " FROM ");
2367 deparseFromExprForRel(buf, root, foreignrel, true, rtindex,
2368 &ignore_conds, &additional_conds, params_list);
2369 remote_conds = list_concat(remote_conds, ignore_conds);
2370 }
2371
2372 appendWhereClause(remote_conds, additional_conds, &context);
2373
2374 if (additional_conds != NIL)
2376
2377 if (foreignrel->reloptkind == RELOPT_JOINREL)
2378 deparseExplicitTargetList(returningList, true, retrieved_attrs,
2379 &context);
2380 else
2381 deparseReturningList(buf, rte, rtindex, rel, false,
2382 NIL, returningList, retrieved_attrs);
2383}
#define Assert(condition)
Definition c.h:943
static void deparseColumnRef(StringInfo buf, int varno, int varattno, RangeTblEntry *rte, bool qualify_col)
Definition deparse.c:2712
static void deparseExpr(Expr *node, deparse_expr_cxt *context)
Definition deparse.c:2915
int16 attnum
#define forboth(cell1, list1, cell2, list2)
Definition pg_list.h:550
#define lfirst_int(lc)
Definition pg_list.h:173
void reset_transmission_modes(int nestlevel)
int set_transmission_modes(void)

References appendStringInfo(), appendStringInfoString(), appendWhereClause(), Assert, attnum, deparse_expr_cxt::buf, buf, deparseColumnRef(), deparseExplicitTargetList(), deparseExpr(), deparseFromExprForRel(), deparseRelation(), deparseReturningList(), fb(), forboth, deparse_expr_cxt::foreignrel, lfirst_int, lfirst_node, list_concat(), list_free_deep(), NIL, deparse_expr_cxt::params_list, planner_rt_fetch, REL_ALIAS_PREFIX, RELOPT_JOINREL, RelOptInfo::reloptkind, reset_transmission_modes(), deparse_expr_cxt::root, 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 
)
extern

Definition at line 2114 of file deparse.c.

2119{
2120 TupleDesc tupdesc = RelationGetDescr(rel);
2122 bool first;
2123 ListCell *lc;
2124
2125 appendStringInfoString(buf, "INSERT INTO ");
2126 deparseRelation(buf, rel);
2127
2128 if (targetAttrs)
2129 {
2131
2132 first = true;
2133 foreach(lc, targetAttrs)
2134 {
2135 int attnum = lfirst_int(lc);
2136
2137 if (!first)
2139 first = false;
2140
2141 deparseColumnRef(buf, rtindex, attnum, rte, false);
2142 }
2143
2144 appendStringInfoString(buf, ") VALUES (");
2145
2146 pindex = 1;
2147 first = true;
2148 foreach(lc, targetAttrs)
2149 {
2150 int attnum = lfirst_int(lc);
2151 CompactAttribute *attr = TupleDescCompactAttr(tupdesc, attnum - 1);
2152
2153 if (!first)
2155 first = false;
2156
2157 if (attr->attgenerated)
2158 appendStringInfoString(buf, "DEFAULT");
2159 else
2160 {
2161 appendStringInfo(buf, "$%d", pindex);
2162 pindex++;
2163 }
2164 }
2165
2167 }
2168 else
2169 appendStringInfoString(buf, " DEFAULT VALUES");
2170 *values_end_len = buf->len;
2171
2172 if (doNothing)
2173 appendStringInfoString(buf, " ON CONFLICT DO NOTHING");
2174
2175 deparseReturningList(buf, rte, rtindex, rel,
2177 withCheckOptionList, returningList, retrieved_attrs);
2178}
int16 AttrNumber
Definition attnum.h:21
void appendStringInfoChar(StringInfo str, char ch)
Definition stringinfo.c:242
bool attgenerated
Definition tupdesc.h:79
bool trig_insert_after_row
Definition reltrigger.h:57
static CompactAttribute * TupleDescCompactAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:195

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

Referenced by postgresBeginForeignInsert(), and postgresPlanForeignModify().

◆ deparseSelectStmtForRel()

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

Definition at line 1266 of file deparse.c.

1270{
1271 deparse_expr_cxt context;
1272 PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) rel->fdw_private;
1273 List *quals;
1274
1275 /*
1276 * We handle relations for foreign tables, joins between those and upper
1277 * relations.
1278 */
1279 Assert(IS_JOIN_REL(rel) || IS_SIMPLE_REL(rel) || IS_UPPER_REL(rel));
1280
1281 /* Fill portions of context common to upper, join and base relation */
1282 context.buf = buf;
1283 context.root = root;
1284 context.foreignrel = rel;
1285 context.scanrel = IS_UPPER_REL(rel) ? fpinfo->outerrel : rel;
1286 context.params_list = params_list;
1287
1288 /* Construct SELECT clause */
1289 deparseSelectSql(tlist, is_subquery, retrieved_attrs, &context);
1290
1291 /*
1292 * For upper relations, the WHERE clause is built from the remote
1293 * conditions of the underlying scan relation; otherwise, we can use the
1294 * supplied list of remote conditions directly.
1295 */
1296 if (IS_UPPER_REL(rel))
1297 {
1299
1300 ofpinfo = (PgFdwRelationInfo *) fpinfo->outerrel->fdw_private;
1301 quals = ofpinfo->remote_conds;
1302 }
1303 else
1304 quals = remote_conds;
1305
1306 /* Construct FROM and WHERE clauses */
1307 deparseFromExpr(quals, &context);
1308
1309 if (IS_UPPER_REL(rel))
1310 {
1311 /* Append GROUP BY clause */
1312 appendGroupByClause(tlist, &context);
1313
1314 /* Append HAVING clause */
1315 if (remote_conds)
1316 {
1317 appendStringInfoString(buf, " HAVING ");
1318 appendConditions(remote_conds, &context);
1319 }
1320 }
1321
1322 /* Add ORDER BY clause if we found any useful pathkeys */
1323 if (pathkeys)
1324 appendOrderByClause(pathkeys, has_final_sort, &context);
1325
1326 /* Add LIMIT clause if necessary */
1327 if (has_limit)
1328 appendLimitClause(&context);
1329
1330 /* Add any necessary FOR UPDATE/SHARE. */
1331 deparseLockingClause(&context);
1332}
static void appendGroupByClause(List *tlist, deparse_expr_cxt *context)
Definition deparse.c:3914
static void deparseFromExpr(List *quals, deparse_expr_cxt *context)
Definition deparse.c:1406
static void deparseLockingClause(deparse_expr_cxt *context)
Definition deparse.c:1512
static void appendOrderByClause(List *pathkeys, bool has_final_sort, deparse_expr_cxt *context)
Definition deparse.c:3962
static void appendConditions(List *exprs, deparse_expr_cxt *context)
Definition deparse.c:1602
static void appendLimitClause(deparse_expr_cxt *context)
Definition deparse.c:4056
static void deparseSelectSql(List *tlist, bool is_subquery, List **retrieved_attrs, deparse_expr_cxt *context)
Definition deparse.c:1348
#define IS_SIMPLE_REL(rel)
Definition pathnodes.h:989
#define IS_JOIN_REL(rel)
Definition pathnodes.h:994
RelOptInfo * outerrel

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

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

◆ deparseStringLiteral()

void deparseStringLiteral ( StringInfo  buf,
const char val 
)
extern

Definition at line 2880 of file deparse.c.

2881{
2882 const char *valptr;
2883
2884 /*
2885 * Rather than making assumptions about the remote server's value of
2886 * standard_conforming_strings, always use E'foo' syntax if there are any
2887 * backslashes. This will fail on remote servers before 8.1, but those
2888 * are long out of support.
2889 */
2890 if (strchr(val, '\\') != NULL)
2893 for (valptr = val; *valptr; valptr++)
2894 {
2895 char ch = *valptr;
2896
2897 if (SQL_STR_DOUBLE(ch, true))
2900 }
2902}
#define ESCAPE_STRING_SYNTAX
Definition c.h:1255
#define SQL_STR_DOUBLE(ch, escape_backslash)
Definition c.h:1252
long val
Definition informix.c:689

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

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

◆ deparseTruncateSql()

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

Definition at line 2677 of file deparse.c.

2681{
2682 ListCell *cell;
2683
2684 appendStringInfoString(buf, "TRUNCATE ");
2685
2686 foreach(cell, rels)
2687 {
2688 Relation rel = lfirst(cell);
2689
2690 if (cell != list_head(rels))
2692
2693 deparseRelation(buf, rel);
2694 }
2695
2696 appendStringInfo(buf, " %s IDENTITY",
2697 restart_seqs ? "RESTART" : "CONTINUE");
2698
2699 if (behavior == DROP_RESTRICT)
2700 appendStringInfoString(buf, " RESTRICT");
2701 else if (behavior == DROP_CASCADE)
2702 appendStringInfoString(buf, " CASCADE");
2703}
@ DROP_CASCADE
@ DROP_RESTRICT
static ListCell * list_head(const List *l)
Definition pg_list.h:128

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 
)
extern

Definition at line 2247 of file deparse.c.

2252{
2253 TupleDesc tupdesc = RelationGetDescr(rel);
2255 bool first;
2256 ListCell *lc;
2257
2258 appendStringInfoString(buf, "UPDATE ");
2259 deparseRelation(buf, rel);
2260 appendStringInfoString(buf, " SET ");
2261
2262 pindex = 2; /* ctid is always the first param */
2263 first = true;
2264 foreach(lc, targetAttrs)
2265 {
2266 int attnum = lfirst_int(lc);
2267 CompactAttribute *attr = TupleDescCompactAttr(tupdesc, attnum - 1);
2268
2269 if (!first)
2271 first = false;
2272
2273 deparseColumnRef(buf, rtindex, attnum, rte, false);
2274 if (attr->attgenerated)
2275 appendStringInfoString(buf, " = DEFAULT");
2276 else
2277 {
2278 appendStringInfo(buf, " = $%d", pindex);
2279 pindex++;
2280 }
2281 }
2282 appendStringInfoString(buf, " WHERE ctid = $1");
2283
2284 deparseReturningList(buf, rte, rtindex, rel,
2286 withCheckOptionList, returningList, retrieved_attrs);
2287}
bool trig_update_after_row
Definition reltrigger.h:62

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

Referenced by postgresPlanForeignModify().

◆ do_sql_command()

void do_sql_command ( PGconn conn,
const char sql 
)
extern

Definition at line 841 of file connection.c.

842{
844 do_sql_command_end(conn, sql, false);
845}
static void do_sql_command_end(PGconn *conn, const char *sql, bool consume_input)
Definition connection.c:855
static void do_sql_command_begin(PGconn *conn, const char *sql)
Definition connection.c:848
PGconn * conn
Definition streamutil.c:52

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 
)
extern

Definition at line 418 of file option.c.

420{
421 ListCell *lc;
422 int i;
423
424 /* Build our options lists if we didn't yet. */
426
427 i = 0;
428 foreach(lc, defelems)
429 {
430 DefElem *d = (DefElem *) lfirst(lc);
431
432 if (is_libpq_option(d->defname))
433 {
434 keywords[i] = d->defname;
435 values[i] = defGetString(d);
436 i++;
437 }
438 }
439 return i;
440}
static Datum values[MAXATTR]
Definition bootstrap.c:190
static bool is_libpq_option(const char *keyword)
Definition option.c:397
static void InitPgFdwOptions(void)
Definition option.c:235
static const JsonPathKeyword keywords[]

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

Referenced by construct_connection_params().

◆ ExtractExtensionList()

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

Definition at line 449 of file option.c.

450{
452 List *extlist;
453 ListCell *lc;
454
455 /* SplitIdentifierString scribbles on its input, so pstrdup first */
457 {
458 /* syntax error in name list */
461 errmsg("parameter \"%s\" must be a list of extension names",
462 "extensions")));
463 }
464
465 foreach(lc, extlist)
466 {
467 const char *extension_name = (const char *) lfirst(lc);
469
471 {
473 }
474 else if (warnOnMissing)
475 {
478 errmsg("extension \"%s\" is not installed",
480 }
481 }
482
484 return extensionOids;
485}
#define OidIsValid(objectId)
Definition c.h:858
int errcode(int sqlerrcode)
Definition elog.c:874
#define WARNING
Definition elog.h:37
#define ereport(elevel,...)
Definition elog.h:152
Oid get_extension_oid(const char *extname, bool missing_ok)
Definition extension.c:229
List * lappend_oid(List *list, Oid datum)
Definition list.c:375
void list_free(List *list)
Definition list.c:1546
char * pstrdup(const char *in)
Definition mcxt.c:1781
static char * errmsg
bool SplitIdentifierString(char *rawstring, char separator, List **namelist)
Definition varlena.c:2867

References ereport, errcode(), errmsg, ERROR, fb(), 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 
)
extern

Definition at line 8680 of file postgres_fdw.c.

8681{
8682 PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) rel->fdw_private;
8685
8687 while ((em = eclass_member_iterator_next(&it)) != NULL)
8688 {
8689 /*
8690 * Note we require !bms_is_empty, else we'd accept constant
8691 * expressions which are not suitable for the purpose.
8692 */
8693 if (bms_is_subset(em->em_relids, rel->relids) &&
8694 !bms_is_empty(em->em_relids) &&
8695 bms_is_empty(bms_intersect(em->em_relids, fpinfo->hidden_subquery_rels)) &&
8696 is_foreign_expr(root, rel, em->em_expr))
8697 return em;
8698 }
8699
8700 return NULL;
8701}
Bitmapset * bms_intersect(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:292
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:412
#define bms_is_empty(a)
Definition bitmapset.h:118
void setup_eclass_member_iterator(EquivalenceMemberIterator *it, EquivalenceClass *ec, Relids child_relids)
EquivalenceMember * eclass_member_iterator_next(EquivalenceMemberIterator *it)
Relids relids
Definition pathnodes.h:1021

References bms_intersect(), bms_is_empty, bms_is_subset(), eclass_member_iterator_next(), fb(), is_foreign_expr(), RelOptInfo::relids, root, and setup_eclass_member_iterator().

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 
)
extern

Definition at line 8715 of file postgres_fdw.c.

8717{
8718 PathTarget *target = rel->reltarget;
8719 ListCell *lc1;
8720 int i;
8721
8722 i = 0;
8723 foreach(lc1, target->exprs)
8724 {
8725 Expr *expr = (Expr *) lfirst(lc1);
8727 ListCell *lc2;
8728
8729 /* Ignore non-sort expressions */
8730 if (sgref == 0 ||
8732 root->parse->sortClause) == NULL)
8733 {
8734 i++;
8735 continue;
8736 }
8737
8738 /* We ignore binary-compatible relabeling on both ends */
8739 while (expr && IsA(expr, RelabelType))
8740 expr = ((RelabelType *) expr)->arg;
8741
8742 /*
8743 * Locate an EquivalenceClass member matching this expr, if any.
8744 * Ignore child members.
8745 */
8746 foreach(lc2, ec->ec_members)
8747 {
8749 Expr *em_expr;
8750
8751 /* Don't match constants */
8752 if (em->em_is_const)
8753 continue;
8754
8755 /* Child members should not exist in ec_members */
8756 Assert(!em->em_is_child);
8757
8758 /* Match if same expression (after stripping relabel) */
8759 em_expr = em->em_expr;
8760 while (em_expr && IsA(em_expr, RelabelType))
8761 em_expr = ((RelabelType *) em_expr)->arg;
8762
8763 if (!equal(em_expr, expr))
8764 continue;
8765
8766 /* Check that expression (including relabels!) is shippable */
8767 if (is_foreign_expr(root, rel, em->em_expr))
8768 return em;
8769 }
8770
8771 i++;
8772 }
8773
8774 return NULL;
8775}
unsigned int Index
Definition c.h:698
bool equal(const void *a, const void *b)
Definition equalfuncs.c:223
#define IsA(nodeptr, _type_)
Definition nodes.h:164
#define get_pathtarget_sortgroupref(target, colno)
Definition pathnodes.h:1894
SortGroupClause * get_sortgroupref_clause_noerr(Index sortref, List *clauses)
Definition tlist.c:452

References Assert, EquivalenceClass::ec_members, equal(), PathTarget::exprs, fb(), get_pathtarget_sortgroupref, get_sortgroupref_clause_noerr(), i, is_foreign_expr(), IsA, lfirst, RelOptInfo::reltarget, and root.

Referenced by add_foreign_ordered_paths(), and appendOrderByClause().

◆ get_jointype_name()

const char * get_jointype_name ( JoinType  jointype)
extern

Definition at line 1672 of file deparse.c.

1673{
1674 switch (jointype)
1675 {
1676 case JOIN_INNER:
1677 return "INNER";
1678
1679 case JOIN_LEFT:
1680 return "LEFT";
1681
1682 case JOIN_RIGHT:
1683 return "RIGHT";
1684
1685 case JOIN_FULL:
1686 return "FULL";
1687
1688 case JOIN_SEMI:
1689 return "SEMI";
1690
1691 default:
1692 /* Shouldn't come here, but protect from buggy code. */
1693 elog(ERROR, "unsupported join type %d", jointype);
1694 }
1695
1696 /* Keep compiler happy */
1697 return NULL;
1698}
@ JOIN_SEMI
Definition nodes.h:317
@ JOIN_FULL
Definition nodes.h:305
@ JOIN_INNER
Definition nodes.h:303
@ JOIN_RIGHT
Definition nodes.h:306
@ JOIN_LEFT
Definition nodes.h:304

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

Referenced by deparseFromExprForRel(), and foreign_join_ok().

◆ GetConnection()

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

Definition at line 216 of file connection.c.

217{
218 bool found;
219 bool retry = false;
220 ConnCacheEntry *entry;
223
224 /* First time through, initialize connection cache hashtable */
225 if (ConnectionHash == NULL)
226 {
227 HASHCTL ctl;
228
229 if (pgfdw_we_get_result == 0)
231 WaitEventExtensionNew("PostgresFdwGetResult");
232
233 ctl.keysize = sizeof(ConnCacheKey);
234 ctl.entrysize = sizeof(ConnCacheEntry);
235 ConnectionHash = hash_create("postgres_fdw connections", 8,
236 &ctl,
238
239 /*
240 * Register some callback functions that manage connection cleanup.
241 * This should be done just once in each backend.
242 */
249 }
250
251 /* Set flag that we did GetConnection during the current transaction */
252 xact_got_connection = true;
253
254 /* Create hash key for the entry. Assume no pad bytes in key struct */
255 key = user->umid;
256
257 /*
258 * Find or create cached entry for requested connection.
259 */
260 entry = hash_search(ConnectionHash, &key, HASH_ENTER, &found);
261 if (!found)
262 {
263 /*
264 * We need only clear "conn" here; remaining fields will be filled
265 * later when "conn" is set.
266 */
267 entry->conn = NULL;
268 }
269
270 /* Reject further use of connections which failed abort cleanup. */
272
273 /*
274 * If the connection needs to be remade due to invalidation, disconnect as
275 * soon as we're out of all transactions.
276 */
277 if (entry->conn != NULL && entry->invalidated && entry->xact_depth == 0)
278 {
279 elog(DEBUG3, "closing connection %p for option changes to take effect",
280 entry->conn);
282 }
283
284 /*
285 * If cache entry doesn't have a connection, we have to establish a new
286 * connection. (If connect_pg_server throws an error, the cache entry
287 * will remain in a valid empty state, ie conn == NULL.)
288 */
289 if (entry->conn == NULL)
291
292 /*
293 * We check the health of the cached connection here when using it. In
294 * cases where we're out of all transactions, if a broken connection is
295 * detected, we try to reestablish a new connection later.
296 */
297 PG_TRY();
298 {
299 /* Process a pending asynchronous request if any. */
300 if (entry->state.pendingAreq)
302 /* Start a new transaction or subtransaction if needed. */
303 begin_remote_xact(entry);
304 }
305 PG_CATCH();
306 {
309
310 /*
311 * Determine whether to try to reestablish the connection.
312 *
313 * After a broken connection is detected in libpq, any error other
314 * than connection failure (e.g., out-of-memory) can be thrown
315 * somewhere between return from libpq and the expected ereport() call
316 * in pgfdw_report_error(). In this case, since PQstatus() indicates
317 * CONNECTION_BAD, checking only PQstatus() causes the false detection
318 * of connection failure. To avoid this, we also verify that the
319 * error's sqlstate is ERRCODE_CONNECTION_FAILURE. Note that also
320 * checking only the sqlstate can cause another false detection
321 * because pgfdw_report_error() may report ERRCODE_CONNECTION_FAILURE
322 * for any libpq-originated error condition.
323 */
324 if (errdata->sqlerrcode != ERRCODE_CONNECTION_FAILURE ||
325 PQstatus(entry->conn) != CONNECTION_BAD ||
326 entry->xact_depth > 0)
327 {
329 PG_RE_THROW();
330 }
331
332 /* Clean up the error state */
335 errdata = NULL;
336
337 retry = true;
338 }
339 PG_END_TRY();
340
341 /*
342 * If a broken connection is detected, disconnect it, reestablish a new
343 * connection and retry a new remote transaction. If connection failure is
344 * reported again, we give up getting a connection.
345 */
346 if (retry)
347 {
348 Assert(entry->xact_depth == 0);
349
351 (errmsg_internal("could not start remote transaction on connection %p",
352 entry->conn)),
354
355 elog(DEBUG3, "closing connection %p to reestablish a new one",
356 entry->conn);
358
360
361 begin_remote_xact(entry);
362 }
363
364 /* Remember if caller will prepare statements */
366
367 /* If caller needs access to the per-connection state, return it. */
368 if (state)
369 *state = &entry->state;
370
371 return entry->conn;
372}
Oid ConnCacheKey
Definition connection.c:54
static void disconnect_pg_server(ConnCacheEntry *entry)
Definition connection.c:688
static uint32 pgfdw_we_get_result
Definition connection.c:99
static bool xact_got_connection
Definition connection.c:88
static HTAB * ConnectionHash
Definition connection.c:81
static void make_new_connection(ConnCacheEntry *entry, UserMapping *user)
Definition connection.c:379
static void pgfdw_subxact_callback(SubXactEvent event, SubTransactionId mySubid, SubTransactionId parentSubid, void *arg)
static void pgfdw_reject_incomplete_xact_state_change(ConnCacheEntry *entry)
static void pgfdw_xact_callback(XactEvent event, void *arg)
static void begin_remote_xact(ConnCacheEntry *entry)
Definition connection.c:889
static void pgfdw_inval_callback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition dynahash.c:889
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
Definition dynahash.c:360
void FreeErrorData(ErrorData *edata)
Definition elog.c:2013
ErrorData * CopyErrorData(void)
Definition elog.c:1941
void FlushErrorState(void)
Definition elog.c:2062
#define PG_RE_THROW()
Definition elog.h:407
int int errdetail_internal(const char *fmt,...) pg_attribute_printf(1
#define DEBUG3
Definition elog.h:29
int int errmsg_internal(const char *fmt,...) pg_attribute_printf(1
#define PG_TRY(...)
Definition elog.h:374
#define PG_END_TRY(...)
Definition elog.h:399
#define PG_CATCH(...)
Definition elog.h:384
ConnStatusType PQstatus(const PGconn *conn)
char * PQerrorMessage(const PGconn *conn)
@ HASH_ENTER
Definition hsearch.h:109
#define HASH_ELEM
Definition hsearch.h:90
#define HASH_BLOBS
Definition hsearch.h:92
void CacheRegisterSyscacheCallback(SysCacheIdentifier cacheid, SyscacheCallbackFunction func, Datum arg)
Definition inval.c:1816
@ CONNECTION_BAD
Definition libpq-fe.h:91
char * pchomp(const char *in)
Definition mcxt.c:1809
MemoryContext CurrentMemoryContext
Definition mcxt.c:160
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
static char * user
Definition pg_regress.c:121
uint64_t Datum
Definition postgres.h:70
void process_pending_request(AsyncRequest *areq)
tree ctl
Definition radixtree.h:1838
PGconn * conn
Definition connection.c:59
bool have_prep_stmt
Definition connection.c:64
PgFdwConnState state
Definition connection.c:75
AsyncRequest * pendingAreq
uint32 WaitEventExtensionNew(const char *wait_event_name)
Definition wait_event.c:149
void RegisterXactCallback(XactCallback callback, void *arg)
Definition xact.c:3855
void RegisterSubXactCallback(SubXactCallback callback, void *arg)
Definition xact.c:3915

References Assert, begin_remote_xact(), CacheRegisterSyscacheCallback(), ConnCacheEntry::conn, CONNECTION_BAD, ConnectionHash, CopyErrorData(), ctl, CurrentMemoryContext, DEBUG3, disconnect_pg_server(), elog, ereport, errdetail_internal(), errmsg_internal(), fb(), FlushErrorState(), FreeErrorData(), HASH_BLOBS, hash_create(), HASH_ELEM, HASH_ENTER, hash_search(), ConnCacheEntry::have_prep_stmt, ConnCacheEntry::invalidated, 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_we_get_result, pgfdw_xact_callback(), PQerrorMessage(), PQstatus(), process_pending_request(), RegisterSubXactCallback(), RegisterXactCallback(), ConnCacheEntry::state, user, WaitEventExtensionNew(), ConnCacheEntry::xact_depth, and xact_got_connection.

◆ GetCursorNumber()

unsigned int GetCursorNumber ( PGconn conn)
extern

Definition at line 1034 of file connection.c.

1035{
1036 return ++cursor_number;
1037}
static unsigned int cursor_number
Definition connection.c:84

References cursor_number.

Referenced by postgresAcquireSampleRowsFunc(), and postgresBeginForeignScan().

◆ GetPrepStmtNumber()

unsigned int GetPrepStmtNumber ( PGconn conn)
extern

Definition at line 1048 of file connection.c.

1049{
1050 return ++prep_stmt_number;
1051}
static unsigned int prep_stmt_number
Definition connection.c:85

References prep_stmt_number.

Referenced by prepare_foreign_modify().

◆ is_builtin()

bool is_builtin ( Oid  objectId)
extern

Definition at line 153 of file shippable.c.

154{
155 return (objectId < FirstGenbkiObjectId);
156}
#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 
)
extern

Definition at line 244 of file deparse.c.

247{
251
252 /*
253 * Check that the expression consists of nodes that are safe to execute
254 * remotely.
255 */
256 glob_cxt.root = root;
257 glob_cxt.foreignrel = baserel;
258
259 /*
260 * For an upper relation, use relids from its underneath scan relation,
261 * because the upperrel's own relids currently aren't set to anything
262 * meaningful by the core code. For other relation, use their own relids.
263 */
265 glob_cxt.relids = fpinfo->outerrel->relids;
266 else
267 glob_cxt.relids = baserel->relids;
268 loc_cxt.collation = InvalidOid;
270 if (!foreign_expr_walker((Node *) expr, &glob_cxt, &loc_cxt, NULL))
271 return false;
272
273 /*
274 * If the expression has a valid collation that does not arise from a
275 * foreign var, the expression can not be sent over.
276 */
277 if (loc_cxt.state == FDW_COLLATE_UNSAFE)
278 return false;
279
280 /*
281 * An expression which includes any mutable functions can't be sent over
282 * because its result is not stable. For example, sending now() remote
283 * side could cause confusion from clock offsets. Future versions might
284 * be able to make this choice with more granularity. (We check this last
285 * because it requires a lot of expensive catalog lookups.)
286 */
287 if (contain_mutable_functions((Node *) expr))
288 return false;
289
290 /* OK to evaluate on the remote server */
291 return true;
292}
bool contain_mutable_functions(Node *clause)
Definition clauses.c:381
@ FDW_COLLATE_UNSAFE
Definition deparse.c:85
@ FDW_COLLATE_NONE
Definition deparse.c:81
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:312
#define InvalidOid

References contain_mutable_functions(), fb(), FDW_COLLATE_NONE, FDW_COLLATE_UNSAFE, foreign_expr_walker(), InvalidOid, IS_UPPER_REL, PgFdwRelationInfo::outerrel, RelOptInfo::relids, and root.

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 
)
extern

Definition at line 1115 of file deparse.c.

1118{
1119 if (expr == NULL)
1120 return false;
1121
1122 switch (nodeTag(expr))
1123 {
1124 case T_Var:
1125 {
1126 /* It would have to be sent unless it's a foreign Var */
1127 Var *var = (Var *) expr;
1128 PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) (baserel->fdw_private);
1129 Relids relids;
1130
1131 if (IS_UPPER_REL(baserel))
1132 relids = fpinfo->outerrel->relids;
1133 else
1134 relids = baserel->relids;
1135
1136 if (bms_is_member(var->varno, relids) && var->varlevelsup == 0)
1137 return false; /* foreign Var, so not a param */
1138 else
1139 return true; /* it'd have to be a param */
1140 break;
1141 }
1142 case T_Param:
1143 /* Params always have to be sent to the foreign server */
1144 return true;
1145 default:
1146 break;
1147 }
1148 return false;
1149}
bool bms_is_member(int x, const Bitmapset *a)
Definition bitmapset.c:510
#define nodeTag(nodeptr)
Definition nodes.h:139
int varno
Definition primnodes.h:270
Index varlevelsup
Definition primnodes.h:295

References bms_is_member(), fb(), IS_UPPER_REL, nodeTag, Var::varlevelsup, and Var::varno.

Referenced by foreign_grouping_ok().

◆ is_foreign_pathkey()

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

Definition at line 1156 of file deparse.c.

1159{
1160 EquivalenceClass *pathkey_ec = pathkey->pk_eclass;
1162
1163 /*
1164 * is_foreign_expr would detect volatile expressions as well, but checking
1165 * ec_has_volatile here saves some cycles.
1166 */
1167 if (pathkey_ec->ec_has_volatile)
1168 return false;
1169
1170 /* can't push down the sort if the pathkey's opfamily is not shippable */
1172 return false;
1173
1174 /* can push if a suitable EC member exists */
1176}
EquivalenceMember * find_em_for_rel(PlannerInfo *root, EquivalenceClass *ec, RelOptInfo *rel)
bool is_shippable(Oid objectId, Oid classId, PgFdwRelationInfo *fpinfo)
Definition shippable.c:163

References fb(), find_em_for_rel(), is_shippable(), and root.

Referenced by get_useful_pathkeys_for_relation().

◆ is_shippable()

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

Definition at line 163 of file shippable.c.

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. */
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
189 if (!entry)
190 {
191 /* Not found in cache, so perform shippability lookup. */
192 bool shippable = lookup_shippable(objectId, classId, fpinfo);
193
194 /*
195 * Don't create a new hash entry until *after* we have the shippable
196 * result in hand, as the underlying catalog lookups might trigger a
197 * cache invalidation.
198 */
199 entry = (ShippableCacheEntry *)
201
202 entry->shippable = shippable;
203 }
204
205 return entry->shippable;
206}
@ HASH_FIND
Definition hsearch.h:108
static bool lookup_shippable(Oid objectId, Oid classId, PgFdwRelationInfo *fpinfo)
Definition shippable.c:117
bool is_builtin(Oid objectId)
Definition shippable.c:153
static void InitializeShippableCache(void)
Definition shippable.c:92
static HTAB * ShippableCacheHash
Definition shippable.c:34

References fb(), HASH_ENTER, HASH_FIND, hash_search(), InitializeShippableCache(), is_builtin(), lookup_shippable(), NIL, ShippableCacheEntry::shippable, 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 
)
extern

Definition at line 1063 of file connection.c.

1064{
1065 /* First, process a pending asynchronous request, if any. */
1066 if (state && state->pendingAreq)
1067 process_pending_request(state->pendingAreq);
1068
1069 if (!PQsendQuery(conn, query))
1070 return NULL;
1071 return pgfdw_get_result(conn);
1072}
PGresult * pgfdw_get_result(PGconn *conn)
int PQsendQuery(PGconn *conn, const char *query)
Definition fe-exec.c:1433

References conn, fb(), pgfdw_get_result(), PQsendQuery(), and process_pending_request().

Referenced by close_cursor(), deallocate_query(), fetch_attstats(), fetch_more_data(), fetch_relstats(), get_remote_estimate(), pgfdw_xact_callback(), postgresAcquireSampleRowsFunc(), postgresAnalyzeForeignTable(), postgresGetAnalyzeInfoForForeignTable(), postgresImportForeignSchema(), and postgresReScanForeignScan().

◆ pgfdw_get_result()

PGresult * pgfdw_get_result ( PGconn conn)
extern

Definition at line 1080 of file connection.c.

1081{
1083}
static PGresult * libpqsrv_get_result_last(PGconn *conn, uint32 wait_event_info)

References conn, libpqsrv_get_result_last(), and pgfdw_we_get_result.

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

void pgfdw_report ( int  elevel,
PGresult res,
PGconn conn,
const char sql 
)
extern

Definition at line 1111 of file connection.c.

1112{
1113 Assert(elevel < ERROR); /* use pgfdw_report_error for that */
1114 pgfdw_report_internal(elevel, res, conn, sql);
1115}
static void pgfdw_report_internal(int elevel, PGresult *res, PGconn *conn, const char *sql)

References Assert, conn, ERROR, and pgfdw_report_internal().

Referenced by pgfdw_exec_cleanup_query_begin(), and pgfdw_exec_cleanup_query_end().

◆ pgfdw_report_error()

◆ process_pending_request()

void process_pending_request ( AsyncRequest areq)
extern

Definition at line 8353 of file postgres_fdw.c.

8354{
8355 ForeignScanState *node = (ForeignScanState *) areq->requestee;
8356 PgFdwScanState *fsstate = (PgFdwScanState *) node->fdw_state;
8357
8358 /* The request would have been pending for a callback */
8359 Assert(areq->callback_pending);
8360
8361 /* The request should be currently in-process */
8362 Assert(fsstate->conn_state->pendingAreq == areq);
8363
8364 fetch_more_data(node);
8365
8366 /*
8367 * If we didn't get any tuples, must be end of data; complete the request
8368 * now. Otherwise, we postpone completing the request until we are called
8369 * from postgresForeignAsyncConfigureWait()/postgresForeignAsyncNotify().
8370 */
8371 if (fsstate->next_tuple >= fsstate->num_tuples)
8372 {
8373 /* Unlike AsyncNotify, we unset callback_pending ourselves */
8374 areq->callback_pending = false;
8375 /* Mark the request as complete */
8377 /* Unlike AsyncNotify, we call ExecAsyncResponse ourselves */
8379 }
8380}
void ExecAsyncResponse(AsyncRequest *areq)
Definition execAsync.c:118
void ExecAsyncRequestDone(AsyncRequest *areq, TupleTableSlot *result)
Definition execAsync.c:138
static void fetch_more_data(ForeignScanState *node)
PgFdwConnState * conn_state

References Assert, PgFdwScanState::conn_state, ExecAsyncRequestDone(), ExecAsyncResponse(), fb(), ForeignScanState::fdw_state, fetch_more_data(), PgFdwScanState::next_tuple, PgFdwScanState::num_tuples, and PgFdwConnState::pendingAreq.

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)
extern

Definition at line 495 of file option.c.

496{
497 const char *p;
499
501
502 for (p = appname; *p != '\0'; p++)
503 {
504 if (*p != '%')
505 {
506 /* literal char, just copy */
508 continue;
509 }
510
511 /* must be a '%', so skip to the next char */
512 p++;
513 if (*p == '\0')
514 break; /* format error - ignore it */
515 else if (*p == '%')
516 {
517 /* string contains %% */
519 continue;
520 }
521
522 /* process the option */
523 switch (*p)
524 {
525 case 'a':
527 break;
528 case 'c':
530 break;
531 case 'C':
533 break;
534 case 'd':
535 if (MyProcPort)
536 {
537 const char *dbname = MyProcPort->database_name;
538
539 if (dbname)
541 else
542 appendStringInfoString(&buf, "[unknown]");
543 }
544 break;
545 case 'p':
547 break;
548 case 'u':
549 if (MyProcPort)
550 {
551 const char *username = MyProcPort->user_name;
552
553 if (username)
555 else
556 appendStringInfoString(&buf, "[unknown]");
557 }
558 break;
559 default:
560 /* format error - ignore it */
561 break;
562 }
563 }
564
565 return buf.data;
566}
int MyProcPid
Definition globals.c:49
struct Port * MyProcPort
Definition globals.c:53
pg_time_t MyStartTime
Definition globals.c:50
char * cluster_name
Definition guc_tables.c:582
char * application_name
Definition guc_tables.c:589
static char * username
Definition initdb.c:153
char * dbname
Definition streamutil.c:49
char * user_name
Definition libpq-be.h:151
char * database_name
Definition libpq-be.h:150

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

Referenced by construct_connection_params().

◆ rebuildInsertSql()

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

Definition at line 2187 of file deparse.c.

2191{
2192 TupleDesc tupdesc = RelationGetDescr(rel);
2193 int i;
2194 int pindex;
2195 bool first;
2196 ListCell *lc;
2197
2198 /* Make sure the values_end_len is sensible */
2199 Assert((values_end_len > 0) && (values_end_len <= strlen(orig_query)));
2200
2201 /* Copy up to the end of the first record from the original query */
2203
2204 /*
2205 * Add records to VALUES clause (we already have parameters for the first
2206 * row, so start at the right offset).
2207 */
2208 pindex = num_params + 1;
2209 for (i = 0; i < num_rows; i++)
2210 {
2212
2213 first = true;
2214 foreach(lc, target_attrs)
2215 {
2216 int attnum = lfirst_int(lc);
2217 CompactAttribute *attr = TupleDescCompactAttr(tupdesc, attnum - 1);
2218
2219 if (!first)
2221 first = false;
2222
2223 if (attr->attgenerated)
2224 appendStringInfoString(buf, "DEFAULT");
2225 else
2226 {
2227 appendStringInfo(buf, "$%d", pindex);
2228 pindex++;
2229 }
2230 }
2231
2233 }
2234
2235 /* Copy stuff after VALUES clause from the original query */
2237}
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition stringinfo.c:281

References appendBinaryStringInfo(), appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), Assert, CompactAttribute::attgenerated, attnum, buf, fb(), i, lfirst_int, RelationGetDescr, and TupleDescCompactAttr().

Referenced by execute_foreign_modify().

◆ ReleaseConnection()

void ReleaseConnection ( PGconn conn)
extern

Definition at line 1013 of file connection.c.

1014{
1015 /*
1016 * Currently, we don't actually track connection references because all
1017 * cleanup is managed on a transaction or subtransaction basis instead. So
1018 * there's nothing to do here.
1019 */
1020}

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

◆ reset_transmission_modes()

void reset_transmission_modes ( int  nestlevel)
extern

Definition at line 4144 of file postgres_fdw.c.

4145{
4146 AtEOXact_GUC(true, nestlevel);
4147}
void AtEOXact_GUC(bool isCommit, int nestLevel)
Definition guc.c:2169

References AtEOXact_GUC(), and fb().

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

◆ set_transmission_modes()

int set_transmission_modes ( void  )
extern

Definition at line 4108 of file postgres_fdw.c.

4109{
4110 int nestlevel = NewGUCNestLevel();
4111
4112 /*
4113 * The values set here should match what pg_dump does. See also
4114 * configure_remote_session in connection.c.
4115 */
4116 if (DateStyle != USE_ISO_DATES)
4117 (void) set_config_option("datestyle", "ISO",
4119 GUC_ACTION_SAVE, true, 0, false);
4121 (void) set_config_option("intervalstyle", "postgres",
4123 GUC_ACTION_SAVE, true, 0, false);
4124 if (extra_float_digits < 3)
4125 (void) set_config_option("extra_float_digits", "3",
4127 GUC_ACTION_SAVE, true, 0, false);
4128
4129 /*
4130 * In addition force restrictive search_path, in case there are any
4131 * regproc or similar constants to be printed.
4132 */
4133 (void) set_config_option("search_path", "pg_catalog",
4135 GUC_ACTION_SAVE, true, 0, false);
4136
4137 return nestlevel;
4138}
int extra_float_digits
Definition float.c:57
int DateStyle
Definition globals.c:127
int IntervalStyle
Definition globals.c:129
int NewGUCNestLevel(void)
Definition guc.c:2142
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:3248
@ GUC_ACTION_SAVE
Definition guc.h:205
@ PGC_S_SESSION
Definition guc.h:126
@ PGC_USERSET
Definition guc.h:79
#define USE_ISO_DATES
Definition miscadmin.h:240
#define INTSTYLE_POSTGRES
Definition miscadmin.h:260

References DateStyle, extra_float_digits, fb(), 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 46 of file option.c.

Referenced by _PG_init(), and construct_connection_params().