PostgreSQL Source Code  git master
deparse.c File Reference
#include "postgres.h"
#include "postgres_fdw.h"
#include "access/heapam.h"
#include "access/htup_details.h"
#include "access/sysattr.h"
#include "catalog/pg_aggregate.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "commands/defrem.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "nodes/plannodes.h"
#include "optimizer/clauses.h"
#include "optimizer/prep.h"
#include "optimizer/tlist.h"
#include "optimizer/var.h"
#include "parser/parsetree.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/syscache.h"
#include "utils/typcache.h"
Include dependency graph for deparse.c:

Go to the source code of this file.

Data Structures

struct  foreign_glob_cxt
 
struct  foreign_loc_cxt
 
struct  deparse_expr_cxt
 

Macros

#define REL_ALIAS_PREFIX   "r"
 
#define ADD_REL_QUALIFIER(buf, varno)   appendStringInfo((buf), "%s%d.", REL_ALIAS_PREFIX, (varno))
 
#define SUBQUERY_REL_ALIAS_PREFIX   "s"
 
#define SUBQUERY_COL_ALIAS_PREFIX   "c"
 

Typedefs

typedef struct foreign_glob_cxt foreign_glob_cxt
 
typedef struct foreign_loc_cxt foreign_loc_cxt
 
typedef struct deparse_expr_cxt deparse_expr_cxt
 

Enumerations

enum  FDWCollateState { FDW_COLLATE_NONE, FDW_COLLATE_SAFE, FDW_COLLATE_UNSAFE }
 

Functions

static bool foreign_expr_walker (Node *node, foreign_glob_cxt *glob_cxt, foreign_loc_cxt *outer_cxt)
 
static char * deparse_type_name (Oid type_oid, int32 typemod)
 
static void deparseTargetList (StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, bool is_returning, Bitmapset *attrs_used, bool qualify_col, List **retrieved_attrs)
 
static void deparseExplicitTargetList (List *tlist, bool is_returning, List **retrieved_attrs, deparse_expr_cxt *context)
 
static void deparseSubqueryTargetList (deparse_expr_cxt *context)
 
static void deparseReturningList (StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, bool trig_after_row, List *returningList, List **retrieved_attrs)
 
static void deparseColumnRef (StringInfo buf, int varno, int varattno, RangeTblEntry *rte, bool qualify_col)
 
static void deparseRelation (StringInfo buf, Relation rel)
 
static void deparseExpr (Expr *expr, deparse_expr_cxt *context)
 
static void deparseVar (Var *node, deparse_expr_cxt *context)
 
static void deparseConst (Const *node, deparse_expr_cxt *context, int showtype)
 
static void deparseParam (Param *node, deparse_expr_cxt *context)
 
static void deparseArrayRef (ArrayRef *node, deparse_expr_cxt *context)
 
static void deparseFuncExpr (FuncExpr *node, deparse_expr_cxt *context)
 
static void deparseOpExpr (OpExpr *node, deparse_expr_cxt *context)
 
static void deparseOperatorName (StringInfo buf, Form_pg_operator opform)
 
static void deparseDistinctExpr (DistinctExpr *node, deparse_expr_cxt *context)
 
static void deparseScalarArrayOpExpr (ScalarArrayOpExpr *node, deparse_expr_cxt *context)
 
static void deparseRelabelType (RelabelType *node, deparse_expr_cxt *context)
 
static void deparseBoolExpr (BoolExpr *node, deparse_expr_cxt *context)
 
static void deparseNullTest (NullTest *node, deparse_expr_cxt *context)
 
static void deparseArrayExpr (ArrayExpr *node, deparse_expr_cxt *context)
 
static void printRemoteParam (int paramindex, Oid paramtype, int32 paramtypmod, deparse_expr_cxt *context)
 
static void printRemotePlaceholder (Oid paramtype, int32 paramtypmod, deparse_expr_cxt *context)
 
static void deparseSelectSql (List *tlist, bool is_subquery, List **retrieved_attrs, deparse_expr_cxt *context)
 
static void deparseLockingClause (deparse_expr_cxt *context)
 
static void appendOrderByClause (List *pathkeys, deparse_expr_cxt *context)
 
static void appendConditions (List *exprs, deparse_expr_cxt *context)
 
static void deparseFromExprForRel (StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel, bool use_alias, Index ignore_rel, List **ignore_conds, List **params_list)
 
static void deparseFromExpr (List *quals, deparse_expr_cxt *context)
 
static void deparseRangeTblRef (StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel, bool make_subquery, Index ignore_rel, List **ignore_conds, List **params_list)
 
static void deparseAggref (Aggref *node, deparse_expr_cxt *context)
 
static void appendGroupByClause (List *tlist, deparse_expr_cxt *context)
 
static void appendAggOrderBy (List *orderList, List *targetList, deparse_expr_cxt *context)
 
static void appendFunctionName (Oid funcid, deparse_expr_cxt *context)
 
static NodedeparseSortGroupClause (Index ref, List *tlist, bool force_colno, deparse_expr_cxt *context)
 
static bool is_subquery_var (Var *node, RelOptInfo *foreignrel, int *relno, int *colno)
 
static void get_relation_column_alias_ids (Var *node, RelOptInfo *foreignrel, int *relno, int *colno)
 
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)
 
Listbuild_tlist_to_deparse (RelOptInfo *foreignrel)
 
void deparseSelectStmtForRel (StringInfo buf, PlannerInfo *root, RelOptInfo *rel, List *tlist, List *remote_conds, List *pathkeys, bool is_subquery, List **retrieved_attrs, List **params_list)
 
const char * get_jointype_name (JoinType jointype)
 
void deparseInsertSql (StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, List *targetAttrs, bool doNothing, List *returningList, List **retrieved_attrs)
 
void deparseUpdateSql (StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, List *targetAttrs, List *returningList, List **retrieved_attrs)
 
void deparseDirectUpdateSql (StringInfo buf, PlannerInfo *root, Index rtindex, Relation rel, RelOptInfo *foreignrel, List *targetlist, List *targetAttrs, List *remote_conds, List **params_list, List *returningList, List **retrieved_attrs)
 
void deparseDeleteSql (StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, List *returningList, List **retrieved_attrs)
 
void deparseDirectDeleteSql (StringInfo buf, PlannerInfo *root, Index rtindex, Relation rel, RelOptInfo *foreignrel, List *remote_conds, List **params_list, List *returningList, List **retrieved_attrs)
 
void deparseAnalyzeSizeSql (StringInfo buf, Relation rel)
 
void deparseAnalyzeSql (StringInfo buf, Relation rel, List **retrieved_attrs)
 
void deparseStringLiteral (StringInfo buf, const char *val)
 

Macro Definition Documentation

◆ ADD_REL_QUALIFIER

#define ADD_REL_QUALIFIER (   buf,
  varno 
)    appendStringInfo((buf), "%s%d.", REL_ALIAS_PREFIX, (varno))

Definition at line 110 of file deparse.c.

Referenced by deparseColumnRef(), and deparseTargetList().

◆ REL_ALIAS_PREFIX

#define REL_ALIAS_PREFIX   "r"

◆ SUBQUERY_COL_ALIAS_PREFIX

#define SUBQUERY_COL_ALIAS_PREFIX   "c"

Definition at line 113 of file deparse.c.

Referenced by deparseRangeTblRef(), and deparseVar().

◆ SUBQUERY_REL_ALIAS_PREFIX

#define SUBQUERY_REL_ALIAS_PREFIX   "s"

Definition at line 112 of file deparse.c.

Referenced by deparseRangeTblRef(), and deparseVar().

Typedef Documentation

◆ deparse_expr_cxt

◆ foreign_glob_cxt

◆ foreign_loc_cxt

Enumeration Type Documentation

◆ FDWCollateState

Enumerator
FDW_COLLATE_NONE 
FDW_COLLATE_SAFE 
FDW_COLLATE_UNSAFE 

Definition at line 78 of file deparse.c.

