PostgreSQL Source Code  git master
deparse.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * deparse.c
4  * Query deparser for postgres_fdw
5  *
6  * This file includes functions that examine query WHERE clauses to see
7  * whether they're safe to send to the remote server for execution, as
8  * well as functions to construct the query text to be sent. The latter
9  * functionality is annoyingly duplicative of ruleutils.c, but there are
10  * enough special considerations that it seems best to keep this separate.
11  * One saving grace is that we only need deparse logic for node types that
12  * we consider safe to send.
13  *
14  * We assume that the remote session's search_path is exactly "pg_catalog",
15  * and thus we need schema-qualify all and only names outside pg_catalog.
16  *
17  * We do not consider that it is ever safe to send COLLATE expressions to
18  * the remote server: it might not have the same collation names we do.
19  * (Later we might consider it safe to send COLLATE "C", but even that would
20  * fail on old remote servers.) An expression is considered safe to send
21  * only if all operator/function input collations used in it are traceable to
22  * Var(s) of the foreign table. That implies that if the remote server gets
23  * a different answer than we do, the foreign table's columns are not marked
24  * with collations that match the remote table's columns, which we can
25  * consider to be user error.
26  *
27  * Portions Copyright (c) 2012-2018, PostgreSQL Global Development Group
28  *
29  * IDENTIFICATION
30  * contrib/postgres_fdw/deparse.c
31  *
32  *-------------------------------------------------------------------------
33  */
34 #include "postgres.h"
35 
36 #include "postgres_fdw.h"
37 
38 #include "access/heapam.h"
39 #include "access/htup_details.h"
40 #include "access/sysattr.h"
41 #include "catalog/pg_aggregate.h"
42 #include "catalog/pg_collation.h"
43 #include "catalog/pg_namespace.h"
44 #include "catalog/pg_operator.h"
45 #include "catalog/pg_proc.h"
46 #include "catalog/pg_type.h"
47 #include "commands/defrem.h"
48 #include "nodes/makefuncs.h"
49 #include "nodes/nodeFuncs.h"
50 #include "nodes/plannodes.h"
51 #include "optimizer/clauses.h"
52 #include "optimizer/prep.h"
53 #include "optimizer/tlist.h"
54 #include "optimizer/var.h"
55 #include "parser/parsetree.h"
56 #include "utils/builtins.h"
57 #include "utils/lsyscache.h"
58 #include "utils/rel.h"
59 #include "utils/syscache.h"
60 #include "utils/typcache.h"
61 
62 
63 /*
64  * Global context for foreign_expr_walker's search of an expression tree.
65  */
66 typedef struct foreign_glob_cxt
67 {
68  PlannerInfo *root; /* global planner state */
69  RelOptInfo *foreignrel; /* the foreign relation we are planning for */
70  Relids relids; /* relids of base relations in the underlying
71  * scan */
73 
74 /*
75  * Local (per-tree-level) context for foreign_expr_walker's search.
76  * This is concerned with identifying collations used in the expression.
77  */
78 typedef enum
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 */
87 
88 typedef struct foreign_loc_cxt
89 {
90  Oid collation; /* OID of current collation, if any */
91  FDWCollateState state; /* state of current collation choice */
93 
94 /*
95  * Context for deparseExpr
96  */
97 typedef struct deparse_expr_cxt
98 {
99  PlannerInfo *root; /* global planner state */
100  RelOptInfo *foreignrel; /* the foreign relation we are planning for */
101  RelOptInfo *scanrel; /* the underlying scan relation. Same as
102  * foreignrel, when that represents a join or
103  * a base relation. */
104  StringInfo buf; /* output buffer to append to */
105  List **params_list; /* exprs that will become remote Params */
107 
108 #define REL_ALIAS_PREFIX "r"
109 /* Handy macro to add relation name qualification */
110 #define ADD_REL_QUALIFIER(buf, varno) \
111  appendStringInfo((buf), "%s%d.", REL_ALIAS_PREFIX, (varno))
112 #define SUBQUERY_REL_ALIAS_PREFIX "s"
113 #define SUBQUERY_COL_ALIAS_PREFIX "c"
114 
115 /*
116  * Functions to determine whether an expression can be evaluated safely on
117  * remote server.
118  */
119 static bool foreign_expr_walker(Node *node,
120  foreign_glob_cxt *glob_cxt,
121  foreign_loc_cxt *outer_cxt);
122 static char *deparse_type_name(Oid type_oid, int32 typemod);
123 
124 /*
125  * Functions to construct string representation of a node tree.
126  */
127 static void deparseTargetList(StringInfo buf,
128  PlannerInfo *root,
129  Index rtindex,
130  Relation rel,
131  bool is_returning,
132  Bitmapset *attrs_used,
133  bool qualify_col,
134  List **retrieved_attrs);
135 static void deparseExplicitTargetList(List *tlist,
136  bool is_returning,
137  List **retrieved_attrs,
138  deparse_expr_cxt *context);
139 static void deparseSubqueryTargetList(deparse_expr_cxt *context);
141  Index rtindex, Relation rel,
142  bool trig_after_row,
143  List *returningList,
144  List **retrieved_attrs);
145 static void deparseColumnRef(StringInfo buf, int varno, int varattno,
146  PlannerInfo *root, bool qualify_col);
147 static void deparseRelation(StringInfo buf, Relation rel);
148 static void deparseExpr(Expr *expr, deparse_expr_cxt *context);
149 static void deparseVar(Var *node, deparse_expr_cxt *context);
150 static void deparseConst(Const *node, deparse_expr_cxt *context, int showtype);
151 static void deparseParam(Param *node, deparse_expr_cxt *context);
152 static void deparseArrayRef(ArrayRef *node, deparse_expr_cxt *context);
153 static void deparseFuncExpr(FuncExpr *node, deparse_expr_cxt *context);
154 static void deparseOpExpr(OpExpr *node, deparse_expr_cxt *context);
156 static void deparseDistinctExpr(DistinctExpr *node, deparse_expr_cxt *context);
158  deparse_expr_cxt *context);
159 static void deparseRelabelType(RelabelType *node, deparse_expr_cxt *context);
160 static void deparseBoolExpr(BoolExpr *node, deparse_expr_cxt *context);
161 static void deparseNullTest(NullTest *node, deparse_expr_cxt *context);
162 static void deparseArrayExpr(ArrayExpr *node, deparse_expr_cxt *context);
163 static void printRemoteParam(int paramindex, Oid paramtype, int32 paramtypmod,
164  deparse_expr_cxt *context);
165 static void printRemotePlaceholder(Oid paramtype, int32 paramtypmod,
166  deparse_expr_cxt *context);
167 static void deparseSelectSql(List *tlist, bool is_subquery, List **retrieved_attrs,
168  deparse_expr_cxt *context);
169 static void deparseLockingClause(deparse_expr_cxt *context);
170 static void appendOrderByClause(List *pathkeys, deparse_expr_cxt *context);
171 static void appendConditions(List *exprs, deparse_expr_cxt *context);
173  RelOptInfo *foreignrel, bool use_alias,
174  Index ignore_rel, List **ignore_conds,
175  List **params_list);
176 static void deparseFromExpr(List *quals, deparse_expr_cxt *context);
178  RelOptInfo *foreignrel, bool make_subquery,
179  Index ignore_rel, List **ignore_conds, List **params_list);
180 static void deparseAggref(Aggref *node, deparse_expr_cxt *context);
181 static void appendGroupByClause(List *tlist, deparse_expr_cxt *context);
182 static void appendAggOrderBy(List *orderList, List *targetList,
183  deparse_expr_cxt *context);
184 static void appendFunctionName(Oid funcid, deparse_expr_cxt *context);
185 static Node *deparseSortGroupClause(Index ref, List *tlist, bool force_colno,
186  deparse_expr_cxt *context);
187 
188 /*
189  * Helper functions
190  */
191 static bool is_subquery_var(Var *node, RelOptInfo *foreignrel,
192  int *relno, int *colno);
194  int *relno, int *colno);
195 
196 
197 /*
198  * Examine each qual clause in input_conds, and classify them into two groups,
199  * which are returned as two lists:
200  * - remote_conds contains expressions that can be evaluated remotely
201  * - local_conds contains expressions that can't be evaluated remotely
202  */
203 void
205  RelOptInfo *baserel,
206  List *input_conds,
207  List **remote_conds,
208  List **local_conds)
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 }
225 
226 /*
227  * Returns true if given expr is safe to evaluate on the foreign server.
228  */
229 bool
231  RelOptInfo *baserel,
232  Expr *expr)
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 }
279 
280 /*
281  * Check if expression is safe to execute remotely, and return true if so.
282  *
283  * In addition, *outer_cxt is updated with collation information.
284  *
285  * We must check that the expression contains only node types we can deparse,
286  * that all types/functions/operators are safe to send (they are "shippable"),
287  * and that all collations used in the expression derive from Vars of the
288  * foreign table. Because of the latter, the logic is pretty close to
289  * assign_collations_walker() in parse_collate.c, though we can assume here
290  * that the given expression is valid. Note function mutability is not
291  * currently considered here.
292  */
293 static bool
295  foreign_glob_cxt *glob_cxt,
296  foreign_loc_cxt *outer_cxt)
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 &&
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 }
842 
843 /*
844  * Convert type OID + typmod info into a type name we can ship to the remote
845  * server. Someplace else had better have verified that this type name is
846  * expected to be known on the remote end.
847  *
848  * This is almost just format_type_with_typemod(), except that if left to its
849  * own devices, that function will make schema-qualification decisions based
850  * on the local search_path, which is wrong. We must schema-qualify all
851  * type names that are not in pg_catalog. We assume here that built-in types
852  * are all in pg_catalog and need not be qualified; otherwise, qualify.
853  */
854 static char *
855 deparse_type_name(Oid type_oid, int32 typemod)
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 }
864 
865 /*
866  * Build the targetlist for given relation to be deparsed as SELECT clause.
867  *
868  * The output targetlist contains the columns that need to be fetched from the
869  * foreign server for the given relation. If foreignrel is an upper relation,
870  * then the output targetlist can also contain expressions to be evaluated on
871  * foreign server.
872  */
873 List *
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 }
905 
906 /*
907  * Deparse SELECT statement for given relation into buf.
908  *
909  * tlist contains the list of desired columns to be fetched from foreign server.
910  * For a base relation fpinfo->attrs_used is used to construct SELECT clause,
911  * hence the tlist is ignored for a base relation.
912  *
913  * remote_conds is the list of conditions to be deparsed into the WHERE clause
914  * (or, in the case of upper relations, into the HAVING clause).
915  *
916  * If params_list is not NULL, it receives a list of Params and other-relation
917  * Vars used in the clauses; these values must be transmitted to the remote
918  * server as parameter values.
919  *
920  * If params_list is NULL, we're generating the query for EXPLAIN purposes,
921  * so Params and other-relation Vars should be replaced by dummy values.
922  *
923  * pathkeys is the list of pathkeys to order the result by.
924  *
925  * is_subquery is the flag to indicate whether to deparse the specified
926  * relation as a subquery.
927  *
928  * List of columns selected is returned in retrieved_attrs.
929  */
930 void
932  List *tlist, List *remote_conds, List *pathkeys,
933  bool is_subquery, List **retrieved_attrs,
934  List **params_list)
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 }
994 
995 /*
996  * Construct a simple SELECT statement that retrieves desired columns
997  * of the specified foreign table, and append it to "buf". The output
998  * contains just "SELECT ... ".
999  *
1000  * We also create an integer List of the columns being retrieved, which is
1001  * returned to *retrieved_attrs, unless we deparse the specified relation
1002  * as a subquery.
1003  *
1004  * tlist is the list of desired columns. is_subquery is the flag to
1005  * indicate whether to deparse the specified relation as a subquery.
1006  * Read prologue of deparseSelectStmtForRel() for details.
1007  */
1008 static void
1009 deparseSelectSql(List *tlist, bool is_subquery, List **retrieved_attrs,
1010  deparse_expr_cxt *context)
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, root, foreignrel->relid, rel, false,
1054  fpinfo->attrs_used, false, retrieved_attrs);
1055  heap_close(rel, NoLock);
1056  }
1057 }
1058 
1059 /*
1060  * Construct a FROM clause and, if needed, a WHERE clause, and append those to
1061  * "buf".
1062  *
1063  * quals is the list of clauses to be included in the WHERE clause.
1064  * (These may or may not include RestrictInfo decoration.)
1065  */
1066 static void
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 }
1089 
1090 /*
1091  * Emit a target list that retrieves the columns specified in attrs_used.
1092  * This is used for both SELECT and RETURNING targetlists; the is_returning
1093  * parameter is true only for a RETURNING targetlist.
1094  *
1095  * The tlist text is appended to buf, and we also create an integer List
1096  * of the columns being retrieved, which is returned to *retrieved_attrs.
1097  *
1098  * If qualify_col is true, add relation alias before the column name.
1099  */
1100 static void
1102  PlannerInfo *root,
1103  Index rtindex,
1104  Relation rel,
1105  bool is_returning,
1106  Bitmapset *attrs_used,
1107  bool qualify_col,
1108  List **retrieved_attrs)
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, root, 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 }
1187 
1188 /*
1189  * Deparse the appropriate locking clause (FOR UPDATE or FOR SHARE) for a
1190  * given relation (context->scanrel).
1191  */
1192 static void
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 }
1272 
1273 /*
1274  * Deparse conditions from the provided list and append them to buf.
1275  *
1276  * The conditions in the list are assumed to be ANDed. This function is used to
1277  * deparse WHERE clauses, JOIN .. ON clauses and HAVING clauses.
1278  *
1279  * Depending on the caller, the list elements might be either RestrictInfos
1280  * or bare clauses.
1281  */
1282 static void
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 }
1314 
1315 /* Output join name for given join type */
1316 const char *
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 }
1341 
1342 /*
1343  * Deparse given targetlist and append it to context->buf.
1344  *
1345  * tlist is list of TargetEntry's which in turn contain Var nodes.
1346  *
1347  * retrieved_attrs is the list of continuously increasing integers starting
1348  * from 1. It has same number of entries as tlist.
1349  *
1350  * This is used for both SELECT and RETURNING targetlists; the is_returning
1351  * parameter is true only for a RETURNING targetlist.
1352  */
1353 static void
1355  bool is_returning,
1356  List **retrieved_attrs,
1357  deparse_expr_cxt *context)
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 }
1383 
1384 /*
1385  * Emit expressions specified in the given relation's reltarget.
1386  *
1387  * This is used for deparsing the given relation as a subquery.
1388  */
1389 static void
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 }
1416 
1417 /*
1418  * Construct FROM clause for given relation
1419  *
1420  * The function constructs ... JOIN ... ON ... for join relation. For a base
1421  * relation it just returns schema-qualified tablename, with the appropriate
1422  * alias if so requested.
1423  *
1424  * 'ignore_rel' is either zero or the RT index of a target relation. In the
1425  * latter case the function constructs FROM clause of UPDATE or USING clause
1426  * of DELETE; it deparses the join relation as if the relation never contained
1427  * the target relation, and creates a List of conditions to be deparsed into
1428  * the top-level WHERE clause, which is returned to *ignore_conds.
1429  */
1430 static void
1432  bool use_alias, Index ignore_rel, List **ignore_conds,
1433  List **params_list)
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 }
1577 
1578 /*
1579  * Append FROM clause entry for the given relation into buf.
1580  */
1581 static void
1583  bool make_subquery, Index ignore_rel, List **ignore_conds,
1584  List **params_list)
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 }
1643 
1644 /*
1645  * deparse remote INSERT statement
1646  *
1647  * The statement text is appended to buf, and we also create an integer List
1648  * of the columns being retrieved by RETURNING (if any), which is returned
1649  * to *retrieved_attrs.
1650  */
1651 void
1653  Index rtindex, Relation rel,
1654  List *targetAttrs, bool doNothing,
1655  List *returningList, List **retrieved_attrs)
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, root, 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, root, rtindex, rel,
1703  rel->trigdesc && rel->trigdesc->trig_insert_after_row,
1704  returningList, retrieved_attrs);
1705 }
1706 
1707 /*
1708  * deparse remote UPDATE statement
1709  *
1710  * The statement text is appended to buf, and we also create an integer List
1711  * of the columns being retrieved by RETURNING (if any), which is returned
1712  * to *retrieved_attrs.
1713  */
1714 void
1716  Index rtindex, Relation rel,
1717  List *targetAttrs, List *returningList,
1718  List **retrieved_attrs)
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, root, false);
1739  appendStringInfo(buf, " = $%d", pindex);
1740  pindex++;
1741  }
1742  appendStringInfoString(buf, " WHERE ctid = $1");
1743 
1744  deparseReturningList(buf, root, rtindex, rel,
1745  rel->trigdesc && rel->trigdesc->trig_update_after_row,
1746  returningList, retrieved_attrs);
1747 }
1748 
1749 /*
1750  * deparse remote UPDATE statement
1751  *
1752  * 'buf' is the output buffer to append the statement to
1753  * 'rtindex' is the RT index of the associated target relation
1754  * 'rel' is the relation descriptor for the target relation
1755  * 'foreignrel' is the RelOptInfo for the target relation or the join relation
1756  * containing all base relations in the query
1757  * 'targetlist' is the tlist of the underlying foreign-scan plan node
1758  * 'targetAttrs' is the target columns of the UPDATE
1759  * 'remote_conds' is the qual clauses that must be evaluated remotely
1760  * '*params_list' is an output list of exprs that will become remote Params
1761  * 'returningList' is the RETURNING targetlist
1762  * '*retrieved_attrs' is an output list of integers of columns being retrieved
1763  * by RETURNING (if any)
1764  */
1765 void
1767  Index rtindex, Relation rel,
1769  List *targetlist,
1770  List *targetAttrs,
1771  List *remote_conds,
1772  List **params_list,
1773  List *returningList,
1774  List **retrieved_attrs)
1775 {
1776  deparse_expr_cxt context;
1777  int nestlevel;
1778  bool first;
1779  ListCell *lc;
1780 
1781  /* Set up context struct for recursion */
1782  context.root = root;
1783  context.foreignrel = foreignrel;
1784  context.scanrel = foreignrel;
1785  context.buf = buf;
1786  context.params_list = params_list;
1787 
1788  appendStringInfoString(buf, "UPDATE ");
1789  deparseRelation(buf, rel);
1790  if (foreignrel->reloptkind == RELOPT_JOINREL)
1791  appendStringInfo(buf, " %s%d", REL_ALIAS_PREFIX, rtindex);
1792  appendStringInfoString(buf, " SET ");
1793 
1794  /* Make sure any constants in the exprs are printed portably */
1795  nestlevel = set_transmission_modes();
1796 
1797  first = true;
1798  foreach(lc, targetAttrs)
1799  {
1800  int attnum = lfirst_int(lc);
1801  TargetEntry *tle = get_tle_by_resno(targetlist, attnum);
1802 
1803  if (!tle)
1804  elog(ERROR, "attribute number %d not found in UPDATE targetlist",
1805  attnum);
1806 
1807  if (!first)
1808  appendStringInfoString(buf, ", ");
1809  first = false;
1810 
1811  deparseColumnRef(buf, rtindex, attnum, root, false);
1812  appendStringInfoString(buf, " = ");
1813  deparseExpr((Expr *) tle->expr, &context);
1814  }
1815 
1816  reset_transmission_modes(nestlevel);
1817 
1818  if (foreignrel->reloptkind == RELOPT_JOINREL)
1819  {
1820  List *ignore_conds = NIL;
1821 
1822  appendStringInfo(buf, " FROM ");
1823  deparseFromExprForRel(buf, root, foreignrel, true, rtindex,
1824  &ignore_conds, params_list);
1825  remote_conds = list_concat(remote_conds, ignore_conds);
1826  }
1827 
1828  if (remote_conds)
1829  {
1830  appendStringInfoString(buf, " WHERE ");
1831  appendConditions(remote_conds, &context);
1832  }
1833 
1834  if (foreignrel->reloptkind == RELOPT_JOINREL)
1835  deparseExplicitTargetList(returningList, true, retrieved_attrs,
1836  &context);
1837  else
1838  deparseReturningList(buf, root, rtindex, rel, false,
1839  returningList, retrieved_attrs);
1840 }
1841 
1842 /*
1843  * deparse remote DELETE statement
1844  *
1845  * The statement text is appended to buf, and we also create an integer List
1846  * of the columns being retrieved by RETURNING (if any), which is returned
1847  * to *retrieved_attrs.
1848  */
1849 void
1851  Index rtindex, Relation rel,
1852  List *returningList,
1853  List **retrieved_attrs)
1854 {
1855  appendStringInfoString(buf, "DELETE FROM ");
1856  deparseRelation(buf, rel);
1857  appendStringInfoString(buf, " WHERE ctid = $1");
1858 
1859  deparseReturningList(buf, root, rtindex, rel,
1860  rel->trigdesc && rel->trigdesc->trig_delete_after_row,
1861  returningList, retrieved_attrs);
1862 }
1863 
1864 /*
1865  * deparse remote DELETE statement
1866  *
1867  * 'buf' is the output buffer to append the statement to
1868  * 'rtindex' is the RT index of the associated target relation
1869  * 'rel' is the relation descriptor for the target relation
1870  * 'foreignrel' is the RelOptInfo for the target relation or the join relation
1871  * containing all base relations in the query
1872  * 'remote_conds' is the qual clauses that must be evaluated remotely
1873  * '*params_list' is an output list of exprs that will become remote Params
1874  * 'returningList' is the RETURNING targetlist
1875  * '*retrieved_attrs' is an output list of integers of columns being retrieved
1876  * by RETURNING (if any)
1877  */
1878 void
1880  Index rtindex, Relation rel,
1882  List *remote_conds,
1883  List **params_list,
1884  List *returningList,
1885  List **retrieved_attrs)
1886 {
1887  deparse_expr_cxt context;
1888 
1889  /* Set up context struct for recursion */
1890  context.root = root;
1891  context.foreignrel = foreignrel;
1892  context.scanrel = foreignrel;
1893  context.buf = buf;
1894  context.params_list = params_list;
1895 
1896  appendStringInfoString(buf, "DELETE FROM ");
1897  deparseRelation(buf, rel);
1898  if (foreignrel->reloptkind == RELOPT_JOINREL)
1899  appendStringInfo(buf, " %s%d", REL_ALIAS_PREFIX, rtindex);
1900 
1901  if (foreignrel->reloptkind == RELOPT_JOINREL)
1902  {
1903  List *ignore_conds = NIL;
1904 
1905  appendStringInfo(buf, " USING ");
1906  deparseFromExprForRel(buf, root, foreignrel, true, rtindex,
1907  &ignore_conds, params_list);
1908  remote_conds = list_concat(remote_conds, ignore_conds);
1909  }
1910 
1911  if (remote_conds)
1912  {
1913  appendStringInfoString(buf, " WHERE ");
1914  appendConditions(remote_conds, &context);
1915  }
1916 
1917  if (foreignrel->reloptkind == RELOPT_JOINREL)
1918  deparseExplicitTargetList(returningList, true, retrieved_attrs,
1919  &context);
1920  else
1921  deparseReturningList(buf, root, rtindex, rel, false,
1922  returningList, retrieved_attrs);
1923 }
1924 
1925 /*
1926  * Add a RETURNING clause, if needed, to an INSERT/UPDATE/DELETE.
1927  */
1928 static void
1930  Index rtindex, Relation rel,
1931  bool trig_after_row,
1932  List *returningList,
1933  List **retrieved_attrs)
1934 {
1935  Bitmapset *attrs_used = NULL;
1936 
1937  if (trig_after_row)
1938  {
1939  /* whole-row reference acquires all non-system columns */
1940  attrs_used =
1942  }
1943 
1944  if (returningList != NIL)
1945  {
1946  /*
1947  * We need the attrs, non-system and system, mentioned in the local
1948  * query's RETURNING list.
1949  */
1950  pull_varattnos((Node *) returningList, rtindex,
1951  &attrs_used);
1952  }
1953 
1954  if (attrs_used != NULL)
1955  deparseTargetList(buf, root, rtindex, rel, true, attrs_used, false,
1956  retrieved_attrs);
1957  else
1958  *retrieved_attrs = NIL;
1959 }
1960 
1961 /*
1962  * Construct SELECT statement to acquire size in blocks of given relation.
1963  *
1964  * Note: we use local definition of block size, not remote definition.
1965  * This is perhaps debatable.
1966  *
1967  * Note: pg_relation_size() exists in 8.1 and later.
1968  */
1969 void
1971 {
1972  StringInfoData relname;
1973 
1974  /* We'll need the remote relation name as a literal. */
1975  initStringInfo(&relname);
1976  deparseRelation(&relname, rel);
1977 
1978  appendStringInfoString(buf, "SELECT pg_catalog.pg_relation_size(");
1979  deparseStringLiteral(buf, relname.data);
1980  appendStringInfo(buf, "::pg_catalog.regclass) / %d", BLCKSZ);
1981 }
1982 
1983 /*
1984  * Construct SELECT statement to acquire sample rows of given relation.
1985  *
1986  * SELECT command is appended to buf, and list of columns retrieved
1987  * is returned to *retrieved_attrs.
1988  */
1989 void
1991 {
1992  Oid relid = RelationGetRelid(rel);
1993  TupleDesc tupdesc = RelationGetDescr(rel);
1994  int i;
1995  char *colname;
1996  List *options;
1997  ListCell *lc;
1998  bool first = true;
1999 
2000  *retrieved_attrs = NIL;
2001 
2002  appendStringInfoString(buf, "SELECT ");
2003  for (i = 0; i < tupdesc->natts; i++)
2004  {
2005  /* Ignore dropped columns. */
2006  if (TupleDescAttr(tupdesc, i)->attisdropped)
2007  continue;
2008 
2009  if (!first)
2010  appendStringInfoString(buf, ", ");
2011  first = false;
2012 
2013  /* Use attribute name or column_name option. */
2014  colname = NameStr(TupleDescAttr(tupdesc, i)->attname);
2015  options = GetForeignColumnOptions(relid, i + 1);
2016 
2017  foreach(lc, options)
2018  {
2019  DefElem *def = (DefElem *) lfirst(lc);
2020 
2021  if (strcmp(def->defname, "column_name") == 0)
2022  {
2023  colname = defGetString(def);
2024  break;
2025  }
2026  }
2027 
2029 
2030  *retrieved_attrs = lappend_int(*retrieved_attrs, i + 1);
2031  }
2032 
2033  /* Don't generate bad syntax for zero-column relation. */
2034  if (first)
2035  appendStringInfoString(buf, "NULL");
2036 
2037  /*
2038  * Construct FROM clause
2039  */
2040  appendStringInfoString(buf, " FROM ");
2041  deparseRelation(buf, rel);
2042 }
2043 
2044 /*
2045  * Construct name to use for given column, and emit it into buf.
2046  * If it has a column_name FDW option, use that instead of attribute name.
2047  *
2048  * If qualify_col is true, qualify column name with the alias of relation.
2049  */
2050 static void
2051 deparseColumnRef(StringInfo buf, int varno, int varattno, PlannerInfo *root,
2052  bool qualify_col)
2053 {
2054  RangeTblEntry *rte;
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  {
2081  rte = planner_rt_fetch(varno, root);
2082  fetchval = rte->relid;
2083  }
2084 
2085  if (qualify_col)
2086  {
2087  appendStringInfoString(buf, "CASE WHEN (");
2088  ADD_REL_QUALIFIER(buf, varno);
2089  appendStringInfo(buf, "*)::text IS NOT NULL THEN %u END", fetchval);
2090  }
2091  else
2092  appendStringInfo(buf, "%u", fetchval);
2093  }
2094  else if (varattno == 0)
2095  {
2096  /* Whole row reference */
2097  Relation rel;
2098  Bitmapset *attrs_used;
2099 
2100  /* Required only to be passed down to deparseTargetList(). */
2101  List *retrieved_attrs;
2102 
2103  /* Get RangeTblEntry from array in PlannerInfo. */
2104  rte = planner_rt_fetch(varno, root);
2105 
2106  /*
2107  * The lock on the relation will be held by upper callers, so it's
2108  * fine to open it with no lock here.
2109  */
2110  rel = heap_open(rte->relid, NoLock);
2111 
2112  /*
2113  * The local name of the foreign table can not be recognized by the
2114  * foreign server and the table it references on foreign server might
2115  * have different column ordering or different columns than those
2116  * declared locally. Hence we have to deparse whole-row reference as
2117  * ROW(columns referenced locally). Construct this by deparsing a
2118  * "whole row" attribute.
2119  */
2120  attrs_used = bms_add_member(NULL,
2122 
2123  /*
2124  * In case the whole-row reference is under an outer join then it has
2125  * to go NULL whenever the rest of the row goes NULL. Deparsing a join
2126  * query would always involve multiple relations, thus qualify_col
2127  * would be true.
2128  */
2129  if (qualify_col)
2130  {
2131  appendStringInfoString(buf, "CASE WHEN (");
2132  ADD_REL_QUALIFIER(buf, varno);
2133  appendStringInfoString(buf, "*)::text IS NOT NULL THEN ");
2134  }
2135 
2136  appendStringInfoString(buf, "ROW(");
2137  deparseTargetList(buf, root, varno, rel, false, attrs_used, qualify_col,
2138  &retrieved_attrs);
2139  appendStringInfoChar(buf, ')');
2140 
2141  /* Complete the CASE WHEN statement started above. */
2142  if (qualify_col)
2143  appendStringInfoString(buf, " END");
2144 
2145  heap_close(rel, NoLock);
2146  bms_free(attrs_used);
2147  }
2148  else
2149  {
2150  char *colname = NULL;
2151  List *options;
2152  ListCell *lc;
2153 
2154  /* varno must not be any of OUTER_VAR, INNER_VAR and INDEX_VAR. */
2155  Assert(!IS_SPECIAL_VARNO(varno));
2156 
2157  /* Get RangeTblEntry from array in PlannerInfo. */
2158  rte = planner_rt_fetch(varno, root);
2159 
2160  /*
2161  * If it's a column of a foreign table, and it has the column_name FDW
2162  * option, use that value.
2163  */
2164  options = GetForeignColumnOptions(rte->relid, varattno);
2165  foreach(lc, options)
2166  {
2167  DefElem *def = (DefElem *) lfirst(lc);
2168 
2169  if (strcmp(def->defname, "column_name") == 0)
2170  {
2171  colname = defGetString(def);
2172  break;
2173  }
2174  }
2175 
2176  /*
2177  * If it's a column of a regular table or it doesn't have column_name
2178  * FDW option, use attribute name.
2179  */
2180  if (colname == NULL)
2181  colname = get_attname(rte->relid, varattno, false);
2182 
2183  if (qualify_col)
2184  ADD_REL_QUALIFIER(buf, varno);
2185 
2187  }
2188 }
2189 
2190 /*
2191  * Append remote name of specified foreign table to buf.
2192  * Use value of table_name FDW option (if any) instead of relation's name.
2193  * Similarly, schema_name FDW option overrides schema name.
2194  */
2195 static void
2197 {
2198  ForeignTable *table;
2199  const char *nspname = NULL;
2200  const char *relname = NULL;
2201  ListCell *lc;
2202 
2203  /* obtain additional catalog information. */
2204  table = GetForeignTable(RelationGetRelid(rel));
2205 
2206  /*
2207  * Use value of FDW options if any, instead of the name of object itself.
2208  */
2209  foreach(lc, table->options)
2210  {
2211  DefElem *def = (DefElem *) lfirst(lc);
2212 
2213  if (strcmp(def->defname, "schema_name") == 0)
2214  nspname = defGetString(def);
2215  else if (strcmp(def->defname, "table_name") == 0)
2216  relname = defGetString(def);
2217  }
2218 
2219  /*
2220  * Note: we could skip printing the schema name if it's pg_catalog, but
2221  * that doesn't seem worth the trouble.
2222  */
2223  if (nspname == NULL)
2224  nspname = get_namespace_name(RelationGetNamespace(rel));
2225  if (relname == NULL)
2226  relname = RelationGetRelationName(rel);
2227 
2228  appendStringInfo(buf, "%s.%s",
2229  quote_identifier(nspname), quote_identifier(relname));
2230 }
2231 
2232 /*
2233  * Append a SQL string literal representing "val" to buf.
2234  */
2235 void
2237 {
2238  const char *valptr;
2239 
2240  /*
2241  * Rather than making assumptions about the remote server's value of
2242  * standard_conforming_strings, always use E'foo' syntax if there are any
2243  * backslashes. This will fail on remote servers before 8.1, but those
2244  * are long out of support.
2245  */
2246  if (strchr(val, '\\') != NULL)
2248  appendStringInfoChar(buf, '\'');
2249  for (valptr = val; *valptr; valptr++)
2250  {
2251  char ch = *valptr;
2252 
2253  if (SQL_STR_DOUBLE(ch, true))
2254  appendStringInfoChar(buf, ch);
2255  appendStringInfoChar(buf, ch);
2256  }
2257  appendStringInfoChar(buf, '\'');
2258 }
2259 
2260 /*
2261  * Deparse given expression into context->buf.
2262  *
2263  * This function must support all the same node types that foreign_expr_walker
2264  * accepts.
2265  *
2266  * Note: unlike ruleutils.c, we just use a simple hard-wired parenthesization
2267  * scheme: anything more complex than a Var, Const, function call or cast
2268  * should be self-parenthesized.
2269  */
2270 static void
2272 {
2273  if (node == NULL)
2274  return;
2275 
2276  switch (nodeTag(node))
2277  {
2278  case T_Var:
2279  deparseVar((Var *) node, context);
2280  break;
2281  case T_Const:
2282  deparseConst((Const *) node, context, 0);
2283  break;
2284  case T_Param:
2285  deparseParam((Param *) node, context);
2286  break;
2287  case T_ArrayRef:
2288  deparseArrayRef((ArrayRef *) node, context);
2289  break;
2290  case T_FuncExpr:
2291  deparseFuncExpr((FuncExpr *) node, context);
2292  break;
2293  case T_OpExpr:
2294  deparseOpExpr((OpExpr *) node, context);
2295  break;
2296  case T_DistinctExpr:
2297  deparseDistinctExpr((DistinctExpr *) node, context);
2298  break;
2299  case T_ScalarArrayOpExpr:
2300  deparseScalarArrayOpExpr((ScalarArrayOpExpr *) node, context);
2301  break;
2302  case T_RelabelType:
2303  deparseRelabelType((RelabelType *) node, context);
2304  break;
2305  case T_BoolExpr:
2306  deparseBoolExpr((BoolExpr *) node, context);
2307  break;
2308  case T_NullTest:
2309  deparseNullTest((NullTest *) node, context);
2310  break;
2311  case T_ArrayExpr:
2312  deparseArrayExpr((ArrayExpr *) node, context);
2313  break;
2314  case T_Aggref:
2315  deparseAggref((Aggref *) node, context);
2316  break;
2317  default:
2318  elog(ERROR, "unsupported expression type for deparse: %d",
2319  (int) nodeTag(node));
2320  break;
2321  }
2322 }
2323 
2324 /*
2325  * Deparse given Var node into context->buf.
2326  *
2327  * If the Var belongs to the foreign relation, just print its remote name.
2328  * Otherwise, it's effectively a Param (and will in fact be a Param at
2329  * run time). Handle it the same way we handle plain Params --- see
2330  * deparseParam for comments.
2331  */
2332 static void
2334 {
2335  Relids relids = context->scanrel->relids;
2336  int relno;
2337  int colno;
2338 
2339  /* Qualify columns when multiple relations are involved. */
2340  bool qualify_col = (bms_num_members(relids) > 1);
2341 
2342  /*
2343  * If the Var belongs to the foreign relation that is deparsed as a
2344  * subquery, use the relation and column alias to the Var provided by the
2345  * subquery, instead of the remote name.
2346  */
2347  if (is_subquery_var(node, context->scanrel, &relno, &colno))
2348  {
2349  appendStringInfo(context->buf, "%s%d.%s%d",
2351  SUBQUERY_COL_ALIAS_PREFIX, colno);
2352  return;
2353  }
2354 
2355  if (bms_is_member(node->varno, relids) && node->varlevelsup == 0)
2356  deparseColumnRef(context->buf, node->varno, node->varattno,
2357  context->root, qualify_col);
2358  else
2359  {
2360  /* Treat like a Param */
2361  if (context->params_list)
2362  {
2363  int pindex = 0;
2364  ListCell *lc;
2365 
2366  /* find its index in params_list */
2367  foreach(lc, *context->params_list)
2368  {
2369  pindex++;
2370  if (equal(node, (Node *) lfirst(lc)))
2371  break;
2372  }
2373  if (lc == NULL)
2374  {
2375  /* not in list, so add it */
2376  pindex++;
2377  *context->params_list = lappend(*context->params_list, node);
2378  }
2379 
2380  printRemoteParam(pindex, node->vartype, node->vartypmod, context);
2381  }
2382  else
2383  {
2384  printRemotePlaceholder(node->vartype, node->vartypmod, context);
2385  }
2386  }
2387 }
2388 
2389 /*
2390  * Deparse given constant value into context->buf.
2391  *
2392  * This function has to be kept in sync with ruleutils.c's get_const_expr.
2393  * As for that function, showtype can be -1 to never show "::typename" decoration,
2394  * or +1 to always show it, or 0 to show it only if the constant wouldn't be assumed
2395  * to be the right type by default.
2396  */
2397 static void
2398 deparseConst(Const *node, deparse_expr_cxt *context, int showtype)
2399 {
2400  StringInfo buf = context->buf;
2401  Oid typoutput;
2402  bool typIsVarlena;
2403  char *extval;
2404  bool isfloat = false;
2405  bool needlabel;
2406 
2407  if (node->constisnull)
2408  {
2409  appendStringInfoString(buf, "NULL");
2410  if (showtype >= 0)
2411  appendStringInfo(buf, "::%s",
2413  node->consttypmod));
2414  return;
2415  }
2416 
2418  &typoutput, &typIsVarlena);
2419  extval = OidOutputFunctionCall(typoutput, node->constvalue);
2420 
2421  switch (node->consttype)
2422  {
2423  case INT2OID:
2424  case INT4OID:
2425  case INT8OID:
2426  case OIDOID:
2427  case FLOAT4OID:
2428  case FLOAT8OID:
2429  case NUMERICOID:
2430  {
2431  /*
2432  * No need to quote unless it's a special value such as 'NaN'.
2433  * See comments in get_const_expr().
2434  */
2435  if (strspn(extval, "0123456789+-eE.") == strlen(extval))
2436  {
2437  if (extval[0] == '+' || extval[0] == '-')
2438  appendStringInfo(buf, "(%s)", extval);
2439  else
2440  appendStringInfoString(buf, extval);
2441  if (strcspn(extval, "eE.") != strlen(extval))
2442  isfloat = true; /* it looks like a float */
2443  }
2444  else
2445  appendStringInfo(buf, "'%s'", extval);
2446  }
2447  break;
2448  case BITOID:
2449  case VARBITOID:
2450  appendStringInfo(buf, "B'%s'", extval);
2451  break;
2452  case BOOLOID:
2453  if (strcmp(extval, "t") == 0)
2454  appendStringInfoString(buf, "true");
2455  else
2456  appendStringInfoString(buf, "false");
2457  break;
2458  default:
2459  deparseStringLiteral(buf, extval);
2460  break;
2461  }
2462 
2463  pfree(extval);
2464 
2465  if (showtype < 0)
2466  return;
2467 
2468  /*
2469  * For showtype == 0, append ::typename unless the constant will be
2470  * implicitly typed as the right type when it is read in.
2471  *
2472  * XXX this code has to be kept in sync with the behavior of the parser,
2473  * especially make_const.
2474  */
2475  switch (node->consttype)
2476  {
2477  case BOOLOID:
2478  case INT4OID:
2479  case UNKNOWNOID:
2480  needlabel = false;
2481  break;
2482  case NUMERICOID:
2483  needlabel = !isfloat || (node->consttypmod >= 0);
2484  break;
2485  default:
2486  needlabel = true;
2487  break;
2488  }
2489  if (needlabel || showtype > 0)
2490  appendStringInfo(buf, "::%s",
2492  node->consttypmod));
2493 }
2494 
2495 /*
2496  * Deparse given Param node.
2497  *
2498  * If we're generating the query "for real", add the Param to
2499  * context->params_list if it's not already present, and then use its index
2500  * in that list as the remote parameter number. During EXPLAIN, there's
2501  * no need to identify a parameter number.
2502  */
2503 static void
2505 {
2506  if (context->params_list)
2507  {
2508  int pindex = 0;
2509  ListCell *lc;
2510 
2511  /* find its index in params_list */
2512  foreach(lc, *context->params_list)
2513  {
2514  pindex++;
2515  if (equal(node, (Node *) lfirst(lc)))
2516  break;
2517  }
2518  if (lc == NULL)
2519  {
2520  /* not in list, so add it */
2521  pindex++;
2522  *context->params_list = lappend(*context->params_list, node);
2523  }
2524 
2525  printRemoteParam(pindex, node->paramtype, node->paramtypmod, context);
2526  }
2527  else
2528  {
2529  printRemotePlaceholder(node->paramtype, node->paramtypmod, context);
2530  }
2531 }
2532 
2533 /*
2534  * Deparse an array subscript expression.
2535  */
2536 static void
2538 {
2539  StringInfo buf = context->buf;
2540  ListCell *lowlist_item;
2541  ListCell *uplist_item;
2542 
2543  /* Always parenthesize the expression. */
2544  appendStringInfoChar(buf, '(');
2545 
2546  /*
2547  * Deparse referenced array expression first. If that expression includes
2548  * a cast, we have to parenthesize to prevent the array subscript from
2549  * being taken as typename decoration. We can avoid that in the typical
2550  * case of subscripting a Var, but otherwise do it.
2551  */
2552  if (IsA(node->refexpr, Var))
2553  deparseExpr(node->refexpr, context);
2554  else
2555  {
2556  appendStringInfoChar(buf, '(');
2557  deparseExpr(node->refexpr, context);
2558  appendStringInfoChar(buf, ')');
2559  }
2560 
2561  /* Deparse subscript expressions. */
2562  lowlist_item = list_head(node->reflowerindexpr); /* could be NULL */
2563  foreach(uplist_item, node->refupperindexpr)
2564  {
2565  appendStringInfoChar(buf, '[');
2566  if (lowlist_item)
2567  {
2568  deparseExpr(lfirst(lowlist_item), context);
2569  appendStringInfoChar(buf, ':');
2570  lowlist_item = lnext(lowlist_item);
2571  }
2572  deparseExpr(lfirst(uplist_item), context);
2573  appendStringInfoChar(buf, ']');
2574  }
2575 
2576  appendStringInfoChar(buf, ')');
2577 }
2578 
2579 /*
2580  * Deparse a function call.
2581  */
2582 static void
2584 {
2585  StringInfo buf = context->buf;
2586  bool use_variadic;
2587  bool first;
2588  ListCell *arg;
2589 
2590  /*
2591  * If the function call came from an implicit coercion, then just show the
2592  * first argument.
2593  */
2594  if (node->funcformat == COERCE_IMPLICIT_CAST)
2595  {
2596  deparseExpr((Expr *) linitial(node->args), context);
2597  return;
2598  }
2599 
2600  /*
2601  * If the function call came from a cast, then show the first argument
2602  * plus an explicit cast operation.
2603  */
2604  if (node->funcformat == COERCE_EXPLICIT_CAST)
2605  {
2606  Oid rettype = node->funcresulttype;
2607  int32 coercedTypmod;
2608 
2609  /* Get the typmod if this is a length-coercion function */
2610  (void) exprIsLengthCoercion((Node *) node, &coercedTypmod);
2611 
2612  deparseExpr((Expr *) linitial(node->args), context);
2613  appendStringInfo(buf, "::%s",
2614  deparse_type_name(rettype, coercedTypmod));
2615  return;
2616  }
2617 
2618  /* Check if need to print VARIADIC (cf. ruleutils.c) */
2619  use_variadic = node->funcvariadic;
2620 
2621  /*
2622  * Normal function: display as proname(args).
2623  */
2624  appendFunctionName(node->funcid, context);
2625  appendStringInfoChar(buf, '(');
2626 
2627  /* ... and all the arguments */
2628  first = true;
2629  foreach(arg, node->args)
2630  {
2631  if (!first)
2632  appendStringInfoString(buf, ", ");
2633  if (use_variadic && lnext(arg) == NULL)
2634  appendStringInfoString(buf, "VARIADIC ");
2635  deparseExpr((Expr *) lfirst(arg), context);
2636  first = false;
2637  }
2638  appendStringInfoChar(buf, ')');
2639 }
2640 
2641 /*
2642  * Deparse given operator expression. To avoid problems around
2643  * priority of operations, we always parenthesize the arguments.
2644  */
2645 static void
2647 {
2648  StringInfo buf = context->buf;
2649  HeapTuple tuple;
2650  Form_pg_operator form;
2651  char oprkind;
2652  ListCell *arg;
2653 
2654  /* Retrieve information about the operator from system catalog. */
2655  tuple = SearchSysCache1(OPEROID, ObjectIdGetDatum(node->opno));
2656  if (!HeapTupleIsValid(tuple))
2657  elog(ERROR, "cache lookup failed for operator %u", node->opno);
2658  form = (Form_pg_operator) GETSTRUCT(tuple);
2659  oprkind = form->oprkind;
2660 
2661  /* Sanity check. */
2662  Assert((oprkind == 'r' && list_length(node->args) == 1) ||
2663  (oprkind == 'l' && list_length(node->args) == 1) ||
2664  (oprkind == 'b' && list_length(node->args) == 2));
2665 
2666  /* Always parenthesize the expression. */
2667  appendStringInfoChar(buf, '(');
2668 
2669  /* Deparse left operand. */
2670  if (oprkind == 'r' || oprkind == 'b')
2671  {
2672  arg = list_head(node->args);
2673  deparseExpr(lfirst(arg), context);
2674  appendStringInfoChar(buf, ' ');
2675  }
2676 
2677  /* Deparse operator name. */
2678  deparseOperatorName(buf, form);
2679 
2680  /* Deparse right operand. */
2681  if (oprkind == 'l' || oprkind == 'b')
2682  {
2683  arg = list_tail(node->args);
2684  appendStringInfoChar(buf, ' ');
2685  deparseExpr(lfirst(arg), context);
2686  }
2687 
2688  appendStringInfoChar(buf, ')');
2689 
2690  ReleaseSysCache(tuple);
2691 }
2692 
2693 /*
2694  * Print the name of an operator.
2695  */
2696 static void
2698 {
2699  char *opname;
2700 
2701  /* opname is not a SQL identifier, so we should not quote it. */
2702  opname = NameStr(opform->oprname);
2703 
2704  /* Print schema name only if it's not pg_catalog */
2705  if (opform->oprnamespace != PG_CATALOG_NAMESPACE)
2706  {
2707  const char *opnspname;
2708 
2709  opnspname = get_namespace_name(opform->oprnamespace);
2710  /* Print fully qualified operator name. */
2711  appendStringInfo(buf, "OPERATOR(%s.%s)",
2712  quote_identifier(opnspname), opname);
2713  }
2714  else
2715  {
2716  /* Just print operator name. */
2717  appendStringInfoString(buf, opname);
2718  }
2719 }
2720 
2721 /*
2722  * Deparse IS DISTINCT FROM.
2723  */
2724 static void
2726 {
2727  StringInfo buf = context->buf;
2728 
2729  Assert(list_length(node->args) == 2);
2730 
2731  appendStringInfoChar(buf, '(');
2732  deparseExpr(linitial(node->args), context);
2733  appendStringInfoString(buf, " IS DISTINCT FROM ");
2734  deparseExpr(lsecond(node->args), context);
2735  appendStringInfoChar(buf, ')');
2736 }
2737 
2738 /*
2739  * Deparse given ScalarArrayOpExpr expression. To avoid problems
2740  * around priority of operations, we always parenthesize the arguments.
2741  */
2742 static void
2744 {
2745  StringInfo buf = context->buf;
2746  HeapTuple tuple;
2747  Form_pg_operator form;
2748  Expr *arg1;
2749  Expr *arg2;
2750 
2751  /* Retrieve information about the operator from system catalog. */
2752  tuple = SearchSysCache1(OPEROID, ObjectIdGetDatum(node->opno));
2753  if (!HeapTupleIsValid(tuple))
2754  elog(ERROR, "cache lookup failed for operator %u", node->opno);
2755  form = (Form_pg_operator) GETSTRUCT(tuple);
2756 
2757  /* Sanity check. */
2758  Assert(list_length(node->args) == 2);
2759 
2760  /* Always parenthesize the expression. */
2761  appendStringInfoChar(buf, '(');
2762 
2763  /* Deparse left operand. */
2764  arg1 = linitial(node->args);
2765  deparseExpr(arg1, context);
2766  appendStringInfoChar(buf, ' ');
2767 
2768  /* Deparse operator name plus decoration. */
2769  deparseOperatorName(buf, form);
2770  appendStringInfo(buf, " %s (", node->useOr ? "ANY" : "ALL");
2771 
2772  /* Deparse right operand. */
2773  arg2 = lsecond(node->args);
2774  deparseExpr(arg2, context);
2775 
2776  appendStringInfoChar(buf, ')');
2777 
2778  /* Always parenthesize the expression. */
2779  appendStringInfoChar(buf, ')');
2780 
2781  ReleaseSysCache(tuple);
2782 }
2783 
2784 /*
2785  * Deparse a RelabelType (binary-compatible cast) node.
2786  */
2787 static void
2789 {
2790  deparseExpr(node->arg, context);
2791  if (node->relabelformat != COERCE_IMPLICIT_CAST)
2792  appendStringInfo(context->buf, "::%s",
2794  node->resulttypmod));
2795 }
2796 
2797 /*
2798  * Deparse a BoolExpr node.
2799  */
2800 static void
2802 {
2803  StringInfo buf = context->buf;
2804  const char *op = NULL; /* keep compiler quiet */
2805  bool first;
2806  ListCell *lc;
2807 
2808  switch (node->boolop)
2809  {
2810  case AND_EXPR:
2811  op = "AND";
2812  break;
2813  case OR_EXPR:
2814  op = "OR";
2815  break;
2816  case NOT_EXPR:
2817  appendStringInfoString(buf, "(NOT ");
2818  deparseExpr(linitial(node->args), context);
2819  appendStringInfoChar(buf, ')');
2820  return;
2821  }
2822 
2823  appendStringInfoChar(buf, '(');
2824  first = true;
2825  foreach(lc, node->args)
2826  {
2827  if (!first)
2828  appendStringInfo(buf, " %s ", op);
2829  deparseExpr((Expr *) lfirst(lc), context);
2830  first = false;
2831  }
2832  appendStringInfoChar(buf, ')');
2833 }
2834 
2835 /*
2836  * Deparse IS [NOT] NULL expression.
2837  */
2838 static void
2840 {
2841  StringInfo buf = context->buf;
2842 
2843  appendStringInfoChar(buf, '(');
2844  deparseExpr(node->arg, context);
2845 
2846  /*
2847  * For scalar inputs, we prefer to print as IS [NOT] NULL, which is
2848  * shorter and traditional. If it's a rowtype input but we're applying a
2849  * scalar test, must print IS [NOT] DISTINCT FROM NULL to be semantically
2850  * correct.
2851  */
2852  if (node->argisrow || !type_is_rowtype(exprType((Node *) node->arg)))
2853  {
2854  if (node->nulltesttype == IS_NULL)
2855  appendStringInfoString(buf, " IS NULL)");
2856  else
2857  appendStringInfoString(buf, " IS NOT NULL)");
2858  }
2859  else
2860  {
2861  if (node->nulltesttype == IS_NULL)
2862  appendStringInfoString(buf, " IS NOT DISTINCT FROM NULL)");
2863  else
2864  appendStringInfoString(buf, " IS DISTINCT FROM NULL)");
2865  }
2866 }
2867 
2868 /*
2869  * Deparse ARRAY[...] construct.
2870  */
2871 static void
2873 {
2874  StringInfo buf = context->buf;
2875  bool first = true;
2876  ListCell *lc;
2877 
2878  appendStringInfoString(buf, "ARRAY[");
2879  foreach(lc, node->elements)
2880  {
2881  if (!first)
2882  appendStringInfoString(buf, ", ");
2883  deparseExpr(lfirst(lc), context);
2884  first = false;
2885  }
2886  appendStringInfoChar(buf, ']');
2887 
2888  /* If the array is empty, we need an explicit cast to the array type. */
2889  if (node->elements == NIL)
2890  appendStringInfo(buf, "::%s",
2891  deparse_type_name(node->array_typeid, -1));
2892 }
2893 
2894 /*
2895  * Deparse an Aggref node.
2896  */
2897 static void
2899 {
2900  StringInfo buf = context->buf;
2901  bool use_variadic;
2902 
2903  /* Only basic, non-split aggregation accepted. */
2904  Assert(node->aggsplit == AGGSPLIT_SIMPLE);
2905 
2906  /* Check if need to print VARIADIC (cf. ruleutils.c) */
2907  use_variadic = node->aggvariadic;
2908 
2909  /* Find aggregate name from aggfnoid which is a pg_proc entry */
2910  appendFunctionName(node->aggfnoid, context);
2911  appendStringInfoChar(buf, '(');
2912 
2913  /* Add DISTINCT */
2914  appendStringInfoString(buf, (node->aggdistinct != NIL) ? "DISTINCT " : "");
2915 
2916  if (AGGKIND_IS_ORDERED_SET(node->aggkind))
2917  {
2918  /* Add WITHIN GROUP (ORDER BY ..) */
2919  ListCell *arg;
2920  bool first = true;
2921 
2922  Assert(!node->aggvariadic);
2923  Assert(node->aggorder != NIL);
2924 
2925  foreach(arg, node->aggdirectargs)
2926  {
2927  if (!first)
2928  appendStringInfoString(buf, ", ");
2929  first = false;
2930 
2931  deparseExpr((Expr *) lfirst(arg), context);
2932  }
2933 
2934  appendStringInfoString(buf, ") WITHIN GROUP (ORDER BY ");
2935  appendAggOrderBy(node->aggorder, node->args, context);
2936  }
2937  else
2938  {
2939  /* aggstar can be set only in zero-argument aggregates */
2940  if (node->aggstar)
2941  appendStringInfoChar(buf, '*');
2942  else
2943  {
2944  ListCell *arg;
2945  bool first = true;
2946 
2947  /* Add all the arguments */
2948  foreach(arg, node->args)
2949  {
2950  TargetEntry *tle = (TargetEntry *) lfirst(arg);
2951  Node *n = (Node *) tle->expr;
2952 
2953  if (tle->resjunk)
2954  continue;
2955 
2956  if (!first)
2957  appendStringInfoString(buf, ", ");
2958  first = false;
2959 
2960  /* Add VARIADIC */
2961  if (use_variadic && lnext(arg) == NULL)
2962  appendStringInfoString(buf, "VARIADIC ");
2963 
2964  deparseExpr((Expr *) n, context);
2965  }
2966  }
2967 
2968  /* Add ORDER BY */
2969  if (node->aggorder != NIL)
2970  {
2971  appendStringInfoString(buf, " ORDER BY ");
2972  appendAggOrderBy(node->aggorder, node->args, context);
2973  }
2974  }
2975 
2976  /* Add FILTER (WHERE ..) */
2977  if (node->aggfilter != NULL)
2978  {
2979  appendStringInfoString(buf, ") FILTER (WHERE ");
2980  deparseExpr((Expr *) node->aggfilter, context);
2981  }
2982 
2983  appendStringInfoChar(buf, ')');
2984 }
2985 
2986 /*
2987  * Append ORDER BY within aggregate function.
2988  */
2989 static void
2990 appendAggOrderBy(List *orderList, List *targetList, deparse_expr_cxt *context)
2991 {
2992  StringInfo buf = context->buf;
2993  ListCell *lc;
2994  bool first = true;
2995 
2996  foreach(lc, orderList)
2997  {
2998  SortGroupClause *srt = (SortGroupClause *) lfirst(lc);
2999  Node *sortexpr;
3000  Oid sortcoltype;
3001  TypeCacheEntry *typentry;
3002 
3003  if (!first)
3004  appendStringInfoString(buf, ", ");
3005  first = false;
3006 
3007  sortexpr = deparseSortGroupClause(srt->tleSortGroupRef, targetList,
3008  false, context);
3009  sortcoltype = exprType(sortexpr);
3010  /* See whether operator is default < or > for datatype */
3011  typentry = lookup_type_cache(sortcoltype,
3013  if (srt->sortop == typentry->lt_opr)
3014  appendStringInfoString(buf, " ASC");
3015  else if (srt->sortop == typentry->gt_opr)
3016  appendStringInfoString(buf, " DESC");
3017  else
3018  {
3019  HeapTuple opertup;
3020  Form_pg_operator operform;
3021 
3022  appendStringInfoString(buf, " USING ");
3023 
3024  /* Append operator name. */
3025  opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(srt->sortop));
3026  if (!HeapTupleIsValid(opertup))
3027  elog(ERROR, "cache lookup failed for operator %u", srt->sortop);
3028  operform = (Form_pg_operator) GETSTRUCT(opertup);
3029  deparseOperatorName(buf, operform);
3030  ReleaseSysCache(opertup);
3031  }
3032 
3033  if (srt->nulls_first)
3034  appendStringInfoString(buf, " NULLS FIRST");
3035  else
3036  appendStringInfoString(buf, " NULLS LAST");
3037  }
3038 }
3039 
3040 /*
3041  * Print the representation of a parameter to be sent to the remote side.
3042  *
3043  * Note: we always label the Param's type explicitly rather than relying on
3044  * transmitting a numeric type OID in PQexecParams(). This allows us to
3045  * avoid assuming that types have the same OIDs on the remote side as they
3046  * do locally --- they need only have the same names.
3047  */
3048 static void
3049 printRemoteParam(int paramindex, Oid paramtype, int32 paramtypmod,
3050  deparse_expr_cxt *context)
3051 {
3052  StringInfo buf = context->buf;
3053  char *ptypename = deparse_type_name(paramtype, paramtypmod);
3054 
3055  appendStringInfo(buf, "$%d::%s", paramindex, ptypename);
3056 }
3057 
3058 /*
3059  * Print the representation of a placeholder for a parameter that will be
3060  * sent to the remote side at execution time.
3061  *
3062  * This is used when we're just trying to EXPLAIN the remote query.
3063  * We don't have the actual value of the runtime parameter yet, and we don't
3064  * want the remote planner to generate a plan that depends on such a value
3065  * anyway. Thus, we can't do something simple like "$1::paramtype".
3066  * Instead, we emit "((SELECT null::paramtype)::paramtype)".
3067  * In all extant versions of Postgres, the planner will see that as an unknown
3068  * constant value, which is what we want. This might need adjustment if we
3069  * ever make the planner flatten scalar subqueries. Note: the reason for the
3070  * apparently useless outer cast is to ensure that the representation as a
3071  * whole will be parsed as an a_expr and not a select_with_parens; the latter
3072  * would do the wrong thing in the context "x = ANY(...)".
3073  */
3074 static void
3075 printRemotePlaceholder(Oid paramtype, int32 paramtypmod,
3076  deparse_expr_cxt *context)
3077 {
3078  StringInfo buf = context->buf;
3079  char *ptypename = deparse_type_name(paramtype, paramtypmod);
3080 
3081  appendStringInfo(buf, "((SELECT null::%s)::%s)", ptypename, ptypename);
3082 }
3083 
3084 /*
3085  * Deparse GROUP BY clause.
3086  */
3087 static void
3089 {
3090  StringInfo buf = context->buf;
3091  Query *query = context->root->parse;
3092  ListCell *lc;
3093  bool first = true;
3094 
3095  /* Nothing to be done, if there's no GROUP BY clause in the query. */
3096  if (!query->groupClause)
3097  return;
3098 
3099  appendStringInfoString(buf, " GROUP BY ");
3100 
3101  /*
3102  * Queries with grouping sets are not pushed down, so we don't expect
3103  * grouping sets here.
3104  */
3105  Assert(!query->groupingSets);
3106 
3107  foreach(lc, query->groupClause)
3108  {
3109  SortGroupClause *grp = (SortGroupClause *) lfirst(lc);
3110 
3111  if (!first)
3112  appendStringInfoString(buf, ", ");
3113  first = false;
3114 
3115  deparseSortGroupClause(grp->tleSortGroupRef, tlist, true, context);
3116  }
3117 }
3118 
3119 /*
3120  * Deparse ORDER BY clause according to the given pathkeys for given base
3121  * relation. From given pathkeys expressions belonging entirely to the given
3122  * base relation are obtained and deparsed.
3123  */
3124 static void
3126 {
3127  ListCell *lcell;
3128  int nestlevel;
3129  char *delim = " ";
3130  RelOptInfo *baserel = context->scanrel;
3131  StringInfo buf = context->buf;
3132 
3133  /* Make sure any constants in the exprs are printed portably */
3134  nestlevel = set_transmission_modes();
3135 
3136  appendStringInfoString(buf, " ORDER BY");
3137  foreach(lcell, pathkeys)
3138  {
3139  PathKey *pathkey = lfirst(lcell);
3140  Expr *em_expr;
3141 
3142  em_expr = find_em_expr_for_rel(pathkey->pk_eclass, baserel);
3143  Assert(em_expr != NULL);
3144 
3145  appendStringInfoString(buf, delim);
3146  deparseExpr(em_expr, context);
3147  if (pathkey->pk_strategy == BTLessStrategyNumber)
3148  appendStringInfoString(buf, " ASC");
3149  else
3150  appendStringInfoString(buf, " DESC");
3151 
3152  if (pathkey->pk_nulls_first)
3153  appendStringInfoString(buf, " NULLS FIRST");
3154  else
3155  appendStringInfoString(buf, " NULLS LAST");
3156 
3157  delim = ", ";
3158  }
3159  reset_transmission_modes(nestlevel);
3160 }
3161 
3162 /*
3163  * appendFunctionName
3164  * Deparses function name from given function oid.
3165  */
3166 static void
3168 {
3169  StringInfo buf = context->buf;
3170  HeapTuple proctup;
3171  Form_pg_proc procform;
3172  const char *proname;
3173 
3174  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
3175  if (!HeapTupleIsValid(proctup))
3176  elog(ERROR, "cache lookup failed for function %u", funcid);
3177  procform = (Form_pg_proc) GETSTRUCT(proctup);
3178 
3179  /* Print schema name only if it's not pg_catalog */
3180  if (procform->pronamespace != PG_CATALOG_NAMESPACE)
3181  {
3182  const char *schemaname;
3183 
3184  schemaname = get_namespace_name(procform->pronamespace);
3185  appendStringInfo(buf, "%s.", quote_identifier(schemaname));
3186  }
3187 
3188  /* Always print the function name */
3189  proname = NameStr(procform->proname);
3191 
3192  ReleaseSysCache(proctup);
3193 }
3194 
3195 /*
3196  * Appends a sort or group clause.
3197  *
3198  * Like get_rule_sortgroupclause(), returns the expression tree, so caller
3199  * need not find it again.
3200  */
3201 static Node *
3202 deparseSortGroupClause(Index ref, List *tlist, bool force_colno,
3203  deparse_expr_cxt *context)
3204 {
3205  StringInfo buf = context->buf;
3206  TargetEntry *tle;
3207  Expr *expr;
3208 
3209  tle = get_sortgroupref_tle(ref, tlist);
3210  expr = tle->expr;
3211 
3212  if (force_colno)
3213  {
3214  /* Use column-number form when requested by caller. */
3215  Assert(!tle->resjunk);
3216  appendStringInfo(buf, "%d", tle->resno);
3217  }
3218  else if (expr && IsA(expr, Const))
3219  {
3220  /*
3221  * Force a typecast here so that we don't emit something like "GROUP
3222  * BY 2", which will be misconstrued as a column position rather than
3223  * a constant.
3224  */
3225  deparseConst((Const *) expr, context, 1);
3226  }
3227  else if (!expr || IsA(expr, Var))
3228  deparseExpr(expr, context);
3229  else
3230  {
3231  /* Always parenthesize the expression. */
3232  appendStringInfoChar(buf, '(');
3233  deparseExpr(expr, context);
3234  appendStringInfoChar(buf, ')');
3235  }
3236 
3237  return (Node *) expr;
3238 }
3239 
3240 
3241 /*
3242  * Returns true if given Var is deparsed as a subquery output column, in
3243  * which case, *relno and *colno are set to the IDs for the relation and
3244  * column alias to the Var provided by the subquery.
3245  */
3246 static bool
3247 is_subquery_var(Var *node, RelOptInfo *foreignrel, int *relno, int *colno)
3248 {
3249  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
3250  RelOptInfo *outerrel = fpinfo->outerrel;
3251  RelOptInfo *innerrel = fpinfo->innerrel;
3252 
3253  /* Should only be called in these cases. */
3254  Assert(IS_SIMPLE_REL(foreignrel) || IS_JOIN_REL(foreignrel));
3255 
3256  /*
3257  * If the given relation isn't a join relation, it doesn't have any lower
3258  * subqueries, so the Var isn't a subquery output column.
3259  */
3260  if (!IS_JOIN_REL(foreignrel))
3261  return false;
3262 
3263  /*
3264  * If the Var doesn't belong to any lower subqueries, it isn't a subquery
3265  * output column.
3266  */
3267  if (!bms_is_member(node->varno, fpinfo->lower_subquery_rels))
3268  return false;
3269 
3270  if (bms_is_member(node->varno, outerrel->relids))
3271  {
3272  /*
3273  * If outer relation is deparsed as a subquery, the Var is an output
3274  * column of the subquery; get the IDs for the relation/column alias.
3275  */
3276  if (fpinfo->make_outerrel_subquery)
3277  {
3278  get_relation_column_alias_ids(node, outerrel, relno, colno);
3279  return true;
3280  }
3281 
3282  /* Otherwise, recurse into the outer relation. */
3283  return is_subquery_var(node, outerrel, relno, colno);
3284  }
3285  else
3286  {
3287  Assert(bms_is_member(node->varno, innerrel->relids));
3288 
3289  /*
3290  * If inner relation is deparsed as a subquery, the Var is an output
3291  * column of the subquery; get the IDs for the relation/column alias.
3292  */
3293  if (fpinfo->make_innerrel_subquery)
3294  {
3295  get_relation_column_alias_ids(node, innerrel, relno, colno);
3296  return true;
3297  }
3298 
3299  /* Otherwise, recurse into the inner relation. */
3300  return is_subquery_var(node, innerrel, relno, colno);
3301  }
3302 }
3303 
3304 /*
3305  * Get the IDs for the relation and column alias to given Var belonging to
3306  * given relation, which are returned into *relno and *colno.
3307  */
3308 static void
3310  int *relno, int *colno)
3311 {
3312  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
3313  int i;
3314  ListCell *lc;
3315 
3316  /* Get the relation alias ID */
3317  *relno = fpinfo->relation_index;
3318 
3319  /* Get the column alias ID */
3320  i = 1;
3321  foreach(lc, foreignrel->reltarget->exprs)
3322  {
3323  if (equal(lfirst(lc), (Node *) node))
3324  {
3325  *colno = i;
3326  return;
3327  }
3328  i++;
3329  }
3330 
3331  /* Shouldn't get here */
3332  elog(ERROR, "unexpected expression in subquery output");
3333 }
Datum constvalue
Definition: primnodes.h:196
List * aggdistinct
Definition: primnodes.h:303
Oid funcresulttype
Definition: primnodes.h:450
bool is_builtin(Oid objectId)
Definition: shippable.c:155
#define NIL
Definition: pg_list.h:69
List * rowMarks
Definition: relation.h:256
void deparseUpdateSql(StringInfo buf, PlannerInfo *root, Index rtindex, Relation rel, List *targetAttrs, List *returningList, List **retrieved_attrs)
Definition: deparse.c:1715
Expr * refassgnexpr
Definition: primnodes.h:410
bool aggvariadic
Definition: primnodes.h:306
static Node * deparseSortGroupClause(Index ref, List *tlist, bool force_colno, deparse_expr_cxt *context)
Definition: deparse.c:3202
#define IsA(nodeptr, _type_)
Definition: nodes.h:564
Query * parse
Definition: relation.h:155
static void deparseAggref(Aggref *node, deparse_expr_cxt *context)
Definition: deparse.c:2898
#define OperatorRelationId
Definition: pg_operator.h:32
Index varlevelsup
Definition: primnodes.h:173
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2650
static void deparseBoolExpr(BoolExpr *node, deparse_expr_cxt *context)
Definition: deparse.c:2801
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
static void appendGroupByClause(List *tlist, deparse_expr_cxt *context)
Definition: deparse.c:3088
void deparseDirectDeleteSql(StringInfo buf, PlannerInfo *root, Index rtindex, Relation rel, RelOptInfo *foreignrel, List *remote_conds, List **params_list, List *returningList, List **retrieved_attrs)
Definition: deparse.c:1879
RelOptKind reloptkind
Definition: relation.h:582
List * args
Definition: primnodes.h:457
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10435
static void deparseNullTest(NullTest *node, deparse_expr_cxt *context)
Definition: deparse.c:2839
struct deparse_expr_cxt deparse_expr_cxt
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2991
#define RelationGetDescr(relation)
Definition: rel.h:437
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
static void deparseDistinctExpr(DistinctExpr *node, deparse_expr_cxt *context)
Definition: deparse.c:2725
#define OIDOID
Definition: pg_type.h:328
#define NUMERICOID
Definition: pg_type.h:554
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
#define ProcedureRelationId
Definition: pg_proc.h:33
Oid funccollid
Definition: primnodes.h:455
FDWCollateState state
Definition: deparse.c:91
static void deparseSubqueryTargetList(deparse_expr_cxt *context)
Definition: deparse.c:1390
#define FORMAT_TYPE_TYPEMOD_GIVEN
Definition: builtins.h:117
List ** params_list
Definition: deparse.c:105
static void appendFunctionName(Oid funcid, deparse_expr_cxt *context)
Definition: deparse.c:3167
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1053
#define IS_UPPER_REL(rel)
Definition: relation.h:571
int resultRelation
Definition: parsenodes.h:120
#define IS_JOIN_REL(rel)
Definition: relation.h:566
unsigned char uint8
Definition: c.h:312
Index tleSortGroupRef
Definition: parsenodes.h:1204
Expr * arg
Definition: primnodes.h:794
Oid inputcollid
Definition: primnodes.h:297
#define INT4OID
Definition: pg_type.h:316
List * groupingSets
Definition: parsenodes.h:148
void classifyConditions(PlannerInfo *root, RelOptInfo *baserel, List *input_conds, List **remote_conds, List **local_conds)
Definition: deparse.c:204
int set_transmission_modes(void)
List * list_copy(const List *oldlist)
Definition: list.c:1160
Definition: nodes.h:513
#define VARBITOID
Definition: pg_type.h:546
Relids lower_subquery_rels
Definition: postgres_fdw.h:103
bool exprIsLengthCoercion(const Node *expr, int32 *coercedTypmod)
Definition: nodeFuncs.c:513
List * args
Definition: primnodes.h:301
ForeignTable * GetForeignTable(Oid relid)
Definition: foreign.c:216
static void deparseColumnRef(StringInfo buf, int varno, int varattno, PlannerInfo *root, bool qualify_col)
Definition: deparse.c:2051
AttrNumber varattno
Definition: primnodes.h:168
Oid array_typeid
Definition: primnodes.h:956
List * list_concat(List *list1, List *list2)
Definition: list.c:321
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
static void deparseOperatorName(StringInfo buf, Form_pg_operator opform)
Definition: deparse.c:2697
List * pull_var_clause(Node *node, int flags)
Definition: var.c:535
#define heap_close(r, l)
Definition: heapam.h:97
static void deparseTargetList(StringInfo buf, PlannerInfo *root, Index rtindex, Relation rel, bool is_returning, Bitmapset *attrs_used, bool qualify_col, List **retrieved_attrs)
Definition: deparse.c:1101
bool aggstar
Definition: primnodes.h:305
unsigned int Oid
Definition: postgres_ext.h:31
static void deparseArrayRef(ArrayRef *node, deparse_expr_cxt *context)
Definition: deparse.c:2537
Definition: primnodes.h:163
#define ESCAPE_STRING_SYNTAX
Definition: c.h:994
#define TypeRelationId
Definition: pg_type.h:34
bool is_shippable(Oid objectId, Oid classId, PgFdwRelationInfo *fpinfo)
Definition: shippable.c:165
#define OidIsValid(objectId)
Definition: c.h:594
#define PVC_RECURSE_PLACEHOLDERS
Definition: var.h:26
int natts
Definition: tupdesc.h:79
#define lsecond(l)
Definition: pg_list.h:116
int pk_strategy
Definition: relation.h:945
RelOptInfo * outerrel
Definition: postgres_fdw.h:89
#define IS_SIMPLE_REL(rel)
Definition: relation.h:561
void pull_varattnos(Node *node, Index varno, Bitmapset **varattnos)
Definition: var.c:219
signed int int32
Definition: c.h:302
static void printRemoteParam(int paramindex, Oid paramtype, int32 paramtypmod, deparse_expr_cxt *context)
Definition: deparse.c:3049
JoinType
Definition: nodes.h:677
void deparseInsertSql(StringInfo buf, PlannerInfo *root, Index rtindex, Relation rel, List *targetAttrs, bool doNothing, List *returningList, List **retrieved_attrs)
Definition: deparse.c:1652
#define AGGKIND_IS_ORDERED_SET(kind)
Definition: pg_aggregate.h:133
Oid consttype
Definition: primnodes.h:192
FDWCollateState
Definition: deparse.c:78
static ListCell * list_tail(List *l)
Definition: pg_list.h:83
CoercionForm funcformat
Definition: primnodes.h:454
bool make_outerrel_subquery
Definition: postgres_fdw.h:99
List * GetForeignColumnOptions(Oid relid, AttrNumber attnum)
Definition: foreign.c:254
void pfree(void *pointer)
Definition: mcxt.c:936
#define IS_SPECIAL_VARNO(varno)
Definition: primnodes.h:157
void deparseDeleteSql(StringInfo buf, PlannerInfo *root, Index rtindex, Relation rel, List *returningList, List **retrieved_attrs)
Definition: deparse.c:1850
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
bool resjunk
Definition: primnodes.h:1382
#define linitial(l)
Definition: pg_list.h:111
#define planner_rt_fetch(rti, root)
Definition: relation.h:328
Oid funcid
Definition: primnodes.h:449
bool pk_nulls_first
Definition: relation.h:946
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
static void deparseParam(Param *node, deparse_expr_cxt *context)
Definition: deparse.c:2504
static void deparseScalarArrayOpExpr(ScalarArrayOpExpr *node, deparse_expr_cxt *context)
Definition: deparse.c:2743
#define ADD_REL_QUALIFIER(buf, varno)
Definition: deparse.c:110
#define SUBQUERY_COL_ALIAS_PREFIX
Definition: deparse.c:113
Oid paramcollid
Definition: primnodes.h:248
#define lfirst_int(lc)
Definition: pg_list.h:107
Oid vartype
Definition: primnodes.h:170
char * defGetString(DefElem *def)
Definition: define.c:49
BoolExprType boolop
Definition: primnodes.h:562
#define SUBQUERY_REL_ALIAS_PREFIX
Definition: deparse.c:112
static void deparseOpExpr(OpExpr *node, deparse_expr_cxt *context)
Definition: deparse.c:2646
Expr * arg
Definition: primnodes.h:1187
TriggerDesc * trigdesc
Definition: rel.h:120
Oid constcollid
Definition: primnodes.h:194
static void appendOrderByClause(List *pathkeys, deparse_expr_cxt *context)
Definition: deparse.c:3125
#define lfirst_node(type, lc)
Definition: pg_list.h:109
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:649
#define INT2OID
Definition: pg_type.h:308
Relids relids
Definition: deparse.c:70
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
bool trig_delete_after_row
Definition: reltrigger.h:66
static void deparseArrayExpr(ArrayExpr *node, deparse_expr_cxt *context)
Definition: deparse.c:2872
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3051
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:223
char * c
#define NoLock
Definition: lockdefs.h:34
static char * buf
Definition: pg_test_fsync.c:67
List * refupperindexpr
Definition: primnodes.h:403
#define DEFAULT_COLLATION_OID
Definition: pg_collation.h:75
#define REL_ALIAS_PREFIX
Definition: deparse.c:108
List * reflowerindexpr
Definition: primnodes.h:405
const char * get_jointype_name(JoinType jointype)
Definition: deparse.c:1317
List * aggorder
Definition: primnodes.h:302
AttrNumber resno
Definition: primnodes.h:1376
PlannerInfo * root
Definition: deparse.c:68
#define RelationGetRelationName(relation)
Definition: rel.h:445
RelOptInfo * foreignrel
Definition: deparse.c:69
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define TableOidAttributeNumber
Definition: sysattr.h:27
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
Relids relids
Definition: relation.h:585
List * aggdirectargs
Definition: primnodes.h:300
#define FORMAT_TYPE_FORCE_QUALIFY
Definition: builtins.h:119
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
List * elements
Definition: primnodes.h:959
#define TYPECACHE_GT_OPR
Definition: typcache.h:129
bool trig_insert_after_row
Definition: reltrigger.h:56
static void deparseExplicitTargetList(List *tlist, bool is_returning, List **retrieved_attrs, deparse_expr_cxt *context)
Definition: deparse.c:1354
static bool foreign_expr_walker(Node *node, foreign_glob_cxt *glob_cxt, foreign_loc_cxt *outer_cxt)
Definition: deparse.c:294
#define PG_CATALOG_NAMESPACE
Definition: pg_namespace.h:71
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2409
#define lnext(lc)
Definition: pg_list.h:105
Oid opcollid
Definition: primnodes.h:500
TargetEntry * get_sortgroupref_tle(Index sortref, List *targetList)
Definition: tlist.c:348
void deparseAnalyzeSql(StringInfo buf, Relation rel, List **retrieved_attrs)
Definition: deparse.c:1990
static void deparseSelectSql(List *tlist, bool is_subquery, List **retrieved_attrs, deparse_expr_cxt *context)
Definition: deparse.c:1009
Definition: nodes.h:292
List * lappend_int(List *list, int datum)
Definition: list.c:146
Index relid
Definition: relation.h:613
bool trig_update_after_row
Definition: reltrigger.h:61
static void deparseRelabelType(RelabelType *node, deparse_expr_cxt *context)
Definition: deparse.c:2788
static void deparseVar(Var *node, deparse_expr_cxt *context)
Definition: deparse.c:2333
Definition: nodes.h:147
List * lappend(List *list, void *datum)
Definition: list.c:128
Expr * clause
Definition: relation.h:1847
static char ** options
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
static void appendAggOrderBy(List *orderList, List *targetList, deparse_expr_cxt *context)
Definition: deparse.c:2990
Index varno
Definition: primnodes.h:166
Definition: nodes.h:146
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
List * exprs
Definition: relation.h:976
static void appendConditions(List *exprs, deparse_expr_cxt *context)
Definition: deparse.c:1283
StringInfo buf
Definition: deparse.c:104
void deparseStringLiteral(StringInfo buf, const char *val)
Definition: deparse.c:2236
#define FLOAT4OID
Definition: pg_type.h:416
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
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: deparse.c:1766
Oid resulttype
Definition: primnodes.h:795
unsigned int Index
Definition: c.h:431
static bool is_subquery_var(Var *node, RelOptInfo *foreignrel, int *relno, int *colno)
Definition: deparse.c:3247
NullTestType nulltesttype
Definition: primnodes.h:1188
static char * deparse_type_name(Oid type_oid, int32 typemod)
Definition: deparse.c:855
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:83
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
Oid resultcollid
Definition: primnodes.h:797
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:294
struct foreign_loc_cxt foreign_loc_cxt
void * fdw_private
Definition: relation.h:637
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2196
#define INT8OID
Definition: pg_type.h:304
CmdType commandType
Definition: parsenodes.h:110
int32 paramtypmod
Definition: primnodes.h:247
PlannerInfo * root
Definition: deparse.c:99
#define BITOID
Definition: pg_type.h:542
void bms_free(Bitmapset *a)
Definition: bitmapset.c:245
Bitmapset * attrs_used
Definition: postgres_fdw.h:50
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
Oid inputcollid
Definition: primnodes.h:456
Expr * find_em_expr_for_rel(EquivalenceClass *ec, RelOptInfo *rel)
static void get_relation_column_alias_ids(Var *node, RelOptInfo *foreignrel, int *relno, int *colno)
Definition: deparse.c:3309
#define Assert(condition)
Definition: c.h:688
List * add_to_flat_tlist(List *tlist, List *exprs)
Definition: tlist.c:135
#define lfirst(lc)
Definition: pg_list.h:106
Definition: regguts.h:298
static void deparseConst(Const *node, deparse_expr_cxt *context, int showtype)
Definition: deparse.c:2398
Expr * expr
Definition: primnodes.h:1375
AggSplit aggsplit
Definition: primnodes.h:310
LockClauseStrength strength
Definition: plannodes.h:1031
EquivalenceClass * pk_eclass
Definition: relation.h:943
Oid array_collid
Definition: primnodes.h:957
void deparseAnalyzeSizeSql(StringInfo buf, Relation rel)
Definition: deparse.c:1970
void reset_transmission_modes(int nestlevel)
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
static int list_length(const List *l)
Definition: pg_list.h:89
Oid refcollid
Definition: primnodes.h:402
#define FLOAT8OID
Definition: pg_type.h:419
Expr * aggfilter
Definition: primnodes.h:304
Oid inputcollid
Definition: primnodes.h:501
char * format_type_extended(Oid type_oid, int32 typemod, bits16 flags)
Definition: format_type.c:102
static void deparseFromExpr(List *quals, deparse_expr_cxt *context)
Definition: deparse.c:1067
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:742
#define BOOLOID
Definition: pg_type.h:288
List * args
Definition: primnodes.h:563
#define UNKNOWNOID
Definition: pg_type.h:431
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:57
struct foreign_glob_cxt foreign_glob_cxt
#define nodeTag(nodeptr)
Definition: nodes.h:518
int32 consttypmod
Definition: primnodes.h:193
static void deparseExpr(Expr *expr, deparse_expr_cxt *context)
Definition: deparse.c:2271
List * options
Definition: foreign.h:68
RelOptInfo * innerrel
Definition: postgres_fdw.h:90
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
List * build_tlist_to_deparse(RelOptInfo *foreignrel)
Definition: deparse.c:874
List * groupClause
Definition: parsenodes.h:146
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1742
Oid aggcollid
Definition: primnodes.h:296
static int fe(enum e x)
Definition: preproc-init.c:111
static void deparseLockingClause(deparse_expr_cxt *context)
Definition: deparse.c:1193
bool is_foreign_expr(PlannerInfo *root, RelOptInfo *baserel, Expr *expr)
Definition: deparse.c:230
int i
PlanRowMark * get_plan_rowmark(List *rowmarks, Index rtindex)
Definition: preptlist.c:424
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)
#define TYPECACHE_LT_OPR
Definition: typcache.h:128
#define NameStr(name)
Definition: c.h:565
Oid varcollid
Definition: primnodes.h:172
void * arg
#define SQL_STR_DOUBLE(ch, escape_backslash)
Definition: c.h:991
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:775
static void deparseReturningList(StringInfo buf, PlannerInfo *root, Index rtindex, Relation rel, bool trig_after_row, List *returningList, List **retrieved_attrs)
Definition: deparse.c:1929
bool contain_mutable_functions(Node *clause)
Definition: clauses.c:881
bool argisrow
Definition: primnodes.h:1189
char aggkind
Definition: primnodes.h:308
char * defname
Definition: parsenodes.h:727
int32 resulttypmod
Definition: primnodes.h:796
Oid opno
Definition: primnodes.h:496
#define SelfItemPointerAttributeNumber
Definition: sysattr.h:21
#define elog
Definition: elog.h:219
List * args
Definition: primnodes.h:502
RelOptInfo * scanrel
Definition: deparse.c:101
CoercionForm relabelformat
Definition: primnodes.h:798
#define BTLessStrategyNumber
Definition: stratnum.h:29
Definition: pg_list.h:45
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:464
RelOptInfo * foreignrel
Definition: deparse.c:100
struct PathTarget * reltarget
Definition: relation.h:596
int16 AttrNumber
Definition: attnum.h:21
#define RelationGetRelid(relation)
Definition: rel.h:425
long val
Definition: informix.c:689
Oid paramtype
Definition: primnodes.h:246
bool constisnull
Definition: primnodes.h:197
bool funcvariadic
Definition: primnodes.h:452
static void printRemotePlaceholder(Oid paramtype, int32 paramtypmod, deparse_expr_cxt *context)
Definition: deparse.c:3075
Expr * refexpr
Definition: primnodes.h:408
static void deparseFuncExpr(FuncExpr *node, deparse_expr_cxt *context)
Definition: deparse.c:2583
Definition: nodes.h:148
int32 vartypmod
Definition: primnodes.h:171
#define RelationGetNamespace(relation)
Definition: rel.h:452