79 {
80  FDW_COLLATE_NONE, /* expression is of a noncollatable type, or
81  * it has default collation that is not
82  * traceable to a foreign Var */
83  FDW_COLLATE_SAFE, /* collation derives from a foreign Var */
84  FDW_COLLATE_UNSAFE /* collation is non-default and derives from
85  * something other than a foreign Var */
FDWCollateState
Definition: deparse.c:78

Function Documentation

◆ appendAggOrderBy()

static void appendAggOrderBy ( List orderList,
List targetList,
deparse_expr_cxt context 
)
static

Definition at line 2982 of file deparse.c.

References appendStringInfoString(), buf, deparse_expr_cxt::buf, deparseOperatorName(), deparseSortGroupClause(), elog, ERROR, exprType(), GETSTRUCT, TypeCacheEntry::gt_opr, HeapTupleIsValid, lfirst, lookup_type_cache(), TypeCacheEntry::lt_opr, SortGroupClause::nulls_first, ObjectIdGetDatum, OPEROID, ReleaseSysCache(), SearchSysCache1(), SortGroupClause::sortop, SortGroupClause::tleSortGroupRef, TYPECACHE_GT_OPR, and TYPECACHE_LT_OPR.

Referenced by deparseAggref().

2983 {
2984  StringInfo buf = context->buf;
2985  ListCell *lc;
2986  bool first = true;
2987 
2988  foreach(lc, orderList)
2989  {
2990  SortGroupClause *srt = (SortGroupClause *) lfirst(lc);
2991  Node *sortexpr;
2992  Oid sortcoltype;
2993  TypeCacheEntry *typentry;
2994 
2995  if (!first)
2996  appendStringInfoString(buf, ", ");
2997  first = false;
2998 
2999  sortexpr = deparseSortGroupClause(srt->tleSortGroupRef, targetList,
3000  false, context);
3001  sortcoltype = exprType(sortexpr);
3002  /* See whether operator is default < or > for datatype */
3003  typentry = lookup_type_cache(sortcoltype,
3005  if (srt->sortop == typentry->lt_opr)
3006  appendStringInfoString(buf, " ASC");
3007  else if (srt->sortop == typentry->gt_opr)
3008  appendStringInfoString(buf, " DESC");
3009  else
3010  {
3011  HeapTuple opertup;
3012  Form_pg_operator operform;
3013 
3014  appendStringInfoString(buf, " USING ");
3015 
3016  /* Append operator name. */
3017  opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(srt->sortop));
3018  if (!HeapTupleIsValid(opertup))
3019  elog(ERROR, "cache lookup failed for operator %u", srt->sortop);
3020  operform = (Form_pg_operator) GETSTRUCT(opertup);
3021  deparseOperatorName(buf, operform);
3022  ReleaseSysCache(opertup);
3023  }
3024 
3025  if (srt->nulls_first)
3026  appendStringInfoString(buf, " NULLS FIRST");
3027  else
3028  appendStringInfoString(buf, " NULLS LAST");
3029  }
3030 }
static Node * deparseSortGroupClause(Index ref, List *tlist, bool force_colno, deparse_expr_cxt *context)
Definition: deparse.c:3194
#define GETSTRUCT(TUP)
Definition: htup_details.h:668
Index tleSortGroupRef
Definition: parsenodes.h:1207
Definition: nodes.h:517
static void deparseOperatorName(StringInfo buf, Form_pg_operator opform)
Definition: deparse.c:2689
unsigned int Oid
Definition: postgres_ext.h:31
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
#define TYPECACHE_GT_OPR
Definition: typcache.h:129
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
StringInfo buf
Definition: deparse.c:104
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:321
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define lfirst(lc)
Definition: pg_list.h:106
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:82
#define TYPECACHE_LT_OPR
Definition: typcache.h:128
#define elog
Definition: elog.h:219

◆ appendConditions()

static void appendConditions ( List exprs,
deparse_expr_cxt context 
)
static

Definition at line 1283 of file deparse.c.

References appendStringInfoChar(), appendStringInfoString(), buf, deparse_expr_cxt::buf, deparseExpr(), IsA, lfirst, reset_transmission_modes(), and set_transmission_modes().

Referenced by deparseDirectDeleteSql(), deparseDirectUpdateSql(), deparseFromExpr(), deparseFromExprForRel(), and deparseSelectStmtForRel().

1284 {
1285  int nestlevel;
1286  ListCell *lc;
1287  bool is_first = true;
1288  StringInfo buf = context->buf;
1289 
1290  /* Make sure any constants in the exprs are printed portably */
1291  nestlevel = set_transmission_modes();
1292 
1293  foreach(lc, exprs)
1294  {
1295  Expr *expr = (Expr *) lfirst(lc);
1296 
1297  /* Extract clause from RestrictInfo, if required */
1298  if (IsA(expr, RestrictInfo))
1299  expr = ((RestrictInfo *) expr)->clause;
1300 
1301  /* Connect expressions with "AND" and parenthesize each condition. */
1302  if (!is_first)
1303  appendStringInfoString(buf, " AND ");
1304 
1305  appendStringInfoChar(buf, '(');
1306  deparseExpr(expr, context);
1307  appendStringInfoChar(buf, ')');
1308 
1309  is_first = false;
1310  }
1311 
1312  reset_transmission_modes(nestlevel);
1313 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
int set_transmission_modes(void)
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
StringInfo buf
Definition: deparse.c:104
#define lfirst(lc)
Definition: pg_list.h:106
void reset_transmission_modes(int nestlevel)
static void deparseExpr(Expr *expr, deparse_expr_cxt *context)
Definition: deparse.c:2262

◆ appendFunctionName()

static void appendFunctionName ( Oid  funcid,
deparse_expr_cxt context 
)
static

Definition at line 3159 of file deparse.c.

References appendStringInfo(), appendStringInfoString(), buf, deparse_expr_cxt::buf, elog, ERROR, get_namespace_name(), GETSTRUCT, HeapTupleIsValid, NameStr, ObjectIdGetDatum, PROCOID, quote_identifier(), ReleaseSysCache(), and SearchSysCache1().

Referenced by deparseAggref(), and deparseFuncExpr().

3160 {
3161  StringInfo buf = context->buf;
3162  HeapTuple proctup;
3163  Form_pg_proc procform;
3164  const char *proname;
3165 
3166  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
3167  if (!HeapTupleIsValid(proctup))
3168  elog(ERROR, "cache lookup failed for function %u", funcid);
3169  procform = (Form_pg_proc) GETSTRUCT(proctup);
3170 
3171  /* Print schema name only if it's not pg_catalog */
3172  if (procform->pronamespace != PG_CATALOG_NAMESPACE)
3173  {
3174  const char *schemaname;
3175 
3176  schemaname = get_namespace_name(procform->pronamespace);
3177  appendStringInfo(buf, "%s.", quote_identifier(schemaname));
3178  }
3179 
3180  /* Always print the function name */
3181  proname = NameStr(procform->proname);
3183 
3184  ReleaseSysCache(proctup);
3185 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:668
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10488
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3051
static char * buf
Definition: pg_test_fsync.c:67
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
StringInfo buf
Definition: deparse.c:104
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:132
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define NameStr(name)
Definition: c.h:576
#define elog
Definition: elog.h:219

◆ appendGroupByClause()

static void appendGroupByClause ( List tlist,
deparse_expr_cxt context 
)
static

Definition at line 3080 of file deparse.c.

References appendStringInfoString(), Assert, buf, deparse_expr_cxt::buf, deparseSortGroupClause(), Query::groupClause, Query::groupingSets, lfirst, PlannerInfo::parse, deparse_expr_cxt::root, and SortGroupClause::tleSortGroupRef.

Referenced by deparseSelectStmtForRel().

3081 {
3082  StringInfo buf = context->buf;
3083  Query *query = context->root->parse;
3084  ListCell *lc;
3085  bool first = true;
3086 
3087  /* Nothing to be done, if there's no GROUP BY clause in the query. */
3088  if (!query->groupClause)
3089  return;
3090 
3091  appendStringInfoString(buf, " GROUP BY ");
3092 
3093  /*
3094  * Queries with grouping sets are not pushed down, so we don't expect
3095  * grouping sets here.
3096  */
3097  Assert(!query->groupingSets);
3098 
3099  foreach(lc, query->groupClause)
3100  {
3101  SortGroupClause *grp = (SortGroupClause *) lfirst(lc);
3102 
3103  if (!first)
3104  appendStringInfoString(buf, ", ");
3105  first = false;
3106 
3107  deparseSortGroupClause(grp->tleSortGroupRef, tlist, true, context);
3108  }
3109 }
static Node * deparseSortGroupClause(Index ref, List *tlist, bool force_colno, deparse_expr_cxt *context)
Definition: deparse.c:3194
Query * parse
Definition: relation.h:169
Index tleSortGroupRef
Definition: parsenodes.h:1207
List * groupingSets
Definition: parsenodes.h:150
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
StringInfo buf
Definition: deparse.c:104
PlannerInfo * root
Definition: deparse.c:99
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
List * groupClause
Definition: parsenodes.h:148

◆ appendOrderByClause()

static void appendOrderByClause ( List pathkeys,
deparse_expr_cxt context 
)
static

Definition at line 3117 of file deparse.c.

References appendStringInfoString(), Assert, BTLessStrategyNumber, buf, deparse_expr_cxt::buf, deparseExpr(), find_em_expr_for_rel(), lfirst, PathKey::pk_eclass, PathKey::pk_nulls_first, PathKey::pk_strategy, reset_transmission_modes(), deparse_expr_cxt::scanrel, and set_transmission_modes().

Referenced by deparseSelectStmtForRel().

3118 {
3119  ListCell *lcell;
3120  int nestlevel;
3121  char *delim = " ";
3122  RelOptInfo *baserel = context->scanrel;
3123  StringInfo buf = context->buf;
3124 
3125  /* Make sure any constants in the exprs are printed portably */
3126  nestlevel = set_transmission_modes();
3127 
3128  appendStringInfoString(buf, " ORDER BY");
3129  foreach(lcell, pathkeys)
3130  {
3131  PathKey *pathkey = lfirst(lcell);
3132  Expr *em_expr;
3133 
3134  em_expr = find_em_expr_for_rel(pathkey->pk_eclass, baserel);
3135  Assert(em_expr != NULL);
3136 
3137  appendStringInfoString(buf, delim);
3138  deparseExpr(em_expr, context);
3139  if (pathkey->pk_strategy == BTLessStrategyNumber)
3140  appendStringInfoString(buf, " ASC");
3141  else
3142  appendStringInfoString(buf, " DESC");
3143 
3144  if (pathkey->pk_nulls_first)
3145  appendStringInfoString(buf, " NULLS FIRST");
3146  else
3147  appendStringInfoString(buf, " NULLS LAST");
3148 
3149  delim = ", ";
3150  }
3151  reset_transmission_modes(nestlevel);
3152 }
int set_transmission_modes(void)
int pk_strategy
Definition: relation.h:977
bool pk_nulls_first
Definition: relation.h:978
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
StringInfo buf
Definition: deparse.c:104
Expr * find_em_expr_for_rel(EquivalenceClass *ec, RelOptInfo *rel)
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
EquivalenceClass * pk_eclass
Definition: relation.h:975
void reset_transmission_modes(int nestlevel)
static void deparseExpr(Expr *expr, deparse_expr_cxt *context)
Definition: deparse.c:2262
RelOptInfo * scanrel
Definition: deparse.c:101
#define BTLessStrategyNumber
Definition: stratnum.h:29

◆ build_tlist_to_deparse()

List* build_tlist_to_deparse ( RelOptInfo foreignrel)

Definition at line 874 of file deparse.c.

References add_to_flat_tlist(), RestrictInfo::clause, PathTarget::exprs, RelOptInfo::fdw_private, PgFdwRelationInfo::grouped_tlist, IS_UPPER_REL, lfirst_node, PgFdwRelationInfo::local_conds, NIL, pull_var_clause(), PVC_RECURSE_PLACEHOLDERS, and RelOptInfo::reltarget.

Referenced by estimate_path_cost_size(), and postgresGetForeignPlan().

875 {
876  List *tlist = NIL;
877  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
878  ListCell *lc;
879 
880  /*
881  * For an upper relation, we have already built the target list while
882  * checking shippability, so just return that.
883  */
884  if (IS_UPPER_REL(foreignrel))
885  return fpinfo->grouped_tlist;
886 
887  /*
888  * We require columns specified in foreignrel->reltarget->exprs and those
889  * required for evaluating the local conditions.
890  */
891  tlist = add_to_flat_tlist(tlist,
892  pull_var_clause((Node *) foreignrel->reltarget->exprs,
894  foreach(lc, fpinfo->local_conds)
895  {
896  RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
897 
898  tlist = add_to_flat_tlist(tlist,
899  pull_var_clause((Node *) rinfo->clause,
901  }
902 
903  return tlist;
904 }
#define NIL
Definition: pg_list.h:69
#define IS_UPPER_REL(rel)
Definition: relation.h:595
Definition: nodes.h:517
List * pull_var_clause(Node *node, int flags)
Definition: var.c:535
#define PVC_RECURSE_PLACEHOLDERS
Definition: var.h:26
#define lfirst_node(type, lc)
Definition: pg_list.h:109
Expr * clause
Definition: relation.h:1880
List * exprs
Definition: relation.h:1008
void * fdw_private
Definition: relation.h:664
List * add_to_flat_tlist(List *tlist, List *exprs)
Definition: tlist.c:135
Definition: pg_list.h:45
struct PathTarget * reltarget
Definition: relation.h:623

◆ classifyConditions()

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

Definition at line 204 of file deparse.c.

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

Referenced by estimate_path_cost_size(), and postgresGetForeignRelSize().

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

◆ deparse_type_name()

static char * deparse_type_name ( Oid  type_oid,
int32  typemod 
)
static

Definition at line 855 of file deparse.c.

References format_type_extended(), FORMAT_TYPE_FORCE_QUALIFY, FORMAT_TYPE_TYPEMOD_GIVEN, and is_builtin().

Referenced by deparseArrayExpr(), deparseConst(), deparseFuncExpr(), deparseRelabelType(), printRemoteParam(), and printRemotePlaceholder().

856 {
858 
859  if (!is_builtin(type_oid))
860  flags |= FORMAT_TYPE_FORCE_QUALIFY;
861 
862  return format_type_extended(type_oid, typemod, flags);
863 }
bool is_builtin(Oid objectId)
Definition: shippable.c:155
uint16 bits16
Definition: c.h:333
#define FORMAT_TYPE_TYPEMOD_GIVEN
Definition: builtins.h:121
#define FORMAT_TYPE_FORCE_QUALIFY
Definition: builtins.h:123
char * format_type_extended(Oid type_oid, int32 typemod, bits16 flags)
Definition: format_type.c:110

◆ deparseAggref()

static void deparseAggref ( Aggref node,
deparse_expr_cxt context 
)
static

Definition at line 2890 of file deparse.c.

References Aggref::aggdirectargs, Aggref::aggdistinct, Aggref::aggfilter, Aggref::aggfnoid, Aggref::aggkind, Aggref::aggorder, Aggref::aggsplit, AGGSPLIT_SIMPLE, Aggref::aggstar, Aggref::aggvariadic, appendAggOrderBy(), appendFunctionName(), appendStringInfoChar(), appendStringInfoString(), arg, Aggref::args, Assert, buf, deparse_expr_cxt::buf, deparseExpr(), TargetEntry::expr, lfirst, lnext, NIL, and TargetEntry::resjunk.

Referenced by deparseExpr().

2891 {
2892  StringInfo buf = context->buf;
2893  bool use_variadic;
2894 
2895  /* Only basic, non-split aggregation accepted. */
2896  Assert(node->aggsplit == AGGSPLIT_SIMPLE);
2897 
2898  /* Check if need to print VARIADIC (cf. ruleutils.c) */
2899  use_variadic = node->aggvariadic;
2900 
2901  /* Find aggregate name from aggfnoid which is a pg_proc entry */
2902  appendFunctionName(node->aggfnoid, context);
2903  appendStringInfoChar(buf, '(');
2904 
2905  /* Add DISTINCT */
2906  appendStringInfoString(buf, (node->aggdistinct != NIL) ? "DISTINCT " : "");
2907 
2908  if (AGGKIND_IS_ORDERED_SET(node->aggkind))
2909  {
2910  /* Add WITHIN GROUP (ORDER BY ..) */
2911  ListCell *arg;
2912  bool first = true;
2913 
2914  Assert(!node->aggvariadic);
2915  Assert(node->aggorder != NIL);
2916 
2917  foreach(arg, node->aggdirectargs)
2918  {
2919  if (!first)
2920  appendStringInfoString(buf, ", ");
2921  first = false;
2922 
2923  deparseExpr((Expr *) lfirst(arg), context);
2924  }
2925 
2926  appendStringInfoString(buf, ") WITHIN GROUP (ORDER BY ");
2927  appendAggOrderBy(node->aggorder, node->args, context);
2928  }
2929  else
2930  {
2931  /* aggstar can be set only in zero-argument aggregates */
2932  if (node->aggstar)
2933  appendStringInfoChar(buf, '*');
2934  else
2935  {
2936  ListCell *arg;
2937  bool first = true;
2938 
2939  /* Add all the arguments */
2940  foreach(arg, node->args)
2941  {
2942  TargetEntry *tle = (TargetEntry *) lfirst(arg);
2943  Node *n = (Node *) tle->expr;
2944 
2945  if (tle->resjunk)
2946  continue;
2947 
2948  if (!first)
2949  appendStringInfoString(buf, ", ");
2950  first = false;
2951 
2952  /* Add VARIADIC */
2953  if (use_variadic && lnext(arg) == NULL)
2954  appendStringInfoString(buf, "VARIADIC ");
2955 
2956  deparseExpr((Expr *) n, context);
2957  }
2958  }
2959 
2960  /* Add ORDER BY */
2961  if (node->aggorder != NIL)
2962  {
2963  appendStringInfoString(buf, " ORDER BY ");
2964  appendAggOrderBy(node->aggorder, node->args, context);
2965  }
2966  }
2967 
2968  /* Add FILTER (WHERE ..) */
2969  if (node->aggfilter != NULL)
2970  {
2971  appendStringInfoString(buf, ") FILTER (WHERE ");
2972  deparseExpr((Expr *) node->aggfilter, context);
2973  }
2974 
2975  appendStringInfoChar(buf, ')');
2976 }
List * aggdistinct
Definition: primnodes.h:304
#define NIL
Definition: pg_list.h:69
bool aggvariadic
Definition: primnodes.h:307
static void appendFunctionName(Oid funcid, deparse_expr_cxt *context)
Definition: deparse.c:3159
Definition: nodes.h:517
List * args
Definition: primnodes.h:302
bool aggstar
Definition: primnodes.h:306
bool resjunk
Definition: primnodes.h:1383
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
List * aggorder
Definition: primnodes.h:303
List * aggdirectargs
Definition: primnodes.h:301
#define lnext(lc)
Definition: pg_list.h:105
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
static void appendAggOrderBy(List *orderList, List *targetList, deparse_expr_cxt *context)
Definition: deparse.c:2982
StringInfo buf
Definition: deparse.c:104
Oid aggfnoid
Definition: primnodes.h:295
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
Expr * expr
Definition: primnodes.h:1376
AggSplit aggsplit
Definition: primnodes.h:311
Expr * aggfilter
Definition: primnodes.h:305
static void deparseExpr(Expr *expr, deparse_expr_cxt *context)
Definition: deparse.c:2262
void * arg
char aggkind
Definition: primnodes.h:309

◆ deparseAnalyzeSizeSql()

void deparseAnalyzeSizeSql ( StringInfo  buf,
Relation  rel 
)

Definition at line 1972 of file deparse.c.

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

Referenced by postgresAnalyzeForeignTable().

1973 {
1974  StringInfoData relname;
1975 
1976  /* We'll need the remote relation name as a literal. */
1977  initStringInfo(&relname);
1978  deparseRelation(&relname, rel);
1979 
1980  appendStringInfoString(buf, "SELECT pg_catalog.pg_relation_size(");
1981  deparseStringLiteral(buf, relname.data);
1982  appendStringInfo(buf, "::pg_catalog.regclass) / %d", BLCKSZ);
1983 }
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
void deparseStringLiteral(StringInfo buf, const char *val)
Definition: deparse.c:2227
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2187

◆ deparseAnalyzeSql()

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

Definition at line 1992 of file deparse.c.

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

Referenced by postgresAcquireSampleRowsFunc().

1993 {
1994  Oid relid = RelationGetRelid(rel);
1995  TupleDesc tupdesc = RelationGetDescr(rel);
1996  int i;
1997  char *colname;
1998  List *options;
1999  ListCell *lc;
2000  bool first = true;
2001 
2002  *retrieved_attrs = NIL;
2003 
2004  appendStringInfoString(buf, "SELECT ");
2005  for (i = 0; i < tupdesc->natts; i++)
2006  {
2007  /* Ignore dropped columns. */
2008  if (TupleDescAttr(tupdesc, i)->attisdropped)
2009  continue;
2010 
2011  if (!first)
2012  appendStringInfoString(buf, ", ");
2013  first = false;
2014 
2015  /* Use attribute name or column_name option. */
2016  colname = NameStr(TupleDescAttr(tupdesc, i)->attname);
2017  options = GetForeignColumnOptions(relid, i + 1);
2018 
2019  foreach(lc, options)
2020  {
2021  DefElem *def = (DefElem *) lfirst(lc);
2022 
2023  if (strcmp(def->defname, "column_name") == 0)
2024  {
2025  colname = defGetString(def);
2026  break;
2027  }
2028  }
2029 
2031 
2032  *retrieved_attrs = lappend_int(*retrieved_attrs, i + 1);
2033  }
2034 
2035  /* Don't generate bad syntax for zero-column relation. */
2036  if (first)
2037  appendStringInfoString(buf, "NULL");
2038 
2039  /*
2040  * Construct FROM clause
2041  */
2042  appendStringInfoString(buf, " FROM ");
2043  deparseRelation(buf, rel);
2044 }
#define NIL
Definition: pg_list.h:69
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10488
#define RelationGetDescr(relation)
Definition: rel.h:433
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:93
unsigned int Oid
Definition: postgres_ext.h:31
int natts
Definition: tupdesc.h:82
List * GetForeignColumnOptions(Oid relid, AttrNumber attnum)
Definition: foreign.c:254
NameData attname
Definition: pg_attribute.h:40
char * defGetString(DefElem *def)
Definition: define.c:49
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
List * lappend_int(List *list, int datum)
Definition: list.c:146
static char ** options
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2187
#define lfirst(lc)
Definition: pg_list.h:106
int i
#define NameStr(name)
Definition: c.h:576
char * defname
Definition: parsenodes.h:730
Definition: pg_list.h:45
#define RelationGetRelid(relation)
Definition: rel.h:407

◆ deparseArrayExpr()

static void deparseArrayExpr ( ArrayExpr node,
deparse_expr_cxt context 
)
static

Definition at line 2864 of file deparse.c.

References appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), ArrayExpr::array_typeid, buf, deparse_expr_cxt::buf, deparse_type_name(), deparseExpr(), ArrayExpr::elements, lfirst, and NIL.

Referenced by deparseExpr().

2865 {
2866  StringInfo buf = context->buf;
2867  bool first = true;
2868  ListCell *lc;
2869 
2870  appendStringInfoString(buf, "ARRAY[");
2871  foreach(lc, node->elements)
2872  {
2873  if (!first)
2874  appendStringInfoString(buf, ", ");
2875  deparseExpr(lfirst(lc), context);
2876  first = false;
2877  }
2878  appendStringInfoChar(buf, ']');
2879 
2880  /* If the array is empty, we need an explicit cast to the array type. */
2881  if (node->elements == NIL)
2882  appendStringInfo(buf, "::%s",
2883  deparse_type_name(node->array_typeid, -1));
2884 }
#define NIL
Definition: pg_list.h:69
Oid array_typeid
Definition: primnodes.h:957
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
List * elements
Definition: primnodes.h:960
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
StringInfo buf
Definition: deparse.c:104
static char * deparse_type_name(Oid type_oid, int32 typemod)
Definition: deparse.c:855
#define lfirst(lc)
Definition: pg_list.h:106
static void deparseExpr(Expr *expr, deparse_expr_cxt *context)
Definition: deparse.c:2262

◆ deparseArrayRef()

static void deparseArrayRef ( ArrayRef node,
deparse_expr_cxt context 
)
static

Definition at line 2529 of file deparse.c.

References appendStringInfoChar(), buf, deparse_expr_cxt::buf, deparseExpr(), IsA, lfirst, list_head(), lnext, ArrayRef::refexpr, ArrayRef::reflowerindexpr, and ArrayRef::refupperindexpr.

Referenced by deparseExpr().

2530 {
2531  StringInfo buf = context->buf;
2532  ListCell *lowlist_item;
2533  ListCell *uplist_item;
2534 
2535  /* Always parenthesize the expression. */
2536  appendStringInfoChar(buf, '(');
2537 
2538  /*
2539  * Deparse referenced array expression first. If that expression includes
2540  * a cast, we have to parenthesize to prevent the array subscript from
2541  * being taken as typename decoration. We can avoid that in the typical
2542  * case of subscripting a Var, but otherwise do it.
2543  */
2544  if (IsA(node->refexpr, Var))
2545  deparseExpr(node->refexpr, context);
2546  else
2547  {
2548  appendStringInfoChar(buf, '(');
2549  deparseExpr(node->refexpr, context);
2550  appendStringInfoChar(buf, ')');
2551  }
2552 
2553  /* Deparse subscript expressions. */
2554  lowlist_item = list_head(node->reflowerindexpr); /* could be NULL */
2555  foreach(uplist_item, node->refupperindexpr)
2556  {
2557  appendStringInfoChar(buf, '[');
2558  if (lowlist_item)
2559  {
2560  deparseExpr(lfirst(lowlist_item), context);
2561  appendStringInfoChar(buf, ':');
2562  lowlist_item = lnext(lowlist_item);
2563  }
2564  deparseExpr(lfirst(uplist_item), context);
2565  appendStringInfoChar(buf, ']');
2566  }
2567 
2568  appendStringInfoChar(buf, ')');
2569 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
Definition: primnodes.h:164
static char * buf
Definition: pg_test_fsync.c:67
List * refupperindexpr
Definition: primnodes.h:404
List * reflowerindexpr
Definition: primnodes.h:406
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define lnext(lc)
Definition: pg_list.h:105
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
StringInfo buf
Definition: deparse.c:104
#define lfirst(lc)
Definition: pg_list.h:106
static void deparseExpr(Expr *expr, deparse_expr_cxt *context)
Definition: deparse.c:2262
Expr * refexpr
Definition: primnodes.h:409

◆ deparseBoolExpr()

static void deparseBoolExpr ( BoolExpr node,
deparse_expr_cxt context 
)
static

Definition at line 2793 of file deparse.c.

References AND_EXPR, appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), BoolExpr::args, BoolExpr::boolop, buf, deparse_expr_cxt::buf, deparseExpr(), lfirst, linitial, NOT_EXPR, and OR_EXPR.

Referenced by deparseExpr().

2794 {
2795  StringInfo buf = context->buf;
2796  const char *op = NULL; /* keep compiler quiet */
2797  bool first;
2798  ListCell *lc;
2799 
2800  switch (node->boolop)
2801  {
2802  case AND_EXPR:
2803  op = "AND";
2804  break;
2805  case OR_EXPR:
2806  op = "OR";
2807  break;
2808  case NOT_EXPR:
2809  appendStringInfoString(buf, "(NOT ");
2810  deparseExpr(linitial(node->args), context);
2811  appendStringInfoChar(buf, ')');
2812  return;
2813  }
2814 
2815  appendStringInfoChar(buf, '(');
2816  first = true;
2817  foreach(lc, node->args)
2818  {
2819  if (!first)
2820  appendStringInfo(buf, " %s ", op);
2821  deparseExpr((Expr *) lfirst(lc), context);
2822  first = false;
2823  }
2824  appendStringInfoChar(buf, ')');
2825 }
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define linitial(l)
Definition: pg_list.h:111
BoolExprType boolop
Definition: primnodes.h:563
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
StringInfo buf
Definition: deparse.c:104
#define lfirst(lc)
Definition: pg_list.h:106
List * args
Definition: primnodes.h:564
static void deparseExpr(Expr *expr, deparse_expr_cxt *context)
Definition: deparse.c:2262

◆ deparseColumnRef()

static void deparseColumnRef ( StringInfo  buf,
int  varno,
int  varattno,
RangeTblEntry rte,
bool  qualify_col 
)
static

Definition at line 2053 of file deparse.c.

References ADD_REL_QUALIFIER, appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), Assert, bms_add_member(), bms_free(), defGetString(), DefElem::defname, deparseTargetList(), FirstLowInvalidHeapAttributeNumber, get_attname(), GetForeignColumnOptions(), heap_close, heap_open(), IS_SPECIAL_VARNO, lfirst, NoLock, ObjectIdAttributeNumber, options, quote_identifier(), RangeTblEntry::relid, SelfItemPointerAttributeNumber, and TableOidAttributeNumber.

Referenced by deparseDirectUpdateSql(), deparseInsertSql(), deparseTargetList(), deparseUpdateSql(), and deparseVar().

2055 {
2056  /* We support fetching the remote side's CTID and OID. */
2057  if (varattno == SelfItemPointerAttributeNumber)
2058  {
2059  if (qualify_col)
2060  ADD_REL_QUALIFIER(buf, varno);
2061  appendStringInfoString(buf, "ctid");
2062  }
2063  else if (varattno == ObjectIdAttributeNumber)
2064  {
2065  if (qualify_col)
2066  ADD_REL_QUALIFIER(buf, varno);
2067  appendStringInfoString(buf, "oid");
2068  }
2069  else if (varattno < 0)
2070  {
2071  /*
2072  * All other system attributes are fetched as 0, except for table OID,
2073  * which is fetched as the local table OID. However, we must be
2074  * careful; the table could be beneath an outer join, in which case it
2075  * must go to NULL whenever the rest of the row does.
2076  */
2077  Oid fetchval = 0;
2078 
2079  if (varattno == TableOidAttributeNumber)
2080  fetchval = rte->relid;
2081 
2082  if (qualify_col)
2083  {
2084  appendStringInfoString(buf, "CASE WHEN (");
2085  ADD_REL_QUALIFIER(buf, varno);
2086  appendStringInfo(buf, "*)::text IS NOT NULL THEN %u END", fetchval);
2087  }
2088  else
2089  appendStringInfo(buf, "%u", fetchval);
2090  }
2091  else if (varattno == 0)
2092  {
2093  /* Whole row reference */
2094  Relation rel;
2095  Bitmapset *attrs_used;
2096 
2097  /* Required only to be passed down to deparseTargetList(). */
2098  List *retrieved_attrs;
2099 
2100  /*
2101  * The lock on the relation will be held by upper callers, so it's
2102  * fine to open it with no lock here.
2103  */
2104  rel = heap_open(rte->relid, NoLock);
2105 
2106  /*
2107  * The local name of the foreign table can not be recognized by the
2108  * foreign server and the table it references on foreign server might
2109  * have different column ordering or different columns than those
2110  * declared locally. Hence we have to deparse whole-row reference as
2111  * ROW(columns referenced locally). Construct this by deparsing a
2112  * "whole row" attribute.
2113  */
2114  attrs_used = bms_add_member(NULL,
2116 
2117  /*
2118  * In case the whole-row reference is under an outer join then it has
2119  * to go NULL whenever the rest of the row goes NULL. Deparsing a join
2120  * query would always involve multiple relations, thus qualify_col
2121  * would be true.
2122  */
2123  if (qualify_col)
2124  {
2125  appendStringInfoString(buf, "CASE WHEN (");
2126  ADD_REL_QUALIFIER(buf, varno);
2127  appendStringInfoString(buf, "*)::text IS NOT NULL THEN ");
2128  }
2129 
2130  appendStringInfoString(buf, "ROW(");
2131  deparseTargetList(buf, rte, varno, rel, false, attrs_used, qualify_col,
2132  &retrieved_attrs);
2133  appendStringInfoChar(buf, ')');
2134 
2135  /* Complete the CASE WHEN statement started above. */
2136  if (qualify_col)
2137  appendStringInfoString(buf, " END");
2138 
2139  heap_close(rel, NoLock);
2140  bms_free(attrs_used);
2141  }
2142  else
2143  {
2144  char *colname = NULL;
2145  List *options;
2146  ListCell *lc;
2147 
2148  /* varno must not be any of OUTER_VAR, INNER_VAR and INDEX_VAR. */
2149  Assert(!IS_SPECIAL_VARNO(varno));
2150 
2151  /*
2152  * If it's a column of a foreign table, and it has the column_name FDW
2153  * option, use that value.
2154  */
2155  options = GetForeignColumnOptions(rte->relid, varattno);
2156  foreach(lc, options)
2157  {
2158  DefElem *def = (DefElem *) lfirst(lc);
2159 
2160  if (strcmp(def->defname, "column_name") == 0)
2161  {
2162  colname = defGetString(def);
2163  break;
2164  }
2165  }
2166 
2167  /*
2168  * If it's a column of a regular table or it doesn't have column_name
2169  * FDW option, use attribute name.
2170  */
2171  if (colname == NULL)
2172  colname = get_attname(rte->relid, varattno, false);
2173 
2174  if (qualify_col)
2175  ADD_REL_QUALIFIER(buf, varno);
2176 
2178  }
2179 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10488
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
static void deparseTargetList(StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, bool is_returning, Bitmapset *attrs_used, bool qualify_col, List **retrieved_attrs)
Definition: deparse.c:1101
List * GetForeignColumnOptions(Oid relid, AttrNumber attnum)
Definition: foreign.c:254
#define IS_SPECIAL_VARNO(varno)
Definition: primnodes.h:158
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define ADD_REL_QUALIFIER(buf, varno)
Definition: deparse.c:110
char * defGetString(DefElem *def)
Definition: define.c:49
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
#define NoLock
Definition: lockdefs.h:34
#define TableOidAttributeNumber
Definition: sysattr.h:27
static char ** options
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
void bms_free(Bitmapset *a)
Definition: bitmapset.c:267
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:764
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:775
char * defname
Definition: parsenodes.h:730
#define SelfItemPointerAttributeNumber
Definition: sysattr.h:21
Definition: pg_list.h:45

◆ deparseConst()

static void deparseConst ( Const node,
deparse_expr_cxt context,
int  showtype 
)
static

Definition at line 2390 of file deparse.c.

References appendStringInfo(), appendStringInfoString(), buf, deparse_expr_cxt::buf, Const::constisnull, Const::consttype, Const::consttypmod, Const::constvalue, deparse_type_name(), deparseStringLiteral(), getTypeOutputInfo(), OidOutputFunctionCall(), and pfree().

Referenced by deparseExpr(), and deparseSortGroupClause().

2391 {
2392  StringInfo buf = context->buf;
2393  Oid typoutput;
2394  bool typIsVarlena;
2395  char *extval;
2396  bool isfloat = false;
2397  bool needlabel;
2398 
2399  if (node->constisnull)
2400  {
2401  appendStringInfoString(buf, "NULL");
2402  if (showtype >= 0)
2403  appendStringInfo(buf, "::%s",
2405  node->consttypmod));
2406  return;
2407  }
2408 
2410  &typoutput, &typIsVarlena);
2411  extval = OidOutputFunctionCall(typoutput, node->constvalue);
2412 
2413  switch (node->consttype)
2414  {
2415  case INT2OID:
2416  case INT4OID:
2417  case INT8OID:
2418  case OIDOID:
2419  case FLOAT4OID:
2420  case FLOAT8OID:
2421  case NUMERICOID:
2422  {
2423  /*
2424  * No need to quote unless it's a special value such as 'NaN'.
2425  * See comments in get_const_expr().
2426  */
2427  if (strspn(extval, "0123456789+-eE.") == strlen(extval))
2428  {
2429  if (extval[0] == '+' || extval[0] == '-')
2430  appendStringInfo(buf, "(%s)", extval);
2431  else
2432  appendStringInfoString(buf, extval);
2433  if (strcspn(extval, "eE.") != strlen(extval))
2434  isfloat = true; /* it looks like a float */
2435  }
2436  else
2437  appendStringInfo(buf, "'%s'", extval);
2438  }
2439  break;
2440  case BITOID:
2441  case VARBITOID:
2442  appendStringInfo(buf, "B'%s'", extval);
2443  break;
2444  case BOOLOID:
2445  if (strcmp(extval, "t") == 0)
2446  appendStringInfoString(buf, "true");
2447  else
2448  appendStringInfoString(buf, "false");
2449  break;
2450  default:
2451  deparseStringLiteral(buf, extval);
2452  break;
2453  }
2454 
2455  pfree(extval);
2456 
2457  if (showtype < 0)
2458  return;
2459 
2460  /*
2461  * For showtype == 0, append ::typename unless the constant will be
2462  * implicitly typed as the right type when it is read in.
2463  *
2464  * XXX this code has to be kept in sync with the behavior of the parser,
2465  * especially make_const.
2466  */
2467  switch (node->consttype)
2468  {
2469  case BOOLOID:
2470  case INT4OID:
2471  case UNKNOWNOID:
2472  needlabel = false;
2473  break;
2474  case NUMERICOID:
2475  needlabel = !isfloat || (node->consttypmod >= 0);
2476  break;
2477  default:
2478  needlabel = true;
2479  break;
2480  }
2481  if (needlabel || showtype > 0)
2482  appendStringInfo(buf, "::%s",
2484  node->consttypmod));
2485 }
Datum constvalue
Definition: primnodes.h:197
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2650
unsigned int Oid
Definition: postgres_ext.h:31
Oid consttype
Definition: primnodes.h:193
void pfree(void *pointer)
Definition: mcxt.c:1031
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
StringInfo buf
Definition: deparse.c:104
void deparseStringLiteral(StringInfo buf, const char *val)
Definition: deparse.c:2227
static char * deparse_type_name(Oid type_oid, int32 typemod)
Definition: deparse.c:855
int32 consttypmod
Definition: primnodes.h:194
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1833
bool constisnull
Definition: primnodes.h:198

◆ deparseDeleteSql()

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

Definition at line 1851 of file deparse.c.

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

Referenced by postgresPlanForeignModify().

1855 {
1856  appendStringInfoString(buf, "DELETE FROM ");
1857  deparseRelation(buf, rel);
1858  appendStringInfoString(buf, " WHERE ctid = $1");
1859 
1860  deparseReturningList(buf, rte, rtindex, rel,
1861  rel->trigdesc && rel->trigdesc->trig_delete_after_row,
1862  returningList, retrieved_attrs);
1863 }
static void deparseReturningList(StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, bool trig_after_row, List *returningList, List **retrieved_attrs)
Definition: deparse.c:1931
TriggerDesc * trigdesc
Definition: rel.h:90
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
bool trig_delete_after_row
Definition: reltrigger.h:66
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2187

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

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

Referenced by postgresPlanDirectModify().

1887 {
1888  deparse_expr_cxt context;
1889 
1890  /* Set up context struct for recursion */
1891  context.root = root;
1892  context.foreignrel = foreignrel;
1893  context.scanrel = foreignrel;
1894  context.buf = buf;
1895  context.params_list = params_list;
1896 
1897  appendStringInfoString(buf, "DELETE FROM ");
1898  deparseRelation(buf, rel);
1899  if (foreignrel->reloptkind == RELOPT_JOINREL)
1900  appendStringInfo(buf, " %s%d", REL_ALIAS_PREFIX, rtindex);
1901 
1902  if (foreignrel->reloptkind == RELOPT_JOINREL)
1903  {
1904  List *ignore_conds = NIL;
1905 
1906  appendStringInfo(buf, " USING ");
1907  deparseFromExprForRel(buf, root, foreignrel, true, rtindex,
1908  &ignore_conds, params_list);
1909  remote_conds = list_concat(remote_conds, ignore_conds);
1910  }
1911 
1912  if (remote_conds)
1913  {
1914  appendStringInfoString(buf, " WHERE ");
1915  appendConditions(remote_conds, &context);
1916  }
1917 
1918  if (foreignrel->reloptkind == RELOPT_JOINREL)
1919  deparseExplicitTargetList(returningList, true, retrieved_attrs,
1920  &context);
1921  else
1922  deparseReturningList(buf, planner_rt_fetch(rtindex, root),
1923  rtindex, rel, false,
1924  returningList, retrieved_attrs);
1925 }
#define NIL
Definition: pg_list.h:69
static void deparseReturningList(StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, bool trig_after_row, List *returningList, List **retrieved_attrs)
Definition: deparse.c:1931
RelOptKind reloptkind
Definition: relation.h:609
List ** params_list
Definition: deparse.c:105
List * list_concat(List *list1, List *list2)
Definition: list.c:321
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define planner_rt_fetch(rti, root)
Definition: relation.h:344
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
#define REL_ALIAS_PREFIX
Definition: deparse.c:108
static void deparseExplicitTargetList(List *tlist, bool is_returning, List **retrieved_attrs, deparse_expr_cxt *context)
Definition: deparse.c:1354
static void appendConditions(List *exprs, deparse_expr_cxt *context)
Definition: deparse.c:1283
StringInfo buf
Definition: deparse.c:104
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2187
PlannerInfo * root
Definition: deparse.c:99
static void deparseFromExprForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel, bool use_alias, Index ignore_rel, List **ignore_conds, List **params_list)
Definition: deparse.c:1431
RelOptInfo * scanrel
Definition: deparse.c:101
Definition: pg_list.h:45
RelOptInfo * foreignrel
Definition: deparse.c:100

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

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

Referenced by postgresPlanDirectModify().

1775 {
1776  deparse_expr_cxt context;
1777  int nestlevel;
1778  bool first;
1779  ListCell *lc;
1780  RangeTblEntry *rte = planner_rt_fetch(rtindex, root);
1781 
1782  /* Set up context struct for recursion */
1783  context.root = root;
1784  context.foreignrel = foreignrel;
1785  context.scanrel = foreignrel;
1786  context.buf = buf;
1787  context.params_list = params_list;
1788 
1789  appendStringInfoString(buf, "UPDATE ");
1790  deparseRelation(buf, rel);
1791  if (foreignrel->reloptkind == RELOPT_JOINREL)
1792  appendStringInfo(buf, " %s%d", REL_ALIAS_PREFIX, rtindex);
1793  appendStringInfoString(buf, " SET ");
1794 
1795  /* Make sure any constants in the exprs are printed portably */
1796  nestlevel = set_transmission_modes();
1797 
1798  first = true;
1799  foreach(lc, targetAttrs)
1800  {
1801  int attnum = lfirst_int(lc);
1802  TargetEntry *tle = get_tle_by_resno(targetlist, attnum);
1803 
1804  if (!tle)
1805  elog(ERROR, "attribute number %d not found in UPDATE targetlist",
1806  attnum);
1807 
1808  if (!first)
1809  appendStringInfoString(buf, ", ");
1810  first = false;
1811 
1812  deparseColumnRef(buf, rtindex, attnum, rte, false);
1813  appendStringInfoString(buf, " = ");
1814  deparseExpr((Expr *) tle->expr, &context);
1815  }
1816 
1817  reset_transmission_modes(nestlevel);
1818 
1819  if (foreignrel->reloptkind == RELOPT_JOINREL)
1820  {
1821  List *ignore_conds = NIL;
1822 
1823  appendStringInfo(buf, " FROM ");
1824  deparseFromExprForRel(buf, root, foreignrel, true, rtindex,
1825  &ignore_conds, params_list);
1826  remote_conds = list_concat(remote_conds, ignore_conds);
1827  }
1828 
1829  if (remote_conds)
1830  {
1831  appendStringInfoString(buf, " WHERE ");
1832  appendConditions(remote_conds, &context);
1833  }
1834 
1835  if (foreignrel->reloptkind == RELOPT_JOINREL)
1836  deparseExplicitTargetList(returningList, true, retrieved_attrs,
1837  &context);
1838  else
1839  deparseReturningList(buf, rte, rtindex, rel, false,
1840  returningList, retrieved_attrs);
1841 }
#define NIL
Definition: pg_list.h:69
static void deparseReturningList(StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, bool trig_after_row, List *returningList, List **retrieved_attrs)
Definition: deparse.c:1931
RelOptKind reloptkind
Definition: relation.h:609
List ** params_list
Definition: deparse.c:105
int set_transmission_modes(void)
List * list_concat(List *list1, List *list2)
Definition: list.c:321
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define planner_rt_fetch(rti, root)
Definition: relation.h:344
#define ERROR
Definition: elog.h:43
#define lfirst_int(lc)
Definition: pg_list.h:107
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
#define REL_ALIAS_PREFIX
Definition: deparse.c:108
static void deparseExplicitTargetList(List *tlist, bool is_returning, List **retrieved_attrs, deparse_expr_cxt *context)
Definition: deparse.c:1354
static void appendConditions(List *exprs, deparse_expr_cxt *context)
Definition: deparse.c:1283
StringInfo buf
Definition: deparse.c:104
int16 attnum
Definition: pg_attribute.h:79
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2187
PlannerInfo * root
Definition: deparse.c:99
Expr * expr
Definition: primnodes.h:1376
void reset_transmission_modes(int nestlevel)
static void deparseExpr(Expr *expr, deparse_expr_cxt *context)
Definition: deparse.c:2262
static void deparseFromExprForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel, bool use_alias, Index ignore_rel, List **ignore_conds, List **params_list)
Definition: deparse.c:1431
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)
#define elog
Definition: elog.h:219
RelOptInfo * scanrel
Definition: deparse.c:101
Definition: pg_list.h:45
RelOptInfo * foreignrel
Definition: deparse.c:100
static void deparseColumnRef(StringInfo buf, int varno, int varattno, RangeTblEntry *rte, bool qualify_col)
Definition: deparse.c:2053

◆ deparseDistinctExpr()

static void deparseDistinctExpr ( DistinctExpr node,
deparse_expr_cxt context 
)
static

Definition at line 2717 of file deparse.c.

References appendStringInfoChar(), appendStringInfoString(), OpExpr::args, Assert, buf, deparse_expr_cxt::buf, deparseExpr(), linitial, list_length(), and lsecond.

Referenced by deparseExpr().

2718 {
2719  StringInfo buf = context->buf;
2720 
2721  Assert(list_length(node->args) == 2);
2722 
2723  appendStringInfoChar(buf, '(');
2724  deparseExpr(linitial(node->args), context);
2725  appendStringInfoString(buf, " IS DISTINCT FROM ");
2726  deparseExpr(lsecond(node->args), context);
2727  appendStringInfoChar(buf, ')');
2728 }
#define lsecond(l)
Definition: pg_list.h:116
#define linitial(l)
Definition: pg_list.h:111
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
StringInfo buf
Definition: deparse.c:104
#define Assert(condition)
Definition: c.h:699
static int list_length(const List *l)
Definition: pg_list.h:89
static void deparseExpr(Expr *expr, deparse_expr_cxt *context)
Definition: deparse.c:2262
List * args
Definition: primnodes.h:503

◆ deparseExplicitTargetList()

static void deparseExplicitTargetList ( List tlist,
bool  is_returning,
List **  retrieved_attrs,
deparse_expr_cxt context 
)
static

Definition at line 1354 of file deparse.c.

References appendStringInfoString(), buf, deparse_expr_cxt::buf, deparseExpr(), TargetEntry::expr, i, lappend_int(), lfirst_node, and NIL.

Referenced by deparseDirectDeleteSql(), deparseDirectUpdateSql(), and deparseSelectSql().

1358 {
1359  ListCell *lc;
1360  StringInfo buf = context->buf;
1361  int i = 0;
1362 
1363  *retrieved_attrs = NIL;
1364 
1365  foreach(lc, tlist)
1366  {
1367  TargetEntry *tle = lfirst_node(TargetEntry, lc);
1368 
1369  if (i > 0)
1370  appendStringInfoString(buf, ", ");
1371  else if (is_returning)
1372  appendStringInfoString(buf, " RETURNING ");
1373 
1374  deparseExpr((Expr *) tle->expr, context);
1375 
1376  *retrieved_attrs = lappend_int(*retrieved_attrs, i + 1);
1377  i++;
1378  }
1379 
1380  if (i == 0 && !is_returning)
1381  appendStringInfoString(buf, "NULL");
1382 }
#define NIL
Definition: pg_list.h:69
#define lfirst_node(type, lc)
Definition: pg_list.h:109
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
List * lappend_int(List *list, int datum)
Definition: list.c:146
StringInfo buf
Definition: deparse.c:104
Expr * expr
Definition: primnodes.h:1376
static void deparseExpr(Expr *expr, deparse_expr_cxt *context)
Definition: deparse.c:2262
int i

◆ deparseExpr()

static void deparseExpr ( Expr expr,
deparse_expr_cxt context 
)
static

Definition at line 2262 of file deparse.c.

References deparseAggref(), deparseArrayExpr(), deparseArrayRef(), deparseBoolExpr(), deparseConst(), deparseDistinctExpr(), deparseFuncExpr(), deparseNullTest(), deparseOpExpr(), deparseParam(), deparseRelabelType(), deparseScalarArrayOpExpr(), deparseVar(), elog, ERROR, nodeTag, T_Aggref, T_ArrayExpr, T_ArrayRef, T_BoolExpr, T_Const, T_DistinctExpr, T_FuncExpr, T_NullTest, T_OpExpr, T_Param, T_RelabelType, T_ScalarArrayOpExpr, and T_Var.

Referenced by appendConditions(), appendOrderByClause(), deparseAggref(), deparseArrayExpr(), deparseArrayRef(), deparseBoolExpr(), deparseDirectUpdateSql(), deparseDistinctExpr(), deparseExplicitTargetList(), deparseFuncExpr(), deparseNullTest(), deparseOpExpr(), deparseRelabelType(), deparseScalarArrayOpExpr(), deparseSortGroupClause(), and deparseSubqueryTargetList().

2263 {
2264  if (node == NULL)
2265  return;
2266 
2267  switch (nodeTag(node))
2268  {
2269  case T_Var:
2270  deparseVar((Var *) node, context);
2271  break;
2272  case T_Const:
2273  deparseConst((Const *) node, context, 0);
2274  break;
2275  case T_Param:
2276  deparseParam((Param *) node, context);
2277  break;
2278  case T_ArrayRef:
2279  deparseArrayRef((ArrayRef *) node, context);
2280  break;
2281  case T_FuncExpr:
2282  deparseFuncExpr((FuncExpr *) node, context);
2283  break;
2284  case T_OpExpr:
2285  deparseOpExpr((OpExpr *) node, context);
2286  break;
2287  case T_DistinctExpr:
2288  deparseDistinctExpr((DistinctExpr *) node, context);
2289  break;
2290  case T_ScalarArrayOpExpr:
2291  deparseScalarArrayOpExpr((ScalarArrayOpExpr *) node, context);
2292  break;
2293  case T_RelabelType:
2294  deparseRelabelType((RelabelType *) node, context);
2295  break;
2296  case T_BoolExpr:
2297  deparseBoolExpr((BoolExpr *) node, context);
2298  break;
2299  case T_NullTest:
2300  deparseNullTest((NullTest *) node, context);
2301  break;
2302  case T_ArrayExpr:
2303  deparseArrayExpr((ArrayExpr *) node, context);
2304  break;
2305  case T_Aggref:
2306  deparseAggref((Aggref *) node, context);
2307  break;
2308  default:
2309  elog(ERROR, "unsupported expression type for deparse: %d",
2310  (int) nodeTag(node));
2311  break;
2312  }
2313 }
static void deparseAggref(Aggref *node, deparse_expr_cxt *context)
Definition: deparse.c:2890
static void deparseBoolExpr(BoolExpr *node, deparse_expr_cxt *context)
Definition: deparse.c:2793
static void deparseNullTest(NullTest *node, deparse_expr_cxt *context)
Definition: deparse.c:2831
static void deparseDistinctExpr(DistinctExpr *node, deparse_expr_cxt *context)
Definition: deparse.c:2717
static void deparseArrayRef(ArrayRef *node, deparse_expr_cxt *context)
Definition: deparse.c:2529
Definition: primnodes.h:164
#define ERROR
Definition: elog.h:43
static void deparseParam(Param *node, deparse_expr_cxt *context)
Definition: deparse.c:2496
static void deparseScalarArrayOpExpr(ScalarArrayOpExpr *node, deparse_expr_cxt *context)
Definition: deparse.c:2735
static void deparseOpExpr(OpExpr *node, deparse_expr_cxt *context)
Definition: deparse.c:2638
static void deparseArrayExpr(ArrayExpr *node, deparse_expr_cxt *context)
Definition: deparse.c:2864
static void deparseRelabelType(RelabelType *node, deparse_expr_cxt *context)
Definition: deparse.c:2780
static void deparseVar(Var *node, deparse_expr_cxt *context)
Definition: deparse.c:2324
Definition: nodes.h:148
Definition: nodes.h:147
static void deparseConst(Const *node, deparse_expr_cxt *context, int showtype)
Definition: deparse.c:2390
#define nodeTag(nodeptr)
Definition: nodes.h:522
#define elog
Definition: elog.h:219
static void deparseFuncExpr(FuncExpr *node, deparse_expr_cxt *context)
Definition: deparse.c:2575
Definition: nodes.h:149

◆ deparseFromExpr()

static void deparseFromExpr ( List quals,
deparse_expr_cxt context 
)
static

Definition at line 1067 of file deparse.c.

References appendConditions(), appendStringInfoString(), Assert, bms_num_members(), buf, deparse_expr_cxt::buf, deparseFromExprForRel(), deparse_expr_cxt::foreignrel, IS_JOIN_REL, IS_SIMPLE_REL, IS_UPPER_REL, NIL, deparse_expr_cxt::params_list, RelOptInfo::relids, deparse_expr_cxt::root, and deparse_expr_cxt::scanrel.

Referenced by deparseSelectStmtForRel().

1068 {
1069  StringInfo buf = context->buf;
1070  RelOptInfo *scanrel = context->scanrel;
1071 
1072  /* For upper relations, scanrel must be either a joinrel or a baserel */
1073  Assert(!IS_UPPER_REL(context->foreignrel) ||
1074  IS_JOIN_REL(scanrel) || IS_SIMPLE_REL(scanrel));
1075 
1076  /* Construct FROM clause */
1077  appendStringInfoString(buf, " FROM ");
1078  deparseFromExprForRel(buf, context->root, scanrel,
1079  (bms_num_members(scanrel->relids) > 1),
1080  (Index) 0, NULL, context->params_list);
1081 
1082  /* Construct WHERE clause */
1083  if (quals != NIL)
1084  {
1085  appendStringInfoString(buf, " WHERE ");
1086  appendConditions(quals, context);
1087  }
1088 }
#define NIL
Definition: pg_list.h:69
List ** params_list
Definition: deparse.c:105
#define IS_UPPER_REL(rel)
Definition: relation.h:595
#define IS_JOIN_REL(rel)
Definition: relation.h:590
#define IS_SIMPLE_REL(rel)
Definition: relation.h:585
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:671
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
Relids relids
Definition: relation.h:612
static void appendConditions(List *exprs, deparse_expr_cxt *context)
Definition: deparse.c:1283
StringInfo buf
Definition: deparse.c:104
unsigned int Index
Definition: c.h:442
PlannerInfo * root
Definition: deparse.c:99
#define Assert(condition)
Definition: c.h:699
static void deparseFromExprForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel, bool use_alias, Index ignore_rel, List **ignore_conds, List **params_list)
Definition: deparse.c:1431
RelOptInfo * scanrel
Definition: deparse.c:101
RelOptInfo * foreignrel
Definition: deparse.c:100

◆ deparseFromExprForRel()

static void deparseFromExprForRel ( StringInfo  buf,
PlannerInfo root,
RelOptInfo foreignrel,
bool  use_alias,
Index  ignore_rel,
List **  ignore_conds,
List **  params_list 
)
static

Definition at line 1431 of file deparse.c.

References appendConditions(), appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), Assert, bms_is_member(), buf, deparse_expr_cxt::buf, StringInfoData::data, deparseRangeTblRef(), deparseRelation(), RelOptInfo::fdw_private, foreign_glob_cxt::foreignrel, deparse_expr_cxt::foreignrel, get_jointype_name(), heap_close, heap_open(), initStringInfo(), PgFdwRelationInfo::innerrel, IS_JOIN_REL, JOIN_INNER, PgFdwRelationInfo::joinclauses, PgFdwRelationInfo::jointype, list_concat(), list_copy(), PgFdwRelationInfo::make_innerrel_subquery, PgFdwRelationInfo::make_outerrel_subquery, NIL, NoLock, PgFdwRelationInfo::outerrel, deparse_expr_cxt::params_list, planner_rt_fetch, REL_ALIAS_PREFIX, RelOptInfo::relid, RangeTblEntry::relid, RelOptInfo::relids, foreign_glob_cxt::root, deparse_expr_cxt::root, and deparse_expr_cxt::scanrel.

Referenced by deparseDirectDeleteSql(), deparseDirectUpdateSql(), deparseFromExpr(), and deparseRangeTblRef().

1434 {
1435  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
1436 
1437  if (IS_JOIN_REL(foreignrel))
1438  {
1439  StringInfoData join_sql_o;
1440  StringInfoData join_sql_i;
1441  RelOptInfo *outerrel = fpinfo->outerrel;
1442  RelOptInfo *innerrel = fpinfo->innerrel;
1443  bool outerrel_is_target = false;
1444  bool innerrel_is_target = false;
1445 
1446  if (ignore_rel > 0 && bms_is_member(ignore_rel, foreignrel->relids))
1447  {
1448  /*
1449  * If this is an inner join, add joinclauses to *ignore_conds and
1450  * set it to empty so that those can be deparsed into the WHERE
1451  * clause. Note that since the target relation can never be
1452  * within the nullable side of an outer join, those could safely
1453  * be pulled up into the WHERE clause (see foreign_join_ok()).
1454  * Note also that since the target relation is only inner-joined
1455  * to any other relation in the query, all conditions in the join
1456  * tree mentioning the target relation could be deparsed into the
1457  * WHERE clause by doing this recursively.
1458  */
1459  if (fpinfo->jointype == JOIN_INNER)
1460  {
1461  *ignore_conds = list_concat(*ignore_conds,
1462  list_copy(fpinfo->joinclauses));
1463  fpinfo->joinclauses = NIL;
1464  }
1465 
1466  /*
1467  * Check if either of the input relations is the target relation.
1468  */
1469  if (outerrel->relid == ignore_rel)
1470  outerrel_is_target = true;
1471  else if (innerrel->relid == ignore_rel)
1472  innerrel_is_target = true;
1473  }
1474 
1475  /* Deparse outer relation if not the target relation. */
1476  if (!outerrel_is_target)
1477  {
1478  initStringInfo(&join_sql_o);
1479  deparseRangeTblRef(&join_sql_o, root, outerrel,
1480  fpinfo->make_outerrel_subquery,
1481  ignore_rel, ignore_conds, params_list);
1482 
1483  /*
1484  * If inner relation is the target relation, skip deparsing it.
1485  * Note that since the join of the target relation with any other
1486  * relation in the query is an inner join and can never be within
1487  * the nullable side of an outer join, the join could be
1488  * interchanged with higher-level joins (cf. identity 1 on outer
1489  * join reordering shown in src/backend/optimizer/README), which
1490  * means it's safe to skip the target-relation deparsing here.
1491  */
1492  if (innerrel_is_target)
1493  {
1494  Assert(fpinfo->jointype == JOIN_INNER);
1495  Assert(fpinfo->joinclauses == NIL);
1496  appendStringInfo(buf, "%s", join_sql_o.data);
1497  return;
1498  }
1499  }
1500 
1501  /* Deparse inner relation if not the target relation. */
1502  if (!innerrel_is_target)
1503  {
1504  initStringInfo(&join_sql_i);
1505  deparseRangeTblRef(&join_sql_i, root, innerrel,
1506  fpinfo->make_innerrel_subquery,
1507  ignore_rel, ignore_conds, params_list);
1508 
1509  /*
1510  * If outer relation is the target relation, skip deparsing it.
1511  * See the above note about safety.
1512  */
1513  if (outerrel_is_target)
1514  {
1515  Assert(fpinfo->jointype == JOIN_INNER);
1516  Assert(fpinfo->joinclauses == NIL);
1517  appendStringInfo(buf, "%s", join_sql_i.data);
1518  return;
1519  }
1520  }
1521 
1522  /* Neither of the relations is the target relation. */
1523  Assert(!outerrel_is_target && !innerrel_is_target);
1524 
1525  /*
1526  * For a join relation FROM clause entry is deparsed as
1527  *
1528  * ((outer relation) <join type> (inner relation) ON (joinclauses))
1529  */
1530  appendStringInfo(buf, "(%s %s JOIN %s ON ", join_sql_o.data,
1531  get_jointype_name(fpinfo->jointype), join_sql_i.data);
1532 
1533  /* Append join clause; (TRUE) if no join clause */
1534  if (fpinfo->joinclauses)
1535  {
1536  deparse_expr_cxt context;
1537 
1538  context.buf = buf;
1539  context.foreignrel = foreignrel;
1540  context.scanrel = foreignrel;
1541  context.root = root;
1542  context.params_list = params_list;
1543 
1544  appendStringInfoChar(buf, '(');
1545  appendConditions(fpinfo->joinclauses, &context);
1546  appendStringInfoChar(buf, ')');
1547  }
1548  else
1549  appendStringInfoString(buf, "(TRUE)");
1550 
1551  /* End the FROM clause entry. */
1552  appendStringInfoChar(buf, ')');
1553  }
1554  else
1555  {
1556  RangeTblEntry *rte = planner_rt_fetch(foreignrel->relid, root);
1557 
1558  /*
1559  * Core code already has some lock on each rel being planned, so we
1560  * can use NoLock here.
1561  */
1562  Relation rel = heap_open(rte->relid, NoLock);
1563 
1564  deparseRelation(buf, rel);
1565 
1566  /*
1567  * Add a unique alias to avoid any conflict in relation names due to
1568  * pulled up subqueries in the query being built for a pushed down
1569  * join.
1570  */
1571  if (use_alias)
1572  appendStringInfo(buf, " %s%d", REL_ALIAS_PREFIX, foreignrel->relid);
1573 
1574  heap_close(rel, NoLock);
1575  }
1576 }
#define NIL
Definition: pg_list.h:69
List ** params_list
Definition: deparse.c:105
#define IS_JOIN_REL(rel)
Definition: relation.h:590
List * list_copy(const List *oldlist)
Definition: list.c:1160
List * list_concat(List *list1, List *list2)
Definition: list.c:321
#define heap_close(r, l)
Definition: heapam.h:97
RelOptInfo * outerrel
Definition: postgres_fdw.h:89
bool make_outerrel_subquery
Definition: postgres_fdw.h:99
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define planner_rt_fetch(rti, root)
Definition: relation.h:344
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
#define NoLock
Definition: lockdefs.h:34
static char * buf
Definition: pg_test_fsync.c:67
#define REL_ALIAS_PREFIX
Definition: deparse.c:108
const char * get_jointype_name(JoinType jointype)
Definition: deparse.c:1317
Relids relids
Definition: relation.h:612
static void deparseRangeTblRef(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel, bool make_subquery, Index ignore_rel, List **ignore_conds, List **params_list)
Definition: deparse.c:1582
Index relid
Definition: relation.h:640
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
static void appendConditions(List *exprs, deparse_expr_cxt *context)
Definition: deparse.c:1283
StringInfo buf
Definition: deparse.c:104
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
void * fdw_private
Definition: relation.h:664
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2187
PlannerInfo * root
Definition: deparse.c:99
#define Assert(condition)
Definition: c.h:699
RelOptInfo * innerrel
Definition: postgres_fdw.h:90
RelOptInfo * scanrel
Definition: deparse.c:101
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:486
RelOptInfo * foreignrel
Definition: deparse.c:100

◆ deparseFuncExpr()

static void deparseFuncExpr ( FuncExpr node,
deparse_expr_cxt context 
)
static

Definition at line 2575 of file deparse.c.

References appendFunctionName(), appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), arg, FuncExpr::args, buf, deparse_expr_cxt::buf, COERCE_EXPLICIT_CAST, COERCE_IMPLICIT_CAST, deparse_type_name(), deparseExpr(), exprIsLengthCoercion(), FuncExpr::funcformat, FuncExpr::funcid, FuncExpr::funcresulttype, FuncExpr::funcvariadic, lfirst, linitial, and lnext.

Referenced by deparseExpr().

2576 {
2577  StringInfo buf = context->buf;
2578  bool use_variadic;
2579  bool first;
2580  ListCell *arg;
2581 
2582  /*
2583  * If the function call came from an implicit coercion, then just show the
2584  * first argument.
2585  */
2586  if (node->funcformat == COERCE_IMPLICIT_CAST)
2587  {
2588  deparseExpr((Expr *) linitial(node->args), context);
2589  return;
2590  }
2591 
2592  /*
2593  * If the function call came from a cast, then show the first argument
2594  * plus an explicit cast operation.
2595  */
2596  if (node->funcformat == COERCE_EXPLICIT_CAST)
2597  {
2598  Oid rettype = node->funcresulttype;
2599  int32 coercedTypmod;
2600 
2601  /* Get the typmod if this is a length-coercion function */
2602  (void) exprIsLengthCoercion((Node *) node, &coercedTypmod);
2603 
2604  deparseExpr((Expr *) linitial(node->args), context);
2605  appendStringInfo(buf, "::%s",
2606  deparse_type_name(rettype, coercedTypmod));
2607  return;
2608  }
2609 
2610  /* Check if need to print VARIADIC (cf. ruleutils.c) */
2611  use_variadic = node->funcvariadic;
2612 
2613  /*
2614  * Normal function: display as proname(args).
2615  */
2616  appendFunctionName(node->funcid, context);
2617  appendStringInfoChar(buf, '(');
2618 
2619  /* ... and all the arguments */
2620  first = true;
2621  foreach(arg, node->args)
2622  {
2623  if (!first)
2624  appendStringInfoString(buf, ", ");
2625  if (use_variadic && lnext(arg) == NULL)
2626  appendStringInfoString(buf, "VARIADIC ");
2627  deparseExpr((Expr *) lfirst(arg), context);
2628  first = false;
2629  }
2630  appendStringInfoChar(buf, ')');
2631 }
Oid funcresulttype
Definition: primnodes.h:451
List * args
Definition: primnodes.h:458
static void appendFunctionName(Oid funcid, deparse_expr_cxt *context)
Definition: deparse.c:3159
Definition: nodes.h:517
bool exprIsLengthCoercion(const Node *expr, int32 *coercedTypmod)
Definition: nodeFuncs.c:513
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:313
CoercionForm funcformat
Definition: primnodes.h:455
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define linitial(l)
Definition: pg_list.h:111
Oid funcid
Definition: primnodes.h:450
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
#define lnext(lc)
Definition: pg_list.h:105
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
StringInfo buf
Definition: deparse.c:104
static char * deparse_type_name(Oid type_oid, int32 typemod)
Definition: deparse.c:855
#define lfirst(lc)
Definition: pg_list.h:106
static void deparseExpr(Expr *expr, deparse_expr_cxt *context)
Definition: deparse.c:2262
void * arg
bool funcvariadic
Definition: primnodes.h:453

◆ deparseInsertSql()

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

Definition at line 1652 of file deparse.c.

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

Referenced by postgresBeginForeignInsert(), and postgresPlanForeignModify().

1656 {
1657  AttrNumber pindex;
1658  bool first;
1659  ListCell *lc;
1660 
1661  appendStringInfoString(buf, "INSERT INTO ");
1662  deparseRelation(buf, rel);
1663 
1664  if (targetAttrs)
1665  {
1666  appendStringInfoChar(buf, '(');
1667 
1668  first = true;
1669  foreach(lc, targetAttrs)
1670  {
1671  int attnum = lfirst_int(lc);
1672 
1673  if (!first)
1674  appendStringInfoString(buf, ", ");
1675  first = false;
1676 
1677  deparseColumnRef(buf, rtindex, attnum, rte, false);
1678  }
1679 
1680  appendStringInfoString(buf, ") VALUES (");
1681 
1682  pindex = 1;
1683  first = true;
1684  foreach(lc, targetAttrs)
1685  {
1686  if (!first)
1687  appendStringInfoString(buf, ", ");
1688  first = false;
1689 
1690  appendStringInfo(buf, "$%d", pindex);
1691  pindex++;
1692  }
1693 
1694  appendStringInfoChar(buf, ')');
1695  }
1696  else
1697  appendStringInfoString(buf, " DEFAULT VALUES");
1698 
1699  if (doNothing)
1700  appendStringInfoString(buf, " ON CONFLICT DO NOTHING");
1701 
1702  deparseReturningList(buf, rte, rtindex, rel,
1703  rel->trigdesc && rel->trigdesc->trig_insert_after_row,
1704  returningList, retrieved_attrs);
1705 }
static void deparseReturningList(StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, bool trig_after_row, List *returningList, List **retrieved_attrs)
Definition: deparse.c:1931
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define lfirst_int(lc)
Definition: pg_list.h:107
TriggerDesc * trigdesc
Definition: rel.h:90
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
bool trig_insert_after_row
Definition: reltrigger.h:56
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
int16 attnum
Definition: pg_attribute.h:79
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2187
int16 AttrNumber
Definition: attnum.h:21
static void deparseColumnRef(StringInfo buf, int varno, int varattno, RangeTblEntry *rte, bool qualify_col)
Definition: deparse.c:2053

◆ deparseLockingClause()

static void deparseLockingClause ( deparse_expr_cxt context)
static

Definition at line 1193 of file deparse.c.

References appendStringInfo(), appendStringInfoString(), bms_is_member(), bms_next_member(), bms_num_members(), buf, deparse_expr_cxt::buf, CMD_DELETE, CMD_UPDATE, Query::commandType, RelOptInfo::fdw_private, get_plan_rowmark(), IS_JOIN_REL, LCS_FORKEYSHARE, LCS_FORNOKEYUPDATE, LCS_FORSHARE, LCS_FORUPDATE, LCS_NONE, PgFdwRelationInfo::lower_subquery_rels, PlannerInfo::parse, REL_ALIAS_PREFIX, RelOptInfo::relids, Query::resultRelation, foreign_glob_cxt::root, deparse_expr_cxt::root, PlannerInfo::rowMarks, deparse_expr_cxt::scanrel, and PlanRowMark::strength.

Referenced by deparseSelectStmtForRel().

1194 {
1195  StringInfo buf = context->buf;
1196  PlannerInfo *root = context->root;
1197  RelOptInfo *rel = context->scanrel;
1198  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) rel->fdw_private;
1199  int relid = -1;
1200 
1201  while ((relid = bms_next_member(rel->relids, relid)) >= 0)
1202  {
1203  /*
1204  * Ignore relation if it appears in a lower subquery. Locking clause
1205  * for such a relation is included in the subquery if necessary.
1206  */
1207  if (bms_is_member(relid, fpinfo->lower_subquery_rels))
1208  continue;
1209 
1210  /*
1211  * Add FOR UPDATE/SHARE if appropriate. We apply locking during the
1212  * initial row fetch, rather than later on as is done for local
1213  * tables. The extra roundtrips involved in trying to duplicate the
1214  * local semantics exactly don't seem worthwhile (see also comments
1215  * for RowMarkType).
1216  *
1217  * Note: because we actually run the query as a cursor, this assumes
1218  * that DECLARE CURSOR ... FOR UPDATE is supported, which it isn't
1219  * before 8.3.
1220  */
1221  if (relid == root->parse->resultRelation &&
1222  (root->parse->commandType == CMD_UPDATE ||
1223  root->parse->commandType == CMD_DELETE))
1224  {
1225  /* Relation is UPDATE/DELETE target, so use FOR UPDATE */
1226  appendStringInfoString(buf, " FOR UPDATE");
1227 
1228  /* Add the relation alias if we are here for a join relation */
1229  if (IS_JOIN_REL(rel))
1230  appendStringInfo(buf, " OF %s%d", REL_ALIAS_PREFIX, relid);
1231  }
1232  else
1233  {
1234  PlanRowMark *rc = get_plan_rowmark(root->rowMarks, relid);
1235 
1236  if (rc)
1237  {
1238  /*
1239  * Relation is specified as a FOR UPDATE/SHARE target, so
1240  * handle that. (But we could also see LCS_NONE, meaning this
1241  * isn't a target relation after all.)
1242  *
1243  * For now, just ignore any [NO] KEY specification, since (a)
1244  * it's not clear what that means for a remote table that we
1245  * don't have complete information about, and (b) it wouldn't
1246  * work anyway on older remote servers. Likewise, we don't
1247  * worry about NOWAIT.
1248  */
1249  switch (rc->strength)
1250  {
1251  case LCS_NONE:
1252  /* No locking needed */
1253  break;
1254  case LCS_FORKEYSHARE:
1255  case LCS_FORSHARE:
1256  appendStringInfoString(buf, " FOR SHARE");
1257  break;
1258  case LCS_FORNOKEYUPDATE:
1259  case LCS_FORUPDATE:
1260  appendStringInfoString(buf, " FOR UPDATE");
1261  break;
1262  }
1263 
1264  /* Add the relation alias if we are here for a join relation */
1265  if (bms_num_members(rel->relids) > 1 &&
1266  rc->strength != LCS_NONE)
1267  appendStringInfo(buf, " OF %s%d", REL_ALIAS_PREFIX, relid);
1268  }
1269  }
1270  }
1271 }
List * rowMarks
Definition: relation.h:268
Query * parse
Definition: relation.h:169
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1075
int resultRelation
Definition: parsenodes.h:122
#define IS_JOIN_REL(rel)
Definition: relation.h:590
Relids lower_subquery_rels
Definition: postgres_fdw.h:103
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:671
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
#define REL_ALIAS_PREFIX
Definition: deparse.c:108
Relids relids
Definition: relation.h:612
StringInfo buf
Definition: deparse.c:104
void * fdw_private
Definition: relation.h:664
CmdType commandType
Definition: parsenodes.h:112
PlannerInfo * root
Definition: deparse.c:99
LockClauseStrength strength
Definition: plannodes.h:1043
PlanRowMark * get_plan_rowmark(List *rowmarks, Index rtindex)
Definition: preptlist.c:424
RelOptInfo * scanrel
Definition: deparse.c:101
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:486

◆ deparseNullTest()

static void deparseNullTest ( NullTest node,
deparse_expr_cxt context 
)
static

Definition at line 2831 of file deparse.c.

References appendStringInfoChar(), appendStringInfoString(), NullTest::arg, NullTest::argisrow, buf, deparse_expr_cxt::buf, deparseExpr(), exprType(), IS_NULL, NullTest::nulltesttype, and type_is_rowtype().

Referenced by deparseExpr().

2832 {
2833  StringInfo buf = context->buf;
2834 
2835  appendStringInfoChar(buf, '(');
2836  deparseExpr(node->arg, context);
2837 
2838  /*
2839  * For scalar inputs, we prefer to print as IS [NOT] NULL, which is
2840  * shorter and traditional. If it's a rowtype input but we're applying a
2841  * scalar test, must print IS [NOT] DISTINCT FROM NULL to be semantically
2842  * correct.
2843  */
2844  if (node->argisrow || !type_is_rowtype(exprType((Node *) node->arg)))
2845  {
2846  if (node->nulltesttype == IS_NULL)
2847  appendStringInfoString(buf, " IS NULL)");
2848  else
2849  appendStringInfoString(buf, " IS NOT NULL)");
2850  }
2851  else
2852  {
2853  if (node->nulltesttype == IS_NULL)
2854  appendStringInfoString(buf, " IS NOT DISTINCT FROM NULL)");
2855  else
2856  appendStringInfoString(buf, " IS DISTINCT FROM NULL)");
2857  }
2858 }
Definition: nodes.h:517
Expr * arg
Definition: primnodes.h:1188
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2409
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
StringInfo buf
Definition: deparse.c:104
NullTestType nulltesttype
Definition: primnodes.h:1189
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
static void deparseExpr(Expr *expr, deparse_expr_cxt *context)
Definition: deparse.c:2262
bool argisrow
Definition: primnodes.h:1190

◆ deparseOperatorName()

static void deparseOperatorName ( StringInfo  buf,
Form_pg_operator  opform 
)
static

Definition at line 2689 of file deparse.c.

References appendStringInfo(), appendStringInfoString(), get_namespace_name(), NameStr, and quote_identifier().

Referenced by appendAggOrderBy(), deparseOpExpr(), and deparseScalarArrayOpExpr().

2690 {
2691  char *opname;
2692 
2693  /* opname is not a SQL identifier, so we should not quote it. */
2694  opname = NameStr(opform->oprname);
2695 
2696  /* Print schema name only if it's not pg_catalog */
2697  if (opform->oprnamespace != PG_CATALOG_NAMESPACE)
2698  {
2699  const char *opnspname;
2700 
2701  opnspname = get_namespace_name(opform->oprnamespace);
2702  /* Print fully qualified operator name. */
2703  appendStringInfo(buf, "OPERATOR(%s.%s)",
2704  quote_identifier(opnspname), opname);
2705  }
2706  else
2707  {
2708  /* Just print operator name. */
2709  appendStringInfoString(buf, opname);
2710  }
2711 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10488
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3051
#define NameStr(name)
Definition: c.h:576

◆ deparseOpExpr()

static void deparseOpExpr ( OpExpr node,
deparse_expr_cxt context 
)
static

Definition at line 2638 of file deparse.c.

References appendStringInfoChar(), arg, OpExpr::args, Assert, buf, deparse_expr_cxt::buf, deparseExpr(), deparseOperatorName(), elog, ERROR, GETSTRUCT, HeapTupleIsValid, lfirst, list_head(), list_length(), list_tail(), ObjectIdGetDatum, OPEROID, OpExpr::opno, ReleaseSysCache(), and SearchSysCache1().

Referenced by deparseExpr().

2639 {
2640  StringInfo buf = context->buf;
2641  HeapTuple tuple;
2642  Form_pg_operator form;
2643  char oprkind;
2644  ListCell *arg;
2645 
2646  /* Retrieve information about the operator from system catalog. */
2647  tuple = SearchSysCache1(OPEROID, ObjectIdGetDatum(node->opno));
2648  if (!HeapTupleIsValid(tuple))
2649  elog(ERROR, "cache lookup failed for operator %u", node->opno);
2650  form = (Form_pg_operator) GETSTRUCT(tuple);
2651  oprkind = form->oprkind;
2652 
2653  /* Sanity check. */
2654  Assert((oprkind == 'r' && list_length(node->args) == 1) ||
2655  (oprkind == 'l' && list_length(node->args) == 1) ||
2656  (oprkind == 'b' && list_length(node->args) == 2));
2657 
2658  /* Always parenthesize the expression. */
2659  appendStringInfoChar(buf, '(');
2660 
2661  /* Deparse left operand. */
2662  if (oprkind == 'r' || oprkind == 'b')
2663  {
2664  arg = list_head(node->args);
2665  deparseExpr(lfirst(arg), context);
2666  appendStringInfoChar(buf, ' ');
2667  }
2668 
2669  /* Deparse operator name. */
2670  deparseOperatorName(buf, form);
2671 
2672  /* Deparse right operand. */
2673  if (oprkind == 'l' || oprkind == 'b')
2674  {
2675  arg = list_tail(node->args);
2676  appendStringInfoChar(buf, ' ');
2677  deparseExpr(lfirst(arg), context);
2678  }
2679 
2680  appendStringInfoChar(buf, ')');
2681 
2682  ReleaseSysCache(tuple);
2683 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:668
static void deparseOperatorName(StringInfo buf, Form_pg_operator opform)
Definition: deparse.c:2689
static ListCell * list_tail(List *l)
Definition: pg_list.h:83
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:67
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
StringInfo buf
Definition: deparse.c:104
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:82
static void deparseExpr(Expr *expr, deparse_expr_cxt *context)
Definition: deparse.c:2262
void * arg
Oid opno
Definition: primnodes.h:497
#define elog
Definition: elog.h:219
List * args
Definition: primnodes.h:503

◆ deparseParam()

static void deparseParam ( Param node,
deparse_expr_cxt context 
)
static

Definition at line 2496 of file deparse.c.

References equal(), lappend(), lfirst, deparse_expr_cxt::params_list, Param::paramtype, Param::paramtypmod, printRemoteParam(), and printRemotePlaceholder().

Referenced by deparseExpr().

2497 {
2498  if (context->params_list)
2499  {
2500  int pindex = 0;
2501  ListCell *lc;
2502 
2503  /* find its index in params_list */
2504  foreach(lc, *context->params_list)
2505  {
2506  pindex++;
2507  if (equal(node, (Node *) lfirst(lc)))
2508  break;
2509  }
2510  if (lc == NULL)
2511  {
2512  /* not in list, so add it */
2513  pindex++;
2514  *context->params_list = lappend(*context->params_list, node);
2515  }
2516 
2517  printRemoteParam(pindex, node->paramtype, node->paramtypmod, context);
2518  }
2519  else
2520  {
2521  printRemotePlaceholder(node->paramtype, node->paramtypmod, context);
2522  }
2523 }
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2986
List ** params_list
Definition: deparse.c:105
Definition: nodes.h:517
static void printRemoteParam(int paramindex, Oid paramtype, int32 paramtypmod, deparse_expr_cxt *context)
Definition: deparse.c:3041
List * lappend(List *list, void *datum)
Definition: list.c:128
int32 paramtypmod
Definition: primnodes.h:248
#define lfirst(lc)
Definition: pg_list.h:106
Oid paramtype
Definition: primnodes.h:247
static void printRemotePlaceholder(Oid paramtype, int32 paramtypmod, deparse_expr_cxt *context)
Definition: deparse.c:3067

◆ deparseRangeTblRef()

static void deparseRangeTblRef ( StringInfo  buf,
PlannerInfo root,
RelOptInfo foreignrel,
bool  make_subquery,
Index  ignore_rel,
List **  ignore_conds,
List **  params_list 
)
static

Definition at line 1582 of file deparse.c.

References appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), Assert, bms_is_member(), deparseFromExprForRel(), deparseSelectStmtForRel(), PathTarget::exprs, RelOptInfo::fdw_private, i, IS_JOIN_REL, IS_SIMPLE_REL, list_length(), PgFdwRelationInfo::local_conds, NIL, PgFdwRelationInfo::relation_index, RelOptInfo::relids, RelOptInfo::reltarget, PgFdwRelationInfo::remote_conds, SUBQUERY_COL_ALIAS_PREFIX, and SUBQUERY_REL_ALIAS_PREFIX.

Referenced by deparseFromExprForRel().

1585 {
1586  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
1587 
1588  /* Should only be called in these cases. */
1589  Assert(IS_SIMPLE_REL(foreignrel) || IS_JOIN_REL(foreignrel));
1590 
1591  Assert(fpinfo->local_conds == NIL);
1592 
1593  /* If make_subquery is true, deparse the relation as a subquery. */
1594  if (make_subquery)
1595  {
1596  List *retrieved_attrs;
1597  int ncols;
1598 
1599  /*
1600  * The given relation shouldn't contain the target relation, because
1601  * this should only happen for input relations for a full join, and
1602  * such relations can never contain an UPDATE/DELETE target.
1603  */
1604  Assert(ignore_rel == 0 ||
1605  !bms_is_member(ignore_rel, foreignrel->relids));
1606 
1607  /* Deparse the subquery representing the relation. */
1608  appendStringInfoChar(buf, '(');
1609  deparseSelectStmtForRel(buf, root, foreignrel, NIL,
1610  fpinfo->remote_conds, NIL, true,
1611  &retrieved_attrs, params_list);
1612  appendStringInfoChar(buf, ')');
1613 
1614  /* Append the relation alias. */
1616  fpinfo->relation_index);
1617 
1618  /*
1619  * Append the column aliases if needed. Note that the subquery emits
1620  * expressions specified in the relation's reltarget (see
1621  * deparseSubqueryTargetList).
1622  */
1623  ncols = list_length(foreignrel->reltarget->exprs);
1624  if (ncols > 0)
1625  {
1626  int i;
1627 
1628  appendStringInfoChar(buf, '(');
1629  for (i = 1; i <= ncols; i++)
1630  {
1631  if (i > 1)
1632  appendStringInfoString(buf, ", ");
1633 
1635  }
1636  appendStringInfoChar(buf, ')');
1637  }
1638  }
1639  else
1640  deparseFromExprForRel(buf, root, foreignrel, true, ignore_rel,
1641  ignore_conds, params_list);
1642 }
#define NIL
Definition: pg_list.h:69
#define IS_JOIN_REL(rel)
Definition: relation.h:590
#define IS_SIMPLE_REL(rel)
Definition: relation.h:585
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define SUBQUERY_COL_ALIAS_PREFIX
Definition: deparse.c:113
#define SUBQUERY_REL_ALIAS_PREFIX
Definition: deparse.c:112
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
Relids relids
Definition: relation.h:612
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
List * exprs
Definition: relation.h:1008
void deparseSelectStmtForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *rel, List *tlist, List *remote_conds, List *pathkeys, bool is_subquery, List **retrieved_attrs, List **params_list)
Definition: deparse.c:931
void * fdw_private
Definition: relation.h:664
#define Assert(condition)
Definition: c.h:699
static int list_length(const List *l)
Definition: pg_list.h:89
static void deparseFromExprForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel, bool use_alias, Index ignore_rel, List **ignore_conds, List **params_list)
Definition: deparse.c:1431
int i
Definition: pg_list.h:45
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:486
struct PathTarget * reltarget
Definition: relation.h:623

◆ deparseRelabelType()

static void deparseRelabelType ( RelabelType node,
deparse_expr_cxt context 
)
static

Definition at line 2780 of file deparse.c.

References appendStringInfo(), RelabelType::arg, deparse_expr_cxt::buf, COERCE_IMPLICIT_CAST, deparse_type_name(), deparseExpr(), RelabelType::relabelformat, RelabelType::resulttype, and RelabelType::resulttypmod.

Referenced by deparseExpr().

2781 {
2782  deparseExpr(node->arg, context);
2783  if (node->relabelformat != COERCE_IMPLICIT_CAST)
2784  appendStringInfo(context->buf, "::%s",
2786  node->resulttypmod));
2787 }
Expr * arg
Definition: primnodes.h:795
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
StringInfo buf
Definition: deparse.c:104
Oid resulttype
Definition: primnodes.h:796
static char * deparse_type_name(Oid type_oid, int32 typemod)
Definition: deparse.c:855
static void deparseExpr(Expr *expr, deparse_expr_cxt *context)
Definition: deparse.c:2262
int32 resulttypmod
Definition: primnodes.h:797
CoercionForm relabelformat
Definition: primnodes.h:799

◆ deparseRelation()

static void deparseRelation ( StringInfo  buf,
Relation  rel 
)
static

Definition at line 2187 of file deparse.c.

References appendStringInfo(), defGetString(), DefElem::defname, get_namespace_name(), GetForeignTable(), lfirst, ForeignTable::options, quote_identifier(), RelationGetNamespace, RelationGetRelationName, and RelationGetRelid.

Referenced by deparseAnalyzeSizeSql(), deparseAnalyzeSql(), deparseDeleteSql(), deparseDirectDeleteSql(), deparseDirectUpdateSql(), deparseFromExprForRel(), deparseInsertSql(), and deparseUpdateSql().

2188 {
2189  ForeignTable *table;
2190  const char *nspname = NULL;
2191  const char *relname = NULL;
2192  ListCell *lc;
2193 
2194  /* obtain additional catalog information. */
2195  table = GetForeignTable(RelationGetRelid(rel));
2196 
2197  /*
2198  * Use value of FDW options if any, instead of the name of object itself.
2199  */
2200  foreach(lc, table->options)
2201  {
2202  DefElem *def = (DefElem *) lfirst(lc);
2203 
2204  if (strcmp(def->defname, "schema_name") == 0)
2205  nspname = defGetString(def);
2206  else if (strcmp(def->defname, "table_name") == 0)
2207  relname = defGetString(def);
2208  }
2209 
2210  /*
2211  * Note: we could skip printing the schema name if it's pg_catalog, but
2212  * that doesn't seem worth the trouble.
2213  */
2214  if (nspname == NULL)
2215  nspname = get_namespace_name(RelationGetNamespace(rel));
2216  if (relname == NULL)
2217  relname = RelationGetRelationName(rel);
2218 
2219  appendStringInfo(buf, "%s.%s",
2220  quote_identifier(nspname), quote_identifier(relname));
2221 }
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10488
ForeignTable * GetForeignTable(Oid relid)
Definition: foreign.c:216
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
char * defGetString(DefElem *def)
Definition: define.c:49
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3051
#define RelationGetRelationName(relation)
Definition: rel.h:441
#define lfirst(lc)
Definition: pg_list.h:106
List * options
Definition: foreign.h:68
char * defname
Definition: parsenodes.h:730
#define RelationGetRelid(relation)
Definition: rel.h:407
#define RelationGetNamespace(relation)
Definition: rel.h:448

◆ deparseReturningList()

static void deparseReturningList ( StringInfo  buf,
RangeTblEntry rte,
Index  rtindex,
Relation  rel,
bool  trig_after_row,
List returningList,
List **  retrieved_attrs 
)
static

Definition at line 1931 of file deparse.c.

References bms_make_singleton(), deparseTargetList(), FirstLowInvalidHeapAttributeNumber, NIL, and pull_varattnos().

Referenced by deparseDeleteSql(), deparseDirectDeleteSql(), deparseDirectUpdateSql(), deparseInsertSql(), and deparseUpdateSql().

1936 {
1937  Bitmapset *attrs_used = NULL;
1938 
1939  if (trig_after_row)
1940  {
1941  /* whole-row reference acquires all non-system columns */
1942  attrs_used =
1944  }
1945 
1946  if (returningList != NIL)
1947  {
1948  /*
1949  * We need the attrs, non-system and system, mentioned in the local
1950  * query's RETURNING list.
1951  */
1952  pull_varattnos((Node *) returningList, rtindex,
1953  &attrs_used);
1954  }
1955 
1956  if (attrs_used != NULL)
1957  deparseTargetList(buf, rte, rtindex, rel, true, attrs_used, false,
1958  retrieved_attrs);
1959  else
1960  *retrieved_attrs = NIL;
1961 }
#define NIL
Definition: pg_list.h:69
Definition: nodes.h:517
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
void pull_varattnos(Node *node, Index varno, Bitmapset **varattnos)
Definition: var.c:219
static void deparseTargetList(StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, bool is_returning, Bitmapset *attrs_used, bool qualify_col, List **retrieved_attrs)
Definition: deparse.c:1101
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:245

◆ deparseScalarArrayOpExpr()

static void deparseScalarArrayOpExpr ( ScalarArrayOpExpr node,
deparse_expr_cxt context 
)
static

Definition at line 2735 of file deparse.c.

References appendStringInfo(), appendStringInfoChar(), ScalarArrayOpExpr::args, Assert, buf, deparse_expr_cxt::buf, deparseExpr(), deparseOperatorName(), elog, ERROR, GETSTRUCT, HeapTupleIsValid, linitial, list_length(), lsecond, ObjectIdGetDatum, OPEROID, ScalarArrayOpExpr::opno, ReleaseSysCache(), SearchSysCache1(), and ScalarArrayOpExpr::useOr.

Referenced by deparseExpr().

2736 {
2737  StringInfo buf = context->buf;
2738  HeapTuple tuple;
2739  Form_pg_operator form;
2740  Expr *arg1;
2741  Expr *arg2;
2742 
2743  /* Retrieve information about the operator from system catalog. */
2744  tuple = SearchSysCache1(OPEROID, ObjectIdGetDatum(node->opno));
2745  if (!HeapTupleIsValid(tuple))
2746  elog(ERROR, "cache lookup failed for operator %u", node->opno);
2747  form = (Form_pg_operator) GETSTRUCT(tuple);
2748 
2749  /* Sanity check. */
2750  Assert(list_length(node->args) == 2);
2751 
2752  /* Always parenthesize the expression. */
2753  appendStringInfoChar(buf, '(');
2754 
2755  /* Deparse left operand. */
2756  arg1 = linitial(node->args);
2757  deparseExpr(arg1, context);
2758  appendStringInfoChar(buf, ' ');
2759 
2760  /* Deparse operator name plus decoration. */
2761  deparseOperatorName(buf, form);
2762  appendStringInfo(buf, " %s (", node->useOr ? "ANY" : "ALL");
2763 
2764  /* Deparse right operand. */
2765  arg2 = lsecond(node->args);
2766  deparseExpr(arg2, context);
2767 
2768  appendStringInfoChar(buf, ')');
2769 
2770  /* Always parenthesize the expression. */
2771  appendStringInfoChar(buf, ')');
2772 
2773  ReleaseSysCache(tuple);
2774 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:668
static void deparseOperatorName(StringInfo buf, Form_pg_operator opform)
Definition: deparse.c:2689
#define lsecond(l)
Definition: pg_list.h:116
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define linitial(l)
Definition: pg_list.h:111
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:67
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
StringInfo buf
Definition: deparse.c:104
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:699
static int list_length(const List *l)
Definition: pg_list.h:89
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:82
static void deparseExpr(Expr *expr, deparse_expr_cxt *context)
Definition: deparse.c:2262
#define elog
Definition: elog.h:219

◆ deparseSelectSql()

static void deparseSelectSql ( List tlist,
bool  is_subquery,
List **  retrieved_attrs,
deparse_expr_cxt context 
)
static

Definition at line 1009 of file deparse.c.

References appendStringInfoString(), PgFdwRelationInfo::attrs_used, buf, deparse_expr_cxt::buf, deparseExplicitTargetList(), deparseSubqueryTargetList(), deparseTargetList(), RelOptInfo::fdw_private, foreign_glob_cxt::foreignrel, deparse_expr_cxt::foreignrel, heap_close, heap_open(), IS_JOIN_REL, IS_UPPER_REL, NoLock, planner_rt_fetch, RelOptInfo::relid, RangeTblEntry::relid, foreign_glob_cxt::root, and deparse_expr_cxt::root.

Referenced by deparseSelectStmtForRel().

1011 {
1012  StringInfo buf = context->buf;
1013  RelOptInfo *foreignrel = context->foreignrel;
1014  PlannerInfo *root = context->root;
1015  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
1016 
1017  /*
1018  * Construct SELECT list
1019  */
1020  appendStringInfoString(buf, "SELECT ");
1021 
1022  if (is_subquery)
1023  {
1024  /*
1025  * For a relation that is deparsed as a subquery, emit expressions
1026  * specified in the relation's reltarget. Note that since this is for
1027  * the subquery, no need to care about *retrieved_attrs.
1028  */
1029  deparseSubqueryTargetList(context);
1030  }
1031  else if (IS_JOIN_REL(foreignrel) || IS_UPPER_REL(foreignrel))
1032  {
1033  /*
1034  * For a join or upper relation the input tlist gives the list of
1035  * columns required to be fetched from the foreign server.
1036  */
1037  deparseExplicitTargetList(tlist, false, retrieved_attrs, context);
1038  }
1039  else
1040  {
1041  /*
1042  * For a base relation fpinfo->attrs_used gives the list of columns
1043  * required to be fetched from the foreign server.
1044  */
1045  RangeTblEntry *rte = planner_rt_fetch(foreignrel->relid, root);
1046 
1047  /*
1048  * Core code already has some lock on each rel being planned, so we
1049  * can use NoLock here.
1050  */
1051  Relation rel = heap_open(rte->relid, NoLock);
1052 
1053  deparseTargetList(buf, rte, foreignrel->relid, rel, false,
1054  fpinfo->attrs_used, false, retrieved_attrs);
1055  heap_close(rel, NoLock);
1056  }
1057 }
static void deparseSubqueryTargetList(deparse_expr_cxt *context)
Definition: deparse.c:1390
#define IS_UPPER_REL(rel)
Definition: relation.h:595
#define IS_JOIN_REL(rel)
Definition: relation.h:590
#define heap_close(r, l)
Definition: heapam.h:97
static void deparseTargetList(StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, bool is_returning, Bitmapset *attrs_used, bool qualify_col, List **retrieved_attrs)
Definition: deparse.c:1101
#define planner_rt_fetch(rti, root)
Definition: relation.h:344
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
#define NoLock
Definition: lockdefs.h:34
static char * buf
Definition: pg_test_fsync.c:67
static void deparseExplicitTargetList(List *tlist, bool is_returning, List **retrieved_attrs, deparse_expr_cxt *context)
Definition: deparse.c:1354
Index relid
Definition: relation.h:640
StringInfo buf
Definition: deparse.c:104
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
void * fdw_private
Definition: relation.h:664
PlannerInfo * root
Definition: deparse.c:99
Bitmapset * attrs_used
Definition: postgres_fdw.h:50
RelOptInfo * foreignrel
Definition: deparse.c:100

◆ deparseSelectStmtForRel()

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

Definition at line 931 of file deparse.c.

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

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

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

◆ deparseSortGroupClause()

static Node * deparseSortGroupClause ( Index  ref,
List tlist,
bool  force_colno,
deparse_expr_cxt context 
)
static

Definition at line 3194 of file deparse.c.

References appendStringInfo(), appendStringInfoChar(), Assert, buf, deparse_expr_cxt::buf, deparseConst(), deparseExpr(), TargetEntry::expr, get_sortgroupref_tle(), IsA, TargetEntry::resjunk, and TargetEntry::resno.

Referenced by appendAggOrderBy(), and appendGroupByClause().

3196 {
3197  StringInfo buf = context->buf;
3198  TargetEntry *tle;
3199  Expr *expr;
3200 
3201  tle = get_sortgroupref_tle(ref, tlist);
3202  expr = tle->expr;
3203 
3204  if (force_colno)
3205  {
3206  /* Use column-number form when requested by caller. */
3207  Assert(!tle->resjunk);
3208  appendStringInfo(buf, "%d", tle->resno);
3209  }
3210  else if (expr && IsA(expr, Const))
3211  {
3212  /*
3213  * Force a typecast here so that we don't emit something like "GROUP
3214  * BY 2", which will be misconstrued as a column position rather than
3215  * a constant.
3216  */
3217  deparseConst((Const *) expr, context, 1);
3218  }
3219  else if (!expr || IsA(expr, Var))
3220  deparseExpr(expr, context);
3221  else
3222  {
3223  /* Always parenthesize the expression. */
3224  appendStringInfoChar(buf, '(');
3225  deparseExpr(expr, context);
3226  appendStringInfoChar(buf, ')');
3227  }
3228 
3229  return (Node *) expr;
3230 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
Definition: nodes.h:517
Definition: primnodes.h:164
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
bool resjunk
Definition: primnodes.h:1383
static char * buf
Definition: pg_test_fsync.c:67
AttrNumber resno
Definition: primnodes.h:1377
TargetEntry * get_sortgroupref_tle(Index sortref, List *targetList)
Definition: tlist.c:348
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
StringInfo buf
Definition: deparse.c:104
#define Assert(condition)
Definition: c.h:699
static void deparseConst(Const *node, deparse_expr_cxt *context, int showtype)
Definition: deparse.c:2390
Expr * expr
Definition: primnodes.h:1376
static void deparseExpr(Expr *expr, deparse_expr_cxt *context)
Definition: deparse.c:2262

◆ deparseStringLiteral()

void deparseStringLiteral ( StringInfo  buf,
const char *  val 
)

Definition at line 2227 of file deparse.c.

References appendStringInfoChar(), ESCAPE_STRING_SYNTAX, and SQL_STR_DOUBLE.

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

2228 {
2229  const char *valptr;
2230 
2231  /*
2232  * Rather than making assumptions about the remote server's value of
2233  * standard_conforming_strings, always use E'foo' syntax if there are any
2234  * backslashes. This will fail on remote servers before 8.1, but those
2235  * are long out of support.
2236  */
2237  if (strchr(val, '\\') != NULL)
2239  appendStringInfoChar(buf, '\'');
2240  for (valptr = val; *valptr; valptr++)
2241  {
2242  char ch = *valptr;
2243 
2244  if (SQL_STR_DOUBLE(ch, true))
2245  appendStringInfoChar(buf, ch);
2246  appendStringInfoChar(buf, ch);
2247  }
2248  appendStringInfoChar(buf, '\'');
2249 }
#define ESCAPE_STRING_SYNTAX
Definition: c.h:1005
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
#define SQL_STR_DOUBLE(ch, escape_backslash)
Definition: c.h:1002
long val
Definition: informix.c:689

◆ deparseSubqueryTargetList()

static void deparseSubqueryTargetList ( deparse_expr_cxt context)
static

Definition at line 1390 of file deparse.c.

References appendStringInfoString(), Assert, buf, deparse_expr_cxt::buf, deparseExpr(), PathTarget::exprs, foreign_glob_cxt::foreignrel, deparse_expr_cxt::foreignrel, IS_JOIN_REL, IS_SIMPLE_REL, lfirst, and RelOptInfo::reltarget.

Referenced by deparseSelectSql().

1391 {
1392  StringInfo buf = context->buf;
1393  RelOptInfo *foreignrel = context->foreignrel;
1394  bool first;
1395  ListCell *lc;
1396 
1397  /* Should only be called in these cases. */
1398  Assert(IS_SIMPLE_REL(foreignrel) || IS_JOIN_REL(foreignrel));
1399 
1400  first = true;
1401  foreach(lc, foreignrel->reltarget->exprs)
1402  {
1403  Node *node = (Node *) lfirst(lc);
1404 
1405  if (!first)
1406  appendStringInfoString(buf, ", ");
1407  first = false;
1408 
1409  deparseExpr((Expr *) node, context);
1410  }
1411 
1412  /* Don't generate bad syntax if no expressions */
1413  if (first)
1414  appendStringInfoString(buf, "NULL");
1415 }
#define IS_JOIN_REL(rel)
Definition: relation.h:590
Definition: nodes.h:517
#define IS_SIMPLE_REL(rel)
Definition: relation.h:585
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
static char * buf
Definition: pg_test_fsync.c:67
List * exprs
Definition: relation.h:1008
StringInfo buf
Definition: deparse.c:104
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
static void deparseExpr(Expr *expr, deparse_expr_cxt *context)
Definition: deparse.c:2262
RelOptInfo * foreignrel
Definition: deparse.c:100
struct PathTarget * reltarget
Definition: relation.h:623

◆ deparseTargetList()

static void deparseTargetList ( StringInfo  buf,
RangeTblEntry rte,
Index  rtindex,
Relation  rel,
bool  is_returning,
Bitmapset attrs_used,
bool  qualify_col,
List **  retrieved_attrs 
)
static

Definition at line 1101 of file deparse.c.

References ADD_REL_QUALIFIER, appendStringInfoString(), bms_is_member(), deparseColumnRef(), FirstLowInvalidHeapAttributeNumber, i, lappend_int(), tupleDesc::natts, NIL, ObjectIdAttributeNumber, RelationGetDescr, SelfItemPointerAttributeNumber, and TupleDescAttr.

Referenced by deparseColumnRef(), deparseReturningList(), and deparseSelectSql().

1109 {
1110  TupleDesc tupdesc = RelationGetDescr(rel);
1111  bool have_wholerow;
1112  bool first;
1113  int i;
1114 
1115  *retrieved_attrs = NIL;
1116 
1117  /* If there's a whole-row reference, we'll need all the columns. */
1119  attrs_used);
1120 
1121  first = true;
1122  for (i = 1; i <= tupdesc->natts; i++)
1123  {
1124  Form_pg_attribute attr = TupleDescAttr(tupdesc, i - 1);
1125 
1126  /* Ignore dropped attributes. */
1127  if (attr->attisdropped)
1128  continue;
1129 
1130  if (have_wholerow ||
1132  attrs_used))
1133  {
1134  if (!first)
1135  appendStringInfoString(buf, ", ");
1136  else if (is_returning)
1137  appendStringInfoString(buf, " RETURNING ");
1138  first = false;
1139 
1140  deparseColumnRef(buf, rtindex, i, rte, qualify_col);
1141 
1142  *retrieved_attrs = lappend_int(*retrieved_attrs, i);
1143  }
1144  }
1145 
1146  /*
1147  * Add ctid and oid if needed. We currently don't support retrieving any
1148  * other system columns.
1149  */
1151  attrs_used))
1152  {
1153  if (!first)
1154  appendStringInfoString(buf, ", ");
1155  else if (is_returning)
1156  appendStringInfoString(buf, " RETURNING ");
1157  first = false;
1158 
1159  if (qualify_col)
1160  ADD_REL_QUALIFIER(buf, rtindex);
1161  appendStringInfoString(buf, "ctid");
1162 
1163  *retrieved_attrs = lappend_int(*retrieved_attrs,
1165  }
1167  attrs_used))
1168  {
1169  if (!first)
1170  appendStringInfoString(buf, ", ");
1171  else if (is_returning)
1172  appendStringInfoString(buf, " RETURNING ");
1173  first = false;
1174 
1175  if (qualify_col)
1176  ADD_REL_QUALIFIER(buf, rtindex);
1177  appendStringInfoString(buf, "oid");
1178 
1179  *retrieved_attrs = lappend_int(*retrieved_attrs,
1181  }
1182 
1183  /* Don't generate bad syntax if no undropped columns */
1184  if (first && !is_returning)
1185  appendStringInfoString(buf, "NULL");
1186 }
#define NIL
Definition: pg_list.h:69
#define RelationGetDescr(relation)
Definition: rel.h:433
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:93
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
int natts
Definition: tupdesc.h:82
#define ADD_REL_QUALIFIER(buf, varno)
Definition: deparse.c:110
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:197
List * lappend_int(List *list, int datum)
Definition: list.c:146
int i
#define SelfItemPointerAttributeNumber
Definition: sysattr.h:21
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:486
static void deparseColumnRef(StringInfo buf, int varno, int varattno, RangeTblEntry *rte, bool qualify_col)
Definition: deparse.c:2053

◆ deparseUpdateSql()

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

Definition at line 1715 of file deparse.c.

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

Referenced by postgresPlanForeignModify().

1719 {
1720  AttrNumber pindex;
1721  bool first;
1722  ListCell *lc;
1723 
1724  appendStringInfoString(buf, "UPDATE ");
1725  deparseRelation(buf, rel);
1726  appendStringInfoString(buf, " SET ");
1727 
1728  pindex = 2; /* ctid is always the first param */
1729  first = true;
1730  foreach(lc, targetAttrs)
1731  {
1732  int attnum = lfirst_int(lc);
1733 
1734  if (!first)
1735  appendStringInfoString(buf, ", ");
1736  first = false;
1737 
1738  deparseColumnRef(buf, rtindex, attnum, rte, false);
1739  appendStringInfo(buf, " = $%d", pindex);
1740  pindex++;
1741  }
1742  appendStringInfoString(buf, " WHERE ctid = $1");
1743 
1744  deparseReturningList(buf, rte, rtindex, rel,
1745  rel->trigdesc && rel->trigdesc->trig_update_after_row,
1746  returningList, retrieved_attrs);
1747 }
static void deparseReturningList(StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, bool trig_after_row, List *returningList, List **retrieved_attrs)
Definition: deparse.c:1931
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define lfirst_int(lc)
Definition: pg_list.h:107
TriggerDesc * trigdesc
Definition: rel.h:90
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
bool trig_update_after_row
Definition: reltrigger.h:61
int16 attnum
Definition: pg_attribute.h:79
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2187
int16 AttrNumber
Definition: attnum.h:21
static void deparseColumnRef(StringInfo buf, int varno, int varattno, RangeTblEntry *rte, bool qualify_col)
Definition: deparse.c:2053

◆ deparseVar()

static void deparseVar ( Var node,
deparse_expr_cxt context 
)
static

Definition at line 2324 of file deparse.c.

References appendStringInfo(), bms_is_member(), bms_num_members(), deparse_expr_cxt::buf, deparseColumnRef(), equal(), is_subquery_var(), lappend(), lfirst, deparse_expr_cxt::params_list, planner_rt_fetch, printRemoteParam(), printRemotePlaceholder(), foreign_glob_cxt::relids, RelOptInfo::relids, deparse_expr_cxt::root, deparse_expr_cxt::scanrel, SUBQUERY_COL_ALIAS_PREFIX, SUBQUERY_REL_ALIAS_PREFIX, Var::varattno, Var::varlevelsup, Var::varno, Var::vartype, and Var::vartypmod.

Referenced by deparseExpr().

2325 {
2326  Relids relids = context->scanrel->relids;
2327  int relno;
2328  int colno;
2329 
2330  /* Qualify columns when multiple relations are involved. */
2331  bool qualify_col = (bms_num_members(relids) > 1);
2332 
2333  /*
2334  * If the Var belongs to the foreign relation that is deparsed as a
2335  * subquery, use the relation and column alias to the Var provided by the
2336  * subquery, instead of the remote name.
2337  */
2338  if (is_subquery_var(node, context->scanrel, &relno, &colno))
2339  {
2340  appendStringInfo(context->buf, "%s%d.%s%d",
2342  SUBQUERY_COL_ALIAS_PREFIX, colno);
2343  return;
2344  }
2345 
2346  if (bms_is_member(node->varno, relids) && node->varlevelsup == 0)
2347  deparseColumnRef(context->buf, node->varno, node->varattno,
2348  planner_rt_fetch(node->varno, context->root),
2349  qualify_col);
2350  else
2351  {
2352  /* Treat like a Param */
2353  if (context->params_list)
2354  {
2355  int pindex = 0;
2356  ListCell *lc;
2357 
2358  /* find its index in params_list */
2359  foreach(lc, *context->params_list)
2360  {
2361  pindex++;
2362  if (equal(node, (Node *) lfirst(lc)))
2363  break;
2364  }
2365  if (lc == NULL)
2366  {
2367  /* not in list, so add it */
2368  pindex++;
2369  *context->params_list = lappend(*context->params_list, node);
2370  }
2371 
2372  printRemoteParam(pindex, node->vartype, node->vartypmod, context);
2373  }
2374  else
2375  {
2376  printRemotePlaceholder(node->vartype, node->vartypmod, context);
2377  }
2378  }
2379 }
Index varlevelsup
Definition: primnodes.h:174
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2986
List ** params_list
Definition: deparse.c:105
Definition: nodes.h:517
AttrNumber varattno
Definition: primnodes.h:169
static void printRemoteParam(int paramindex, Oid paramtype, int32 paramtypmod, deparse_expr_cxt *context)
Definition: deparse.c:3041
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define planner_rt_fetch(rti, root)
Definition: relation.h:344
#define SUBQUERY_COL_ALIAS_PREFIX
Definition: deparse.c:113
Oid vartype
Definition: primnodes.h:171
#define SUBQUERY_REL_ALIAS_PREFIX
Definition: deparse.c:112
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:671
Relids relids
Definition: relation.h:612
List * lappend(List *list, void *datum)
Definition: list.c:128
Index varno
Definition: primnodes.h:167
StringInfo buf
Definition: deparse.c:104
static bool is_subquery_var(Var *node, RelOptInfo *foreignrel, int *relno, int *colno)
Definition: deparse.c:3239
PlannerInfo * root
Definition: deparse.c:99
#define lfirst(lc)
Definition: pg_list.h:106
RelOptInfo * scanrel
Definition: deparse.c:101
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:486
static void deparseColumnRef(StringInfo buf, int varno, int varattno, RangeTblEntry *rte, bool qualify_col)
Definition: deparse.c:2053
static void printRemotePlaceholder(Oid paramtype, int32 paramtypmod, deparse_expr_cxt *context)
Definition: deparse.c:3067
int32 vartypmod
Definition: primnodes.h:172

◆ foreign_expr_walker()

static bool foreign_expr_walker ( Node node,
foreign_glob_cxt glob_cxt,
foreign_loc_cxt outer_cxt 
)
static

Definition at line 294 of file deparse.c.

References Aggref::aggcollid, Aggref::aggfilter, Aggref::aggfnoid, Aggref::aggorder, Aggref::aggsplit, AGGSPLIT_SIMPLE, RelabelType::arg, NullTest::arg, Aggref::args, FuncExpr::args, OpExpr::args, ScalarArrayOpExpr::args, BoolExpr::args, ArrayExpr::array_collid, bms_is_member(), foreign_loc_cxt::collation, Const::constcollid, ArrayExpr::elements, TargetEntry::expr, exprType(), FDW_COLLATE_NONE, FDW_COLLATE_SAFE, FDW_COLLATE_UNSAFE, RelOptInfo::fdw_private, fe(), foreign_glob_cxt::foreignrel, FuncExpr::funccollid, FuncExpr::funcid, get_sortgroupref_tle(), TypeCacheEntry::gt_opr, Aggref::inputcollid, FuncExpr::inputcollid, OpExpr::inputcollid, ScalarArrayOpExpr::inputcollid, InvalidOid, is_shippable(), IS_UPPER_REL, IsA, lfirst, lookup_type_cache(), TypeCacheEntry::lt_opr, nodeTag, ObjectIdAttributeNumber, OidIsValid, OpExpr::opcollid, OpExpr::opno, ScalarArrayOpExpr::opno, Param::paramcollid, ArrayRef::refassgnexpr, ArrayRef::refcollid, ArrayRef::refexpr, ArrayRef::reflowerindexpr, ArrayRef::refupperindexpr, foreign_glob_cxt::relids, RelabelType::resultcollid, SelfItemPointerAttributeNumber, SortGroupClause::sortop, foreign_loc_cxt::state, T_Aggref, T_ArrayExpr, T_ArrayRef, T_BoolExpr, T_Const, T_DistinctExpr, T_FuncExpr, T_List, T_NullTest, T_OpExpr, T_Param, T_RelabelType, T_ScalarArrayOpExpr, T_Var, SortGroupClause::tleSortGroupRef, TYPECACHE_GT_OPR, TYPECACHE_LT_OPR, Var::varattno, Var::varcollid, Var::varlevelsup, and Var::varno.

Referenced by is_foreign_expr().

297 {
298  bool check_type = true;
299  PgFdwRelationInfo *fpinfo;
300  foreign_loc_cxt inner_cxt;
301  Oid collation;
303 
304  /* Need do nothing for empty subexpressions */
305  if (node == NULL)
306  return true;
307 
308  /* May need server info from baserel's fdw_private struct */
309  fpinfo = (PgFdwRelationInfo *) (glob_cxt->foreignrel->fdw_private);
310 
311  /* Set up inner_cxt for possible recursion to child nodes */
312  inner_cxt.collation = InvalidOid;
313  inner_cxt.state = FDW_COLLATE_NONE;
314 
315  switch (nodeTag(node))
316  {
317  case T_Var:
318  {
319  Var *var = (Var *) node;
320 
321  /*
322  * If the Var is from the foreign table, we consider its
323  * collation (if any) safe to use. If it is from another
324  * table, we treat its collation the same way as we would a
325  * Param's collation, ie it's not safe for it to have a
326  * non-default collation.
327  */
328  if (bms_is_member(var->varno, glob_cxt->relids) &&
329  var->varlevelsup == 0)
330  {
331  /* Var belongs to foreign table */
332 
333  /*
334  * System columns other than ctid and oid should not be
335  * sent to the remote, since we don't make any effort to
336  * ensure that local and remote values match (tableoid, in
337  * particular, almost certainly doesn't match).
338  */
339  if (var->varattno < 0 &&
342  return false;
343 
344  /* Else check the collation */
345  collation = var->varcollid;
346  state = OidIsValid(collation) ? FDW_COLLATE_SAFE : FDW_COLLATE_NONE;
347  }
348  else
349  {
350  /* Var belongs to some other table */
351  collation = var->varcollid;
352  if (collation == InvalidOid ||
353  collation == DEFAULT_COLLATION_OID)
354  {
355  /*
356  * It's noncollatable, or it's safe to combine with a
357  * collatable foreign Var, so set state to NONE.
358  */
359  state = FDW_COLLATE_NONE;
360  }
361  else
362  {
363  /*
364  * Do not fail right away, since the Var might appear
365  * in a collation-insensitive context.
366  */
367  state = FDW_COLLATE_UNSAFE;
368  }
369  }
370  }
371  break;
372  case T_Const:
373  {
374  Const *c = (Const *) node;
375 
376  /*
377  * If the constant has nondefault collation, either it's of a
378  * non-builtin type, or it reflects folding of a CollateExpr.
379  * It's unsafe to send to the remote unless it's used in a
380  * non-collation-sensitive context.
381  */
382  collation = c->constcollid;
383  if (collation == InvalidOid ||
384  collation == DEFAULT_COLLATION_OID)
385  state = FDW_COLLATE_NONE;
386  else
387  state = FDW_COLLATE_UNSAFE;
388  }
389  break;
390  case T_Param:
391  {
392  Param *p = (Param *) node;
393 
394  /*
395  * Collation rule is same as for Consts and non-foreign Vars.
396  */
397  collation = p->paramcollid;
398  if (collation == InvalidOid ||
399  collation == DEFAULT_COLLATION_OID)
400  state = FDW_COLLATE_NONE;
401  else
402  state = FDW_COLLATE_UNSAFE;
403  }
404  break;
405  case T_ArrayRef:
406  {
407  ArrayRef *ar = (ArrayRef *) node;
408 
409  /* Assignment should not be in restrictions. */
410  if (ar->refassgnexpr != NULL)
411  return false;
412 
413  /*
414  * Recurse to remaining subexpressions. Since the array
415  * subscripts must yield (noncollatable) integers, they won't
416  * affect the inner_cxt state.
417  */
419  glob_cxt, &inner_cxt))
420  return false;
422  glob_cxt, &inner_cxt))
423  return false;
424  if (!foreign_expr_walker((Node *) ar->refexpr,
425  glob_cxt, &inner_cxt))
426  return false;
427 
428  /*
429  * Array subscripting should yield same collation as input,
430  * but for safety use same logic as for function nodes.
431  */
432  collation = ar->refcollid;
433  if (collation == InvalidOid)
434  state = FDW_COLLATE_NONE;
435  else if (inner_cxt.state == FDW_COLLATE_SAFE &&
436  collation == inner_cxt.collation)
437  state = FDW_COLLATE_SAFE;
438  else if (collation == DEFAULT_COLLATION_OID)
439  state = FDW_COLLATE_NONE;
440  else
441  state = FDW_COLLATE_UNSAFE;
442  }
443  break;
444  case T_FuncExpr:
445  {
446  FuncExpr *fe = (FuncExpr *) node;
447 
448  /*
449  * If function used by the expression is not shippable, it
450  * can't be sent to remote because it might have incompatible
451  * semantics on remote side.
452  */
453  if (!is_shippable(fe->funcid, ProcedureRelationId, fpinfo))
454  return false;
455 
456  /*
457  * Recurse to input subexpressions.
458  */
459  if (!foreign_expr_walker((Node *) fe->args,
460  glob_cxt, &inner_cxt))
461  return false;
462 
463  /*
464  * If function's input collation is not derived from a foreign
465  * Var, it can't be sent to remote.
466  */
467  if (fe->inputcollid == InvalidOid)
468  /* OK, inputs are all noncollatable */ ;
469  else if (inner_cxt.state != FDW_COLLATE_SAFE ||
470  fe->inputcollid != inner_cxt.collation)
471  return false;
472 
473  /*
474  * Detect whether node is introducing a collation not derived
475  * from a foreign Var. (If so, we just mark it unsafe for now
476  * rather than immediately returning false, since the parent
477  * node might not care.)
478  */
479  collation = fe->funccollid;
480  if (collation == InvalidOid)
481  state = FDW_COLLATE_NONE;
482  else if (inner_cxt.state == FDW_COLLATE_SAFE &&
483  collation == inner_cxt.collation)
484  state = FDW_COLLATE_SAFE;
485  else if (collation == DEFAULT_COLLATION_OID)
486  state = FDW_COLLATE_NONE;
487  else
488  state = FDW_COLLATE_UNSAFE;
489  }
490  break;
491  case T_OpExpr:
492  case T_DistinctExpr: /* struct-equivalent to OpExpr */
493  {
494  OpExpr *oe = (OpExpr *) node;
495 
496  /*
497  * Similarly, only shippable operators can be sent to remote.
498  * (If the operator is shippable, we assume its underlying
499  * function is too.)
500  */
501  if (!is_shippable(oe->opno, OperatorRelationId, fpinfo))
502  return false;
503 
504  /*
505  * Recurse to input subexpressions.
506  */
507  if (!foreign_expr_walker((Node *) oe->args,
508  glob_cxt, &inner_cxt))
509  return false;
510 
511  /*
512  * If operator's input collation is not derived from a foreign
513  * Var, it can't be sent to remote.
514  */
515  if (oe->inputcollid == InvalidOid)
516  /* OK, inputs are all noncollatable */ ;
517  else if (inner_cxt.state != FDW_COLLATE_SAFE ||
518  oe->inputcollid != inner_cxt.collation)
519  return false;
520 
521  /* Result-collation handling is same as for functions */
522  collation = oe->opcollid;
523  if (collation == InvalidOid)
524  state = FDW_COLLATE_NONE;
525  else if (inner_cxt.state == FDW_COLLATE_SAFE &&
526  collation == inner_cxt.collation)
527  state = FDW_COLLATE_SAFE;
528  else if (collation == DEFAULT_COLLATION_OID)
529  state = FDW_COLLATE_NONE;
530  else
531  state = FDW_COLLATE_UNSAFE;
532  }
533  break;
534  case T_ScalarArrayOpExpr:
535  {
536  ScalarArrayOpExpr *oe = (ScalarArrayOpExpr *) node;
537 
538  /*
539  * Again, only shippable operators can be sent to remote.
540  */
541  if (!is_shippable(oe->opno, OperatorRelationId, fpinfo))
542  return false;
543 
544  /*
545  * Recurse to input subexpressions.
546  */
547  if (!foreign_expr_walker((Node *) oe->args,
548  glob_cxt, &inner_cxt))
549  return false;
550 
551  /*
552  * If operator's input collation is not derived from a foreign
553  * Var, it can't be sent to remote.
554  */
555  if (oe->inputcollid == InvalidOid)
556  /* OK, inputs are all noncollatable */ ;
557  else if (inner_cxt.state != FDW_COLLATE_SAFE ||
558  oe->inputcollid != inner_cxt.collation)
559  return false;
560 
561  /* Output is always boolean and so noncollatable. */
562  collation = InvalidOid;
563  state = FDW_COLLATE_NONE;
564  }
565  break;
566  case T_RelabelType:
567  {
568  RelabelType *r = (RelabelType *) node;
569 
570  /*
571  * Recurse to input subexpression.
572  */
573  if (!foreign_expr_walker((Node *) r->arg,
574  glob_cxt, &inner_cxt))
575  return false;
576 
577  /*
578  * RelabelType must not introduce a collation not derived from
579  * an input foreign Var (same logic as for a real function).
580  */
581  collation = r->resultcollid;
582  if (collation == InvalidOid)
583  state = FDW_COLLATE_NONE;
584  else if (inner_cxt.state == FDW_COLLATE_SAFE &&
585  collation == inner_cxt.collation)
586  state = FDW_COLLATE_SAFE;
587  else if (collation == DEFAULT_COLLATION_OID)
588  state = FDW_COLLATE_NONE;
589  else
590  state = FDW_COLLATE_UNSAFE;
591  }
592  break;
593  case T_BoolExpr:
594  {
595  BoolExpr *b = (BoolExpr *) node;
596 
597  /*
598  * Recurse to input subexpressions.
599  */
600  if (!foreign_expr_walker((Node *) b->args,
601  glob_cxt, &inner_cxt))
602  return false;
603 
604  /* Output is always boolean and so noncollatable. */
605  collation = InvalidOid;
606  state = FDW_COLLATE_NONE;
607  }
608  break;
609  case T_NullTest:
610  {
611  NullTest *nt = (NullTest *) node;
612 
613  /*
614  * Recurse to input subexpressions.
615  */
616  if (!foreign_expr_walker((Node *) nt->arg,
617  glob_cxt, &inner_cxt))
618  return false;
619 
620  /* Output is always boolean and so noncollatable. */
621  collation = InvalidOid;
622  state = FDW_COLLATE_NONE;
623  }
624  break;
625  case T_ArrayExpr:
626  {
627  ArrayExpr *a = (ArrayExpr *) node;
628 
629  /*
630  * Recurse to input subexpressions.
631  */
632  if (!foreign_expr_walker((Node *) a->elements,
633  glob_cxt, &inner_cxt))
634  return false;
635 
636  /*
637  * ArrayExpr must not introduce a collation not derived from
638  * an input foreign Var (same logic as for a function).
639  */
640  collation = a->array_collid;
641  if (collation == InvalidOid)
642  state = FDW_COLLATE_NONE;
643  else if (inner_cxt.state == FDW_COLLATE_SAFE &&
644  collation == inner_cxt.collation)
645  state = FDW_COLLATE_SAFE;
646  else if (collation == DEFAULT_COLLATION_OID)
647  state = FDW_COLLATE_NONE;
648  else
649  state = FDW_COLLATE_UNSAFE;
650  }
651  break;
652  case T_List:
653  {
654  List *l = (List *) node;
655  ListCell *lc;
656 
657  /*
658  * Recurse to component subexpressions.
659  */
660  foreach(lc, l)
661  {
662  if (!foreign_expr_walker((Node *) lfirst(lc),
663  glob_cxt, &inner_cxt))
664  return false;
665  }
666 
667  /*
668  * When processing a list, collation state just bubbles up
669  * from the list elements.
670  */
671  collation = inner_cxt.collation;
672  state = inner_cxt.state;
673 
674  /* Don't apply exprType() to the list. */
675  check_type = false;
676  }
677  break;
678  case T_Aggref:
679  {
680  Aggref *agg = (Aggref *) node;
681  ListCell *lc;
682 
683  /* Not safe to pushdown when not in grouping context */
684  if (!IS_UPPER_REL(glob_cxt->foreignrel))
685  return false;
686 
687  /* Only non-split aggregates are pushable. */
688  if (agg->aggsplit != AGGSPLIT_SIMPLE)
689  return false;
690 
691  /* As usual, it must be shippable. */
692  if (!is_shippable(agg->aggfnoid, ProcedureRelationId, fpinfo))
693  return false;
694 
695  /*
696  * Recurse to input args. aggdirectargs, aggorder and
697  * aggdistinct are all present in args, so no need to check
698  * their shippability explicitly.
699  */
700  foreach(lc, agg->args)
701  {
702  Node *n = (Node *) lfirst(lc);
703 
704  /* If TargetEntry, extract the expression from it */
705  if (IsA(n, TargetEntry))
706  {
707  TargetEntry *tle = (TargetEntry *) n;
708 
709  n = (Node *) tle->expr;
710  }
711 
712  if (!foreign_expr_walker(n, glob_cxt, &inner_cxt))
713  return false;
714  }
715 
716  /*
717  * For aggorder elements, check whether the sort operator, if
718  * specified, is shippable or not.
719  */
720  if (agg->aggorder)
721  {
722  ListCell *lc;
723 
724  foreach(lc, agg->aggorder)
725  {
726  SortGroupClause *srt = (SortGroupClause *) lfirst(lc);
727  Oid sortcoltype;
728  TypeCacheEntry *typentry;
729  TargetEntry *tle;
730 
732  agg->args);
733  sortcoltype = exprType((Node *) tle->expr);
734  typentry = lookup_type_cache(sortcoltype,
736  /* Check shippability of non-default sort operator. */
737  if (srt->sortop != typentry->lt_opr &&
738  srt->sortop != typentry->gt_opr &&
739  !is_shippable(srt->sortop, OperatorRelationId,
740  fpinfo))
741  return false;
742  }
743  }
744 
745  /* Check aggregate filter */
746  if (!foreign_expr_walker((Node *) agg->aggfilter,
747  glob_cxt, &inner_cxt))
748  return false;
749 
750  /*
751  * If aggregate's input collation is not derived from a
752  * foreign Var, it can't be sent to remote.
753  */
754  if (agg->inputcollid == InvalidOid)
755  /* OK, inputs are all noncollatable */ ;
756  else if (inner_cxt.state != FDW_COLLATE_SAFE ||
757  agg->inputcollid != inner_cxt.collation)
758  return false;
759 
760  /*
761  * Detect whether node is introducing a collation not derived
762  * from a foreign Var. (If so, we just mark it unsafe for now
763  * rather than immediately returning false, since the parent
764  * node might not care.)
765  */
766  collation = agg->aggcollid;
767  if (collation == InvalidOid)
768  state = FDW_COLLATE_NONE;
769  else if (inner_cxt.state == FDW_COLLATE_SAFE &&
770  collation == inner_cxt.collation)
771  state = FDW_COLLATE_SAFE;
772  else if (collation == DEFAULT_COLLATION_OID)
773  state = FDW_COLLATE_NONE;
774  else
775  state = FDW_COLLATE_UNSAFE;
776  }
777  break;
778  default:
779 
780  /*
781  * If it's anything else, assume it's unsafe. This list can be
782  * expanded later, but don't forget to add deparse support below.
783  */
784  return false;
785  }
786 
787  /*
788  * If result type of given expression is not shippable, it can't be sent
789  * to remote because it might have incompatible semantics on remote side.
790  */
791  if (check_type && !is_shippable(exprType(node), TypeRelationId, fpinfo))
792  return false;
793 
794  /*
795  * Now, merge my collation information into my parent's state.
796  */
797  if (state > outer_cxt->state)
798  {
799  /* Override previous parent state */
800  outer_cxt->collation = collation;
801  outer_cxt->state = state;
802  }
803  else if (state == outer_cxt->state)
804  {
805  /* Merge, or detect error if there's a collation conflict */
806  switch (state)
807  {
808  case FDW_COLLATE_NONE:
809  /* Nothing + nothing is still nothing */
810  break;
811  case FDW_COLLATE_SAFE:
812  if (collation != outer_cxt->collation)
813  {
814  /*
815  * Non-default collation always beats default.
816  */
817  if (outer_cxt->collation == DEFAULT_COLLATION_OID)
818  {
819  /* Override previous parent state */
820  outer_cxt->collation = collation;
821  }
822  else if (collation != DEFAULT_COLLATION_OID)
823  {
824  /*
825  * Conflict; show state as indeterminate. We don't
826  * want to "return false" right away, since parent
827  * node might not care about collation.
828  */
829  outer_cxt->state = FDW_COLLATE_UNSAFE;
830  }
831  }
832  break;
833  case FDW_COLLATE_UNSAFE:
834  /* We're still conflicted ... */
835  break;
836  }
837  }
838 
839  /* It looks OK */
840  return true;
841 }
Expr * refassgnexpr
Definition: primnodes.h:411
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
Index varlevelsup
Definition: primnodes.h:174
List * args
Definition: primnodes.h:458
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
Oid funccollid
Definition: primnodes.h:456
FDWCollateState state
Definition: deparse.c:91
#define IS_UPPER_REL(rel)
Definition: relation.h:595
Index tleSortGroupRef
Definition: parsenodes.h:1207
Expr * arg
Definition: primnodes.h:795
Oid inputcollid
Definition: primnodes.h:298
Definition: nodes.h:517
List * args
Definition: primnodes.h:302
AttrNumber varattno
Definition: primnodes.h:169
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:164
bool is_shippable(Oid objectId, Oid classId, PgFdwRelationInfo *fpinfo)
Definition: shippable.c:165
#define OidIsValid(objectId)
Definition: c.h:605
FDWCollateState
Definition: deparse.c:78
Oid funcid
Definition: primnodes.h:450
Oid paramcollid
Definition: primnodes.h:249
Expr * arg
Definition: primnodes.h:1188
Oid constcollid
Definition: primnodes.h:195
Relids relids
Definition: deparse.c:70
char * c
List * refupperindexpr
Definition: primnodes.h:404
List * reflowerindexpr
Definition: primnodes.h:406
List * aggorder
Definition: primnodes.h:303
RelOptInfo * foreignrel
Definition: deparse.c:69
List * elements
Definition: primnodes.h:960
#define TYPECACHE_GT_OPR
Definition: typcache.h:129
static bool foreign_expr_walker(Node *node, foreign_glob_cxt *glob_cxt, foreign_loc_cxt *outer_cxt)
Definition: deparse.c:294
Oid opcollid
Definition: primnodes.h:501
TargetEntry * get_sortgroupref_tle(Index sortref, List *targetList)
Definition: tlist.c:348
Definition: nodes.h:296
Definition: nodes.h:148
Index varno
Definition: primnodes.h:167
Definition: nodes.h:147
Oid resultcollid
Definition: primnodes.h:798
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:321
#define InvalidOid
Definition: postgres_ext.h:36
Oid aggfnoid
Definition: primnodes.h:295
void * fdw_private
Definition: relation.h:664
Oid inputcollid
Definition: primnodes.h:457
#define lfirst(lc)
Definition: pg_list.h:106
Definition: regguts.h:298
Expr * expr
Definition: primnodes.h:1376
AggSplit aggsplit
Definition: primnodes.h:311
Oid array_collid
Definition: primnodes.h:958
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
Oid refcollid
Definition: primnodes.h:403
Expr * aggfilter
Definition: primnodes.h:305
Oid inputcollid
Definition: primnodes.h:502
List * args
Definition: primnodes.h:564
#define nodeTag(nodeptr)
Definition: nodes.h:522
Oid aggcollid
Definition: primnodes.h:297
static int fe(enum e x)
Definition: preproc-init.c:111
#define TYPECACHE_LT_OPR
Definition: typcache.h:128
Oid varcollid
Definition: primnodes.h:173
Oid opno
Definition: primnodes.h:497
#define SelfItemPointerAttributeNumber
Definition: sysattr.h:21
List * args
Definition: primnodes.h:503
Definition: pg_list.h:45
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:486
Expr * refexpr
Definition: primnodes.h:409
Definition: nodes.h:149

◆ get_jointype_name()

const char* get_jointype_name ( JoinType  jointype)

Definition at line 1317 of file deparse.c.

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

Referenced by deparseFromExprForRel(), and foreign_join_ok().

1318 {
1319  switch (jointype)
1320  {
1321  case JOIN_INNER:
1322  return "INNER";
1323 
1324  case JOIN_LEFT:
1325  return "LEFT";
1326 
1327  case JOIN_RIGHT:
1328  return "RIGHT";
1329 
1330  case JOIN_FULL:
1331  return "FULL";
1332 
1333  default:
1334  /* Shouldn't come here, but protect from buggy code. */
1335  elog(ERROR, "unsupported join type %d", jointype);
1336  }
1337 
1338  /* Keep compiler happy */
1339  return NULL;
1340 }
#define ERROR
Definition: elog.h:43
#define elog
Definition: elog.h:219

◆ get_relation_column_alias_ids()

static void get_relation_column_alias_ids ( Var node,
RelOptInfo foreignrel,
int *  relno,
int *  colno 
)
static

Definition at line 3301 of file deparse.c.

References elog, equal(), ERROR, PathTarget::exprs, RelOptInfo::fdw_private, i, lfirst, PgFdwRelationInfo::relation_index, and RelOptInfo::reltarget.

Referenced by is_subquery_var().

3303 {
3304  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
3305  int i;
3306  ListCell *lc;
3307 
3308  /* Get the relation alias ID */
3309  *relno = fpinfo->relation_index;
3310 
3311  /* Get the column alias ID */
3312  i = 1;
3313  foreach(lc, foreignrel->reltarget->exprs)
3314  {
3315  if (equal(lfirst(lc), (Node *) node))
3316  {
3317  *colno = i;
3318  return;
3319  }
3320  i++;
3321  }
3322 
3323  /* Shouldn't get here */
3324  elog(ERROR, "unexpected expression in subquery output");
3325 }
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2986
Definition: nodes.h:517
#define ERROR
Definition: elog.h:43
List * exprs
Definition: relation.h:1008
void * fdw_private
Definition: relation.h:664
#define lfirst(lc)
Definition: pg_list.h:106
int i
#define elog
Definition: elog.h:219
struct PathTarget * reltarget
Definition: relation.h:623

◆ is_foreign_expr()

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

Definition at line 230 of file deparse.c.

References foreign_loc_cxt::collation, contain_mutable_functions(), FDW_COLLATE_NONE, FDW_COLLATE_UNSAFE, RelOptInfo::fdw_private, foreign_expr_walker(), foreign_glob_cxt::foreignrel, InvalidOid, IS_UPPER_REL, PgFdwRelationInfo::outerrel, foreign_glob_cxt::relids, RelOptInfo::relids, foreign_glob_cxt::root, and foreign_loc_cxt::state.

Referenced by classifyConditions(), foreign_grouping_ok(), foreign_join_ok(), get_useful_pathkeys_for_relation(), postgresGetForeignPaths(), postgresGetForeignPlan(), and postgresPlanDirectModify().

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

◆ is_subquery_var()

static bool is_subquery_var ( Var node,
RelOptInfo foreignrel,
int *  relno,
int *  colno 
)
static

Definition at line 3239 of file deparse.c.

References Assert, bms_is_member(), RelOptInfo::fdw_private, get_relation_column_alias_ids(), PgFdwRelationInfo::innerrel, IS_JOIN_REL, IS_SIMPLE_REL, PgFdwRelationInfo::lower_subquery_rels, PgFdwRelationInfo::make_innerrel_subquery, PgFdwRelationInfo::make_outerrel_subquery, PgFdwRelationInfo::outerrel, and Var::varno.

Referenced by deparseVar().

3240 {
3241  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
3242  RelOptInfo *outerrel = fpinfo->outerrel;
3243  RelOptInfo *innerrel = fpinfo->innerrel;
3244 
3245  /* Should only be called in these cases. */
3246  Assert(IS_SIMPLE_REL(foreignrel) || IS_JOIN_REL(foreignrel));
3247 
3248  /*
3249  * If the given relation isn't a join relation, it doesn't have any lower
3250  * subqueries, so the Var isn't a subquery output column.
3251  */
3252  if (!IS_JOIN_REL(foreignrel))
3253  return false;
3254 
3255  /*
3256  * If the Var doesn't belong to any lower subqueries, it isn't a subquery
3257  * output column.
3258  */
3259  if (!bms_is_member(node->varno, fpinfo->lower_subquery_rels))
3260  return false;
3261 
3262  if (bms_is_member(node->varno, outerrel->relids))
3263  {
3264  /*
3265  * If outer relation is deparsed as a subquery, the Var is an output
3266  * column of the subquery; get the IDs for the relation/column alias.
3267  */
3268  if (fpinfo->make_outerrel_subquery)
3269  {
3270  get_relation_column_alias_ids(node, outerrel, relno, colno);
3271  return true;
3272  }
3273 
3274  /* Otherwise, recurse into the outer relation. */
3275  return is_subquery_var(node, outerrel, relno, colno);
3276  }
3277  else
3278  {
3279  Assert(bms_is_member(node->varno, innerrel->relids));
3280 
3281  /*
3282  * If inner relation is deparsed as a subquery, the Var is an output
3283  * column of the subquery; get the IDs for the relation/column alias.
3284  */
3285  if (fpinfo->make_innerrel_subquery)
3286  {
3287  get_relation_column_alias_ids(node, innerrel, relno, colno);
3288  return true;
3289  }
3290 
3291  /* Otherwise, recurse into the inner relation. */
3292  return is_subquery_var(node, innerrel, relno, colno);
3293  }
3294 }
#define IS_JOIN_REL(rel)
Definition: relation.h:590
Relids lower_subquery_rels
Definition: postgres_fdw.h:103
RelOptInfo * outerrel
Definition: postgres_fdw.h:89
#define IS_SIMPLE_REL(rel)
Definition: relation.h:585
bool make_outerrel_subquery
Definition: postgres_fdw.h:99
Index varno
Definition: primnodes.h:167
static bool is_subquery_var(Var *node, RelOptInfo *foreignrel, int *relno, int *colno)
Definition: deparse.c:3239
void * fdw_private
Definition: relation.h:664
static void get_relation_column_alias_ids(Var *node, RelOptInfo *foreignrel, int *relno, int *colno)
Definition: deparse.c:3301
#define Assert(condition)
Definition: c.h:699
RelOptInfo * innerrel
Definition: postgres_fdw.h:90
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:486

◆ printRemoteParam()

static void printRemoteParam ( int  paramindex,
Oid  paramtype,
int32  paramtypmod,
deparse_expr_cxt context 
)
static

Definition at line 3041 of file deparse.c.

References appendStringInfo(), buf, deparse_expr_cxt::buf, and deparse_type_name().

Referenced by deparseParam(), and deparseVar().

3043 {
3044  StringInfo buf = context->buf;
3045  char *ptypename = deparse_type_name(paramtype, paramtypmod);
3046 
3047  appendStringInfo(buf, "$%d::%s", paramindex, ptypename);
3048 }
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
static char * buf
Definition: pg_test_fsync.c:67
StringInfo buf
Definition: deparse.c:104
static char * deparse_type_name(Oid type_oid, int32 typemod)
Definition: deparse.c:855

◆ printRemotePlaceholder()

static void printRemotePlaceholder ( Oid  paramtype,
int32  paramtypmod,
deparse_expr_cxt context 
)
static

Definition at line 3067 of file deparse.c.

References appendStringInfo(), buf, deparse_expr_cxt::buf, and deparse_type_name().

Referenced by deparseParam(), and deparseVar().

3069 {
3070  StringInfo buf = context->buf;
3071  char *ptypename = deparse_type_name(paramtype, paramtypmod);
3072 
3073  appendStringInfo(buf, "((SELECT null::%s)::%s)", ptypename, ptypename);
3074 }
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
static char * buf
Definition: pg_test_fsync.c:67
StringInfo buf
Definition: deparse.c:104
static char * deparse_type_name(Oid type_oid, int32 typemod)
Definition: deparse.c:855