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-2024, PostgreSQL Global Development Group
28  *
29  * IDENTIFICATION
30  * contrib/postgres_fdw/deparse.c
31  *
32  *-------------------------------------------------------------------------
33  */
34 #include "postgres.h"
35 
36 #include "access/htup_details.h"
37 #include "access/sysattr.h"
38 #include "access/table.h"
39 #include "catalog/pg_aggregate.h"
40 #include "catalog/pg_authid.h"
41 #include "catalog/pg_collation.h"
42 #include "catalog/pg_namespace.h"
43 #include "catalog/pg_operator.h"
44 #include "catalog/pg_opfamily.h"
45 #include "catalog/pg_proc.h"
46 #include "catalog/pg_ts_config.h"
47 #include "catalog/pg_ts_dict.h"
48 #include "catalog/pg_type.h"
49 #include "commands/defrem.h"
50 #include "commands/tablecmds.h"
51 #include "nodes/makefuncs.h"
52 #include "nodes/nodeFuncs.h"
53 #include "nodes/plannodes.h"
54 #include "optimizer/optimizer.h"
55 #include "optimizer/prep.h"
56 #include "optimizer/tlist.h"
57 #include "parser/parsetree.h"
58 #include "postgres_fdw.h"
59 #include "utils/builtins.h"
60 #include "utils/lsyscache.h"
61 #include "utils/rel.h"
62 #include "utils/syscache.h"
63 #include "utils/typcache.h"
64 
65 /*
66  * Global context for foreign_expr_walker's search of an expression tree.
67  */
68 typedef struct foreign_glob_cxt
69 {
70  PlannerInfo *root; /* global planner state */
71  RelOptInfo *foreignrel; /* the foreign relation we are planning for */
72  Relids relids; /* relids of base relations in the underlying
73  * scan */
75 
76 /*
77  * Local (per-tree-level) context for foreign_expr_walker's search.
78  * This is concerned with identifying collations used in the expression.
79  */
80 typedef enum
81 {
82  FDW_COLLATE_NONE, /* expression is of a noncollatable type, or
83  * it has default collation that is not
84  * traceable to a foreign Var */
85  FDW_COLLATE_SAFE, /* collation derives from a foreign Var */
86  FDW_COLLATE_UNSAFE, /* collation is non-default and derives from
87  * something other than a foreign Var */
89 
90 typedef struct foreign_loc_cxt
91 {
92  Oid collation; /* OID of current collation, if any */
93  FDWCollateState state; /* state of current collation choice */
95 
96 /*
97  * Context for deparseExpr
98  */
99 typedef struct deparse_expr_cxt
100 {
101  PlannerInfo *root; /* global planner state */
102  RelOptInfo *foreignrel; /* the foreign relation we are planning for */
103  RelOptInfo *scanrel; /* the underlying scan relation. Same as
104  * foreignrel, when that represents a join or
105  * a base relation. */
106  StringInfo buf; /* output buffer to append to */
107  List **params_list; /* exprs that will become remote Params */
109 
110 #define REL_ALIAS_PREFIX "r"
111 /* Handy macro to add relation name qualification */
112 #define ADD_REL_QUALIFIER(buf, varno) \
113  appendStringInfo((buf), "%s%d.", REL_ALIAS_PREFIX, (varno))
114 #define SUBQUERY_REL_ALIAS_PREFIX "s"
115 #define SUBQUERY_COL_ALIAS_PREFIX "c"
116 
117 /*
118  * Functions to determine whether an expression can be evaluated safely on
119  * remote server.
120  */
121 static bool foreign_expr_walker(Node *node,
122  foreign_glob_cxt *glob_cxt,
123  foreign_loc_cxt *outer_cxt,
124  foreign_loc_cxt *case_arg_cxt);
125 static char *deparse_type_name(Oid type_oid, int32 typemod);
126 
127 /*
128  * Functions to construct string representation of a node tree.
129  */
130 static void deparseTargetList(StringInfo buf,
131  RangeTblEntry *rte,
132  Index rtindex,
133  Relation rel,
134  bool is_returning,
135  Bitmapset *attrs_used,
136  bool qualify_col,
137  List **retrieved_attrs);
138 static void deparseExplicitTargetList(List *tlist,
139  bool is_returning,
140  List **retrieved_attrs,
144  Index rtindex, Relation rel,
145  bool trig_after_row,
146  List *withCheckOptionList,
147  List *returningList,
148  List **retrieved_attrs);
149 static void deparseColumnRef(StringInfo buf, int varno, int varattno,
150  RangeTblEntry *rte, bool qualify_col);
151 static void deparseRelation(StringInfo buf, Relation rel);
152 static void deparseExpr(Expr *node, deparse_expr_cxt *context);
153 static void deparseVar(Var *node, deparse_expr_cxt *context);
154 static void deparseConst(Const *node, deparse_expr_cxt *context, int showtype);
155 static void deparseParam(Param *node, deparse_expr_cxt *context);
157 static void deparseFuncExpr(FuncExpr *node, deparse_expr_cxt *context);
158 static void deparseOpExpr(OpExpr *node, deparse_expr_cxt *context);
159 static bool isPlainForeignVar(Expr *node, deparse_expr_cxt *context);
165 static void deparseBoolExpr(BoolExpr *node, deparse_expr_cxt *context);
166 static void deparseNullTest(NullTest *node, deparse_expr_cxt *context);
167 static void deparseCaseExpr(CaseExpr *node, deparse_expr_cxt *context);
169 static void printRemoteParam(int paramindex, Oid paramtype, int32 paramtypmod,
171 static void printRemotePlaceholder(Oid paramtype, int32 paramtypmod,
173 static void deparseSelectSql(List *tlist, bool is_subquery, List **retrieved_attrs,
176 static void appendOrderByClause(List *pathkeys, bool has_final_sort,
179 static void appendConditions(List *exprs, deparse_expr_cxt *context);
181  RelOptInfo *foreignrel, bool use_alias,
182  Index ignore_rel, List **ignore_conds,
183  List **additional_conds,
184  List **params_list);
185 static void appendWhereClause(List *exprs, List *additional_conds,
187 static void deparseFromExpr(List *quals, deparse_expr_cxt *context);
189  RelOptInfo *foreignrel, bool make_subquery,
190  Index ignore_rel, List **ignore_conds,
191  List **additional_conds, List **params_list);
192 static void deparseAggref(Aggref *node, deparse_expr_cxt *context);
193 static void appendGroupByClause(List *tlist, deparse_expr_cxt *context);
194 static void appendOrderBySuffix(Oid sortop, Oid sortcoltype, bool nulls_first,
196 static void appendAggOrderBy(List *orderList, List *targetList,
198 static void appendFunctionName(Oid funcid, deparse_expr_cxt *context);
199 static Node *deparseSortGroupClause(Index ref, List *tlist, bool force_colno,
201 
202 /*
203  * Helper functions
204  */
205 static bool is_subquery_var(Var *node, RelOptInfo *foreignrel,
206  int *relno, int *colno);
207 static void get_relation_column_alias_ids(Var *node, RelOptInfo *foreignrel,
208  int *relno, int *colno);
209 
210 
211 /*
212  * Examine each qual clause in input_conds, and classify them into two groups,
213  * which are returned as two lists:
214  * - remote_conds contains expressions that can be evaluated remotely
215  * - local_conds contains expressions that can't be evaluated remotely
216  */
217 void
219  RelOptInfo *baserel,
220  List *input_conds,
221  List **remote_conds,
222  List **local_conds)
223 {
224  ListCell *lc;
225 
226  *remote_conds = NIL;
227  *local_conds = NIL;
228 
229  foreach(lc, input_conds)
230  {
232 
233  if (is_foreign_expr(root, baserel, ri->clause))
234  *remote_conds = lappend(*remote_conds, ri);
235  else
236  *local_conds = lappend(*local_conds, ri);
237  }
238 }
239 
240 /*
241  * Returns true if given expr is safe to evaluate on the foreign server.
242  */
243 bool
245  RelOptInfo *baserel,
246  Expr *expr)
247 {
248  foreign_glob_cxt glob_cxt;
249  foreign_loc_cxt loc_cxt;
250  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) (baserel->fdw_private);
251 
252  /*
253  * Check that the expression consists of nodes that are safe to execute
254  * remotely.
255  */
256  glob_cxt.root = root;
257  glob_cxt.foreignrel = baserel;
258 
259  /*
260  * For an upper relation, use relids from its underneath scan relation,
261  * because the upperrel's own relids currently aren't set to anything
262  * meaningful by the core code. For other relation, use their own relids.
263  */
264  if (IS_UPPER_REL(baserel))
265  glob_cxt.relids = fpinfo->outerrel->relids;
266  else
267  glob_cxt.relids = baserel->relids;
268  loc_cxt.collation = InvalidOid;
269  loc_cxt.state = FDW_COLLATE_NONE;
270  if (!foreign_expr_walker((Node *) expr, &glob_cxt, &loc_cxt, NULL))
271  return false;
272 
273  /*
274  * If the expression has a valid collation that does not arise from a
275  * foreign var, the expression can not be sent over.
276  */
277  if (loc_cxt.state == FDW_COLLATE_UNSAFE)
278  return false;
279 
280  /*
281  * An expression which includes any mutable functions can't be sent over
282  * because its result is not stable. For example, sending now() remote
283  * side could cause confusion from clock offsets. Future versions might
284  * be able to make this choice with more granularity. (We check this last
285  * because it requires a lot of expensive catalog lookups.)
286  */
287  if (contain_mutable_functions((Node *) expr))
288  return false;
289 
290  /* OK to evaluate on the remote server */
291  return true;
292 }
293 
294 /*
295  * Check if expression is safe to execute remotely, and return true if so.
296  *
297  * In addition, *outer_cxt is updated with collation information.
298  *
299  * case_arg_cxt is NULL if this subexpression is not inside a CASE-with-arg.
300  * Otherwise, it points to the collation info derived from the arg expression,
301  * which must be consulted by any CaseTestExpr.
302  *
303  * We must check that the expression contains only node types we can deparse,
304  * that all types/functions/operators are safe to send (they are "shippable"),
305  * and that all collations used in the expression derive from Vars of the
306  * foreign table. Because of the latter, the logic is pretty close to
307  * assign_collations_walker() in parse_collate.c, though we can assume here
308  * that the given expression is valid. Note function mutability is not
309  * currently considered here.
310  */
311 static bool
313  foreign_glob_cxt *glob_cxt,
314  foreign_loc_cxt *outer_cxt,
315  foreign_loc_cxt *case_arg_cxt)
316 {
317  bool check_type = true;
318  PgFdwRelationInfo *fpinfo;
319  foreign_loc_cxt inner_cxt;
320  Oid collation;
322 
323  /* Need do nothing for empty subexpressions */
324  if (node == NULL)
325  return true;
326 
327  /* May need server info from baserel's fdw_private struct */
328  fpinfo = (PgFdwRelationInfo *) (glob_cxt->foreignrel->fdw_private);
329 
330  /* Set up inner_cxt for possible recursion to child nodes */
331  inner_cxt.collation = InvalidOid;
332  inner_cxt.state = FDW_COLLATE_NONE;
333 
334  switch (nodeTag(node))
335  {
336  case T_Var:
337  {
338  Var *var = (Var *) node;
339 
340  /*
341  * If the Var is from the foreign table, we consider its
342  * collation (if any) safe to use. If it is from another
343  * table, we treat its collation the same way as we would a
344  * Param's collation, ie it's not safe for it to have a
345  * non-default collation.
346  */
347  if (bms_is_member(var->varno, glob_cxt->relids) &&
348  var->varlevelsup == 0)
349  {
350  /* Var belongs to foreign table */
351 
352  /*
353  * System columns other than ctid should not be sent to
354  * the remote, since we don't make any effort to ensure
355  * that local and remote values match (tableoid, in
356  * particular, almost certainly doesn't match).
357  */
358  if (var->varattno < 0 &&
360  return false;
361 
362  /* Else check the collation */
363  collation = var->varcollid;
365  }
366  else
367  {
368  /* Var belongs to some other table */
369  collation = var->varcollid;
370  if (collation == InvalidOid ||
371  collation == DEFAULT_COLLATION_OID)
372  {
373  /*
374  * It's noncollatable, or it's safe to combine with a
375  * collatable foreign Var, so set state to NONE.
376  */
378  }
379  else
380  {
381  /*
382  * Do not fail right away, since the Var might appear
383  * in a collation-insensitive context.
384  */
386  }
387  }
388  }
389  break;
390  case T_Const:
391  {
392  Const *c = (Const *) node;
393 
394  /*
395  * Constants of regproc and related types can't be shipped
396  * unless the referenced object is shippable. But NULL's ok.
397  * (See also the related code in dependency.c.)
398  */
399  if (!c->constisnull)
400  {
401  switch (c->consttype)
402  {
403  case REGPROCOID:
404  case REGPROCEDUREOID:
405  if (!is_shippable(DatumGetObjectId(c->constvalue),
406  ProcedureRelationId, fpinfo))
407  return false;
408  break;
409  case REGOPEROID:
410  case REGOPERATOROID:
411  if (!is_shippable(DatumGetObjectId(c->constvalue),
412  OperatorRelationId, fpinfo))
413  return false;
414  break;
415  case REGCLASSOID:
416  if (!is_shippable(DatumGetObjectId(c->constvalue),
417  RelationRelationId, fpinfo))
418  return false;
419  break;
420  case REGTYPEOID:
421  if (!is_shippable(DatumGetObjectId(c->constvalue),
422  TypeRelationId, fpinfo))
423  return false;
424  break;
425  case REGCOLLATIONOID:
426  if (!is_shippable(DatumGetObjectId(c->constvalue),
427  CollationRelationId, fpinfo))
428  return false;
429  break;
430  case REGCONFIGOID:
431 
432  /*
433  * For text search objects only, we weaken the
434  * normal shippability criterion to allow all OIDs
435  * below FirstNormalObjectId. Without this, none
436  * of the initdb-installed TS configurations would
437  * be shippable, which would be quite annoying.
438  */
439  if (DatumGetObjectId(c->constvalue) >= FirstNormalObjectId &&
440  !is_shippable(DatumGetObjectId(c->constvalue),
441  TSConfigRelationId, fpinfo))
442  return false;
443  break;
444  case REGDICTIONARYOID:
445  if (DatumGetObjectId(c->constvalue) >= FirstNormalObjectId &&
446  !is_shippable(DatumGetObjectId(c->constvalue),
447  TSDictionaryRelationId, fpinfo))
448  return false;
449  break;
450  case REGNAMESPACEOID:
451  if (!is_shippable(DatumGetObjectId(c->constvalue),
452  NamespaceRelationId, fpinfo))
453  return false;
454  break;
455  case REGROLEOID:
456  if (!is_shippable(DatumGetObjectId(c->constvalue),
457  AuthIdRelationId, fpinfo))
458  return false;
459  break;
460  }
461  }
462 
463  /*
464  * If the constant has nondefault collation, either it's of a
465  * non-builtin type, or it reflects folding of a CollateExpr.
466  * It's unsafe to send to the remote unless it's used in a
467  * non-collation-sensitive context.
468  */
469  collation = c->constcollid;
470  if (collation == InvalidOid ||
471  collation == DEFAULT_COLLATION_OID)
473  else
475  }
476  break;
477  case T_Param:
478  {
479  Param *p = (Param *) node;
480 
481  /*
482  * If it's a MULTIEXPR Param, punt. We can't tell from here
483  * whether the referenced sublink/subplan contains any remote
484  * Vars; if it does, handling that is too complicated to
485  * consider supporting at present. Fortunately, MULTIEXPR
486  * Params are not reduced to plain PARAM_EXEC until the end of
487  * planning, so we can easily detect this case. (Normal
488  * PARAM_EXEC Params are safe to ship because their values
489  * come from somewhere else in the plan tree; but a MULTIEXPR
490  * references a sub-select elsewhere in the same targetlist,
491  * so we'd be on the hook to evaluate it somehow if we wanted
492  * to handle such cases as direct foreign updates.)
493  */
494  if (p->paramkind == PARAM_MULTIEXPR)
495  return false;
496 
497  /*
498  * Collation rule is same as for Consts and non-foreign Vars.
499  */
500  collation = p->paramcollid;
501  if (collation == InvalidOid ||
502  collation == DEFAULT_COLLATION_OID)
504  else
506  }
507  break;
508  case T_SubscriptingRef:
509  {
510  SubscriptingRef *sr = (SubscriptingRef *) node;
511 
512  /* Assignment should not be in restrictions. */
513  if (sr->refassgnexpr != NULL)
514  return false;
515 
516  /*
517  * Recurse into the remaining subexpressions. The container
518  * subscripts will not affect collation of the SubscriptingRef
519  * result, so do those first and reset inner_cxt afterwards.
520  */
522  glob_cxt, &inner_cxt, case_arg_cxt))
523  return false;
524  inner_cxt.collation = InvalidOid;
525  inner_cxt.state = FDW_COLLATE_NONE;
527  glob_cxt, &inner_cxt, case_arg_cxt))
528  return false;
529  inner_cxt.collation = InvalidOid;
530  inner_cxt.state = FDW_COLLATE_NONE;
531  if (!foreign_expr_walker((Node *) sr->refexpr,
532  glob_cxt, &inner_cxt, case_arg_cxt))
533  return false;
534 
535  /*
536  * Container subscripting typically yields same collation as
537  * refexpr's, but in case it doesn't, use same logic as for
538  * function nodes.
539  */
540  collation = sr->refcollid;
541  if (collation == InvalidOid)
543  else if (inner_cxt.state == FDW_COLLATE_SAFE &&
544  collation == inner_cxt.collation)
546  else if (collation == DEFAULT_COLLATION_OID)
548  else
550  }
551  break;
552  case T_FuncExpr:
553  {
554  FuncExpr *fe = (FuncExpr *) node;
555 
556  /*
557  * If function used by the expression is not shippable, it
558  * can't be sent to remote because it might have incompatible
559  * semantics on remote side.
560  */
561  if (!is_shippable(fe->funcid, ProcedureRelationId, fpinfo))
562  return false;
563 
564  /*
565  * Recurse to input subexpressions.
566  */
567  if (!foreign_expr_walker((Node *) fe->args,
568  glob_cxt, &inner_cxt, case_arg_cxt))
569  return false;
570 
571  /*
572  * If function's input collation is not derived from a foreign
573  * Var, it can't be sent to remote.
574  */
575  if (fe->inputcollid == InvalidOid)
576  /* OK, inputs are all noncollatable */ ;
577  else if (inner_cxt.state != FDW_COLLATE_SAFE ||
578  fe->inputcollid != inner_cxt.collation)
579  return false;
580 
581  /*
582  * Detect whether node is introducing a collation not derived
583  * from a foreign Var. (If so, we just mark it unsafe for now
584  * rather than immediately returning false, since the parent
585  * node might not care.)
586  */
587  collation = fe->funccollid;
588  if (collation == InvalidOid)
590  else if (inner_cxt.state == FDW_COLLATE_SAFE &&
591  collation == inner_cxt.collation)
593  else if (collation == DEFAULT_COLLATION_OID)
595  else
597  }
598  break;
599  case T_OpExpr:
600  case T_DistinctExpr: /* struct-equivalent to OpExpr */
601  {
602  OpExpr *oe = (OpExpr *) node;
603 
604  /*
605  * Similarly, only shippable operators can be sent to remote.
606  * (If the operator is shippable, we assume its underlying
607  * function is too.)
608  */
609  if (!is_shippable(oe->opno, OperatorRelationId, fpinfo))
610  return false;
611 
612  /*
613  * Recurse to input subexpressions.
614  */
615  if (!foreign_expr_walker((Node *) oe->args,
616  glob_cxt, &inner_cxt, case_arg_cxt))
617  return false;
618 
619  /*
620  * If operator's input collation is not derived from a foreign
621  * Var, it can't be sent to remote.
622  */
623  if (oe->inputcollid == InvalidOid)
624  /* OK, inputs are all noncollatable */ ;
625  else if (inner_cxt.state != FDW_COLLATE_SAFE ||
626  oe->inputcollid != inner_cxt.collation)
627  return false;
628 
629  /* Result-collation handling is same as for functions */
630  collation = oe->opcollid;
631  if (collation == InvalidOid)
633  else if (inner_cxt.state == FDW_COLLATE_SAFE &&
634  collation == inner_cxt.collation)
636  else if (collation == DEFAULT_COLLATION_OID)
638  else
640  }
641  break;
642  case T_ScalarArrayOpExpr:
643  {
644  ScalarArrayOpExpr *oe = (ScalarArrayOpExpr *) node;
645 
646  /*
647  * Again, only shippable operators can be sent to remote.
648  */
649  if (!is_shippable(oe->opno, OperatorRelationId, fpinfo))
650  return false;
651 
652  /*
653  * Recurse to input subexpressions.
654  */
655  if (!foreign_expr_walker((Node *) oe->args,
656  glob_cxt, &inner_cxt, case_arg_cxt))
657  return false;
658 
659  /*
660  * If operator's input collation is not derived from a foreign
661  * Var, it can't be sent to remote.
662  */
663  if (oe->inputcollid == InvalidOid)
664  /* OK, inputs are all noncollatable */ ;
665  else if (inner_cxt.state != FDW_COLLATE_SAFE ||
666  oe->inputcollid != inner_cxt.collation)
667  return false;
668 
669  /* Output is always boolean and so noncollatable. */
670  collation = InvalidOid;
672  }
673  break;
674  case T_RelabelType:
675  {
676  RelabelType *r = (RelabelType *) node;
677 
678  /*
679  * Recurse to input subexpression.
680  */
681  if (!foreign_expr_walker((Node *) r->arg,
682  glob_cxt, &inner_cxt, case_arg_cxt))
683  return false;
684 
685  /*
686  * RelabelType must not introduce a collation not derived from
687  * an input foreign Var (same logic as for a real function).
688  */
689  collation = r->resultcollid;
690  if (collation == InvalidOid)
692  else if (inner_cxt.state == FDW_COLLATE_SAFE &&
693  collation == inner_cxt.collation)
695  else if (collation == DEFAULT_COLLATION_OID)
697  else
699  }
700  break;
701  case T_BoolExpr:
702  {
703  BoolExpr *b = (BoolExpr *) node;
704 
705  /*
706  * Recurse to input subexpressions.
707  */
708  if (!foreign_expr_walker((Node *) b->args,
709  glob_cxt, &inner_cxt, case_arg_cxt))
710  return false;
711 
712  /* Output is always boolean and so noncollatable. */
713  collation = InvalidOid;
715  }
716  break;
717  case T_NullTest:
718  {
719  NullTest *nt = (NullTest *) node;
720 
721  /*
722  * Recurse to input subexpressions.
723  */
724  if (!foreign_expr_walker((Node *) nt->arg,
725  glob_cxt, &inner_cxt, case_arg_cxt))
726  return false;
727 
728  /* Output is always boolean and so noncollatable. */
729  collation = InvalidOid;
731  }
732  break;
733  case T_CaseExpr:
734  {
735  CaseExpr *ce = (CaseExpr *) node;
736  foreign_loc_cxt arg_cxt;
737  foreign_loc_cxt tmp_cxt;
738  ListCell *lc;
739 
740  /*
741  * Recurse to CASE's arg expression, if any. Its collation
742  * has to be saved aside for use while examining CaseTestExprs
743  * within the WHEN expressions.
744  */
745  arg_cxt.collation = InvalidOid;
746  arg_cxt.state = FDW_COLLATE_NONE;
747  if (ce->arg)
748  {
749  if (!foreign_expr_walker((Node *) ce->arg,
750  glob_cxt, &arg_cxt, case_arg_cxt))
751  return false;
752  }
753 
754  /* Examine the CaseWhen subexpressions. */
755  foreach(lc, ce->args)
756  {
757  CaseWhen *cw = lfirst_node(CaseWhen, lc);
758 
759  if (ce->arg)
760  {
761  /*
762  * In a CASE-with-arg, the parser should have produced
763  * WHEN clauses of the form "CaseTestExpr = RHS",
764  * possibly with an implicit coercion inserted above
765  * the CaseTestExpr. However in an expression that's
766  * been through the optimizer, the WHEN clause could
767  * be almost anything (since the equality operator
768  * could have been expanded into an inline function).
769  * In such cases forbid pushdown, because
770  * deparseCaseExpr can't handle it.
771  */
772  Node *whenExpr = (Node *) cw->expr;
773  List *opArgs;
774 
775  if (!IsA(whenExpr, OpExpr))
776  return false;
777 
778  opArgs = ((OpExpr *) whenExpr)->args;
779  if (list_length(opArgs) != 2 ||
781  CaseTestExpr))
782  return false;
783  }
784 
785  /*
786  * Recurse to WHEN expression, passing down the arg info.
787  * Its collation doesn't affect the result (really, it
788  * should be boolean and thus not have a collation).
789  */
790  tmp_cxt.collation = InvalidOid;
791  tmp_cxt.state = FDW_COLLATE_NONE;
792  if (!foreign_expr_walker((Node *) cw->expr,
793  glob_cxt, &tmp_cxt, &arg_cxt))
794  return false;
795 
796  /* Recurse to THEN expression. */
797  if (!foreign_expr_walker((Node *) cw->result,
798  glob_cxt, &inner_cxt, case_arg_cxt))
799  return false;
800  }
801 
802  /* Recurse to ELSE expression. */
803  if (!foreign_expr_walker((Node *) ce->defresult,
804  glob_cxt, &inner_cxt, case_arg_cxt))
805  return false;
806 
807  /*
808  * Detect whether node is introducing a collation not derived
809  * from a foreign Var. (If so, we just mark it unsafe for now
810  * rather than immediately returning false, since the parent
811  * node might not care.) This is the same as for function
812  * nodes, except that the input collation is derived from only
813  * the THEN and ELSE subexpressions.
814  */
815  collation = ce->casecollid;
816  if (collation == InvalidOid)
818  else if (inner_cxt.state == FDW_COLLATE_SAFE &&
819  collation == inner_cxt.collation)
821  else if (collation == DEFAULT_COLLATION_OID)
823  else
825  }
826  break;
827  case T_CaseTestExpr:
828  {
829  CaseTestExpr *c = (CaseTestExpr *) node;
830 
831  /* Punt if we seem not to be inside a CASE arg WHEN. */
832  if (!case_arg_cxt)
833  return false;
834 
835  /*
836  * Otherwise, any nondefault collation attached to the
837  * CaseTestExpr node must be derived from foreign Var(s) in
838  * the CASE arg.
839  */
840  collation = c->collation;
841  if (collation == InvalidOid)
843  else if (case_arg_cxt->state == FDW_COLLATE_SAFE &&
844  collation == case_arg_cxt->collation)
846  else if (collation == DEFAULT_COLLATION_OID)
848  else
850  }
851  break;
852  case T_ArrayExpr:
853  {
854  ArrayExpr *a = (ArrayExpr *) node;
855 
856  /*
857  * Recurse to input subexpressions.
858  */
859  if (!foreign_expr_walker((Node *) a->elements,
860  glob_cxt, &inner_cxt, case_arg_cxt))
861  return false;
862 
863  /*
864  * ArrayExpr must not introduce a collation not derived from
865  * an input foreign Var (same logic as for a function).
866  */
867  collation = a->array_collid;
868  if (collation == InvalidOid)
870  else if (inner_cxt.state == FDW_COLLATE_SAFE &&
871  collation == inner_cxt.collation)
873  else if (collation == DEFAULT_COLLATION_OID)
875  else
877  }
878  break;
879  case T_List:
880  {
881  List *l = (List *) node;
882  ListCell *lc;
883 
884  /*
885  * Recurse to component subexpressions.
886  */
887  foreach(lc, l)
888  {
889  if (!foreign_expr_walker((Node *) lfirst(lc),
890  glob_cxt, &inner_cxt, case_arg_cxt))
891  return false;
892  }
893 
894  /*
895  * When processing a list, collation state just bubbles up
896  * from the list elements.
897  */
898  collation = inner_cxt.collation;
899  state = inner_cxt.state;
900 
901  /* Don't apply exprType() to the list. */
902  check_type = false;
903  }
904  break;
905  case T_Aggref:
906  {
907  Aggref *agg = (Aggref *) node;
908  ListCell *lc;
909 
910  /* Not safe to pushdown when not in grouping context */
911  if (!IS_UPPER_REL(glob_cxt->foreignrel))
912  return false;
913 
914  /* Only non-split aggregates are pushable. */
915  if (agg->aggsplit != AGGSPLIT_SIMPLE)
916  return false;
917 
918  /* As usual, it must be shippable. */
919  if (!is_shippable(agg->aggfnoid, ProcedureRelationId, fpinfo))
920  return false;
921 
922  /*
923  * Recurse to input args. aggdirectargs, aggorder and
924  * aggdistinct are all present in args, so no need to check
925  * their shippability explicitly.
926  */
927  foreach(lc, agg->args)
928  {
929  Node *n = (Node *) lfirst(lc);
930 
931  /* If TargetEntry, extract the expression from it */
932  if (IsA(n, TargetEntry))
933  {
934  TargetEntry *tle = (TargetEntry *) n;
935 
936  n = (Node *) tle->expr;
937  }
938 
939  if (!foreign_expr_walker(n,
940  glob_cxt, &inner_cxt, case_arg_cxt))
941  return false;
942  }
943 
944  /*
945  * For aggorder elements, check whether the sort operator, if
946  * specified, is shippable or not.
947  */
948  if (agg->aggorder)
949  {
950  foreach(lc, agg->aggorder)
951  {
952  SortGroupClause *srt = (SortGroupClause *) lfirst(lc);
953  Oid sortcoltype;
954  TypeCacheEntry *typentry;
955  TargetEntry *tle;
956 
958  agg->args);
959  sortcoltype = exprType((Node *) tle->expr);
960  typentry = lookup_type_cache(sortcoltype,
962  /* Check shippability of non-default sort operator. */
963  if (srt->sortop != typentry->lt_opr &&
964  srt->sortop != typentry->gt_opr &&
965  !is_shippable(srt->sortop, OperatorRelationId,
966  fpinfo))
967  return false;
968  }
969  }
970 
971  /* Check aggregate filter */
972  if (!foreign_expr_walker((Node *) agg->aggfilter,
973  glob_cxt, &inner_cxt, case_arg_cxt))
974  return false;
975 
976  /*
977  * If aggregate's input collation is not derived from a
978  * foreign Var, it can't be sent to remote.
979  */
980  if (agg->inputcollid == InvalidOid)
981  /* OK, inputs are all noncollatable */ ;
982  else if (inner_cxt.state != FDW_COLLATE_SAFE ||
983  agg->inputcollid != inner_cxt.collation)
984  return false;
985 
986  /*
987  * Detect whether node is introducing a collation not derived
988  * from a foreign Var. (If so, we just mark it unsafe for now
989  * rather than immediately returning false, since the parent
990  * node might not care.)
991  */
992  collation = agg->aggcollid;
993  if (collation == InvalidOid)
995  else if (inner_cxt.state == FDW_COLLATE_SAFE &&
996  collation == inner_cxt.collation)
998  else if (collation == DEFAULT_COLLATION_OID)
1000  else
1002  }
1003  break;
1004  default:
1005 
1006  /*
1007  * If it's anything else, assume it's unsafe. This list can be
1008  * expanded later, but don't forget to add deparse support below.
1009  */
1010  return false;
1011  }
1012 
1013  /*
1014  * If result type of given expression is not shippable, it can't be sent
1015  * to remote because it might have incompatible semantics on remote side.
1016  */
1017  if (check_type && !is_shippable(exprType(node), TypeRelationId, fpinfo))
1018  return false;
1019 
1020  /*
1021  * Now, merge my collation information into my parent's state.
1022  */
1023  if (state > outer_cxt->state)
1024  {
1025  /* Override previous parent state */
1026  outer_cxt->collation = collation;
1027  outer_cxt->state = state;
1028  }
1029  else if (state == outer_cxt->state)
1030  {
1031  /* Merge, or detect error if there's a collation conflict */
1032  switch (state)
1033  {
1034  case FDW_COLLATE_NONE:
1035  /* Nothing + nothing is still nothing */
1036  break;
1037  case FDW_COLLATE_SAFE:
1038  if (collation != outer_cxt->collation)
1039  {
1040  /*
1041  * Non-default collation always beats default.
1042  */
1043  if (outer_cxt->collation == DEFAULT_COLLATION_OID)
1044  {
1045  /* Override previous parent state */
1046  outer_cxt->collation = collation;
1047  }
1048  else if (collation != DEFAULT_COLLATION_OID)
1049  {
1050  /*
1051  * Conflict; show state as indeterminate. We don't
1052  * want to "return false" right away, since parent
1053  * node might not care about collation.
1054  */
1055  outer_cxt->state = FDW_COLLATE_UNSAFE;
1056  }
1057  }
1058  break;
1059  case FDW_COLLATE_UNSAFE:
1060  /* We're still conflicted ... */
1061  break;
1062  }
1063  }
1064 
1065  /* It looks OK */
1066  return true;
1067 }
1068 
1069 /*
1070  * Returns true if given expr is something we'd have to send the value of
1071  * to the foreign server.
1072  *
1073  * This should return true when the expression is a shippable node that
1074  * deparseExpr would add to context->params_list. Note that we don't care
1075  * if the expression *contains* such a node, only whether one appears at top
1076  * level. We need this to detect cases where setrefs.c would recognize a
1077  * false match between an fdw_exprs item (which came from the params_list)
1078  * and an entry in fdw_scan_tlist (which we're considering putting the given
1079  * expression into).
1080  */
1081 bool
1083  RelOptInfo *baserel,
1084  Expr *expr)
1085 {
1086  if (expr == NULL)
1087  return false;
1088 
1089  switch (nodeTag(expr))
1090  {
1091  case T_Var:
1092  {
1093  /* It would have to be sent unless it's a foreign Var */
1094  Var *var = (Var *) expr;
1095  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) (baserel->fdw_private);
1096  Relids relids;
1097 
1098  if (IS_UPPER_REL(baserel))
1099  relids = fpinfo->outerrel->relids;
1100  else
1101  relids = baserel->relids;
1102 
1103  if (bms_is_member(var->varno, relids) && var->varlevelsup == 0)
1104  return false; /* foreign Var, so not a param */
1105  else
1106  return true; /* it'd have to be a param */
1107  break;
1108  }
1109  case T_Param:
1110  /* Params always have to be sent to the foreign server */
1111  return true;
1112  default:
1113  break;
1114  }
1115  return false;
1116 }
1117 
1118 /*
1119  * Returns true if it's safe to push down the sort expression described by
1120  * 'pathkey' to the foreign server.
1121  */
1122 bool
1124  RelOptInfo *baserel,
1125  PathKey *pathkey)
1126 {
1127  EquivalenceClass *pathkey_ec = pathkey->pk_eclass;
1128  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) baserel->fdw_private;
1129 
1130  /*
1131  * is_foreign_expr would detect volatile expressions as well, but checking
1132  * ec_has_volatile here saves some cycles.
1133  */
1134  if (pathkey_ec->ec_has_volatile)
1135  return false;
1136 
1137  /* can't push down the sort if the pathkey's opfamily is not shippable */
1138  if (!is_shippable(pathkey->pk_opfamily, OperatorFamilyRelationId, fpinfo))
1139  return false;
1140 
1141  /* can push if a suitable EC member exists */
1142  return (find_em_for_rel(root, pathkey_ec, baserel) != NULL);
1143 }
1144 
1145 /*
1146  * Convert type OID + typmod info into a type name we can ship to the remote
1147  * server. Someplace else had better have verified that this type name is
1148  * expected to be known on the remote end.
1149  *
1150  * This is almost just format_type_with_typemod(), except that if left to its
1151  * own devices, that function will make schema-qualification decisions based
1152  * on the local search_path, which is wrong. We must schema-qualify all
1153  * type names that are not in pg_catalog. We assume here that built-in types
1154  * are all in pg_catalog and need not be qualified; otherwise, qualify.
1155  */
1156 static char *
1157 deparse_type_name(Oid type_oid, int32 typemod)
1158 {
1160 
1161  if (!is_builtin(type_oid))
1162  flags |= FORMAT_TYPE_FORCE_QUALIFY;
1163 
1164  return format_type_extended(type_oid, typemod, flags);
1165 }
1166 
1167 /*
1168  * Build the targetlist for given relation to be deparsed as SELECT clause.
1169  *
1170  * The output targetlist contains the columns that need to be fetched from the
1171  * foreign server for the given relation. If foreignrel is an upper relation,
1172  * then the output targetlist can also contain expressions to be evaluated on
1173  * foreign server.
1174  */
1175 List *
1177 {
1178  List *tlist = NIL;
1179  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
1180  ListCell *lc;
1181 
1182  /*
1183  * For an upper relation, we have already built the target list while
1184  * checking shippability, so just return that.
1185  */
1186  if (IS_UPPER_REL(foreignrel))
1187  return fpinfo->grouped_tlist;
1188 
1189  /*
1190  * We require columns specified in foreignrel->reltarget->exprs and those
1191  * required for evaluating the local conditions.
1192  */
1193  tlist = add_to_flat_tlist(tlist,
1194  pull_var_clause((Node *) foreignrel->reltarget->exprs,
1196  foreach(lc, fpinfo->local_conds)
1197  {
1198  RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
1199 
1200  tlist = add_to_flat_tlist(tlist,
1201  pull_var_clause((Node *) rinfo->clause,
1203  }
1204 
1205  return tlist;
1206 }
1207 
1208 /*
1209  * Deparse SELECT statement for given relation into buf.
1210  *
1211  * tlist contains the list of desired columns to be fetched from foreign server.
1212  * For a base relation fpinfo->attrs_used is used to construct SELECT clause,
1213  * hence the tlist is ignored for a base relation.
1214  *
1215  * remote_conds is the list of conditions to be deparsed into the WHERE clause
1216  * (or, in the case of upper relations, into the HAVING clause).
1217  *
1218  * If params_list is not NULL, it receives a list of Params and other-relation
1219  * Vars used in the clauses; these values must be transmitted to the remote
1220  * server as parameter values.
1221  *
1222  * If params_list is NULL, we're generating the query for EXPLAIN purposes,
1223  * so Params and other-relation Vars should be replaced by dummy values.
1224  *
1225  * pathkeys is the list of pathkeys to order the result by.
1226  *
1227  * is_subquery is the flag to indicate whether to deparse the specified
1228  * relation as a subquery.
1229  *
1230  * List of columns selected is returned in retrieved_attrs.
1231  */
1232 void
1234  List *tlist, List *remote_conds, List *pathkeys,
1235  bool has_final_sort, bool has_limit, bool is_subquery,
1236  List **retrieved_attrs, List **params_list)
1237 {
1239  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) rel->fdw_private;
1240  List *quals;
1241 
1242  /*
1243  * We handle relations for foreign tables, joins between those and upper
1244  * relations.
1245  */
1246  Assert(IS_JOIN_REL(rel) || IS_SIMPLE_REL(rel) || IS_UPPER_REL(rel));
1247 
1248  /* Fill portions of context common to upper, join and base relation */
1249  context.buf = buf;
1250  context.root = root;
1251  context.foreignrel = rel;
1252  context.scanrel = IS_UPPER_REL(rel) ? fpinfo->outerrel : rel;
1253  context.params_list = params_list;
1254 
1255  /* Construct SELECT clause */
1256  deparseSelectSql(tlist, is_subquery, retrieved_attrs, &context);
1257 
1258  /*
1259  * For upper relations, the WHERE clause is built from the remote
1260  * conditions of the underlying scan relation; otherwise, we can use the
1261  * supplied list of remote conditions directly.
1262  */
1263  if (IS_UPPER_REL(rel))
1264  {
1265  PgFdwRelationInfo *ofpinfo;
1266 
1267  ofpinfo = (PgFdwRelationInfo *) fpinfo->outerrel->fdw_private;
1268  quals = ofpinfo->remote_conds;
1269  }
1270  else
1271  quals = remote_conds;
1272 
1273  /* Construct FROM and WHERE clauses */
1274  deparseFromExpr(quals, &context);
1275 
1276  if (IS_UPPER_REL(rel))
1277  {
1278  /* Append GROUP BY clause */
1279  appendGroupByClause(tlist, &context);
1280 
1281  /* Append HAVING clause */
1282  if (remote_conds)
1283  {
1284  appendStringInfoString(buf, " HAVING ");
1285  appendConditions(remote_conds, &context);
1286  }
1287  }
1288 
1289  /* Add ORDER BY clause if we found any useful pathkeys */
1290  if (pathkeys)
1291  appendOrderByClause(pathkeys, has_final_sort, &context);
1292 
1293  /* Add LIMIT clause if necessary */
1294  if (has_limit)
1296 
1297  /* Add any necessary FOR UPDATE/SHARE. */
1299 }
1300 
1301 /*
1302  * Construct a simple SELECT statement that retrieves desired columns
1303  * of the specified foreign table, and append it to "buf". The output
1304  * contains just "SELECT ... ".
1305  *
1306  * We also create an integer List of the columns being retrieved, which is
1307  * returned to *retrieved_attrs, unless we deparse the specified relation
1308  * as a subquery.
1309  *
1310  * tlist is the list of desired columns. is_subquery is the flag to
1311  * indicate whether to deparse the specified relation as a subquery.
1312  * Read prologue of deparseSelectStmtForRel() for details.
1313  */
1314 static void
1315 deparseSelectSql(List *tlist, bool is_subquery, List **retrieved_attrs,
1317 {
1318  StringInfo buf = context->buf;
1319  RelOptInfo *foreignrel = context->foreignrel;
1320  PlannerInfo *root = context->root;
1321  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
1322 
1323  /*
1324  * Construct SELECT list
1325  */
1326  appendStringInfoString(buf, "SELECT ");
1327 
1328  if (is_subquery)
1329  {
1330  /*
1331  * For a relation that is deparsed as a subquery, emit expressions
1332  * specified in the relation's reltarget. Note that since this is for
1333  * the subquery, no need to care about *retrieved_attrs.
1334  */
1336  }
1337  else if (IS_JOIN_REL(foreignrel) || IS_UPPER_REL(foreignrel))
1338  {
1339  /*
1340  * For a join or upper relation the input tlist gives the list of
1341  * columns required to be fetched from the foreign server.
1342  */
1343  deparseExplicitTargetList(tlist, false, retrieved_attrs, context);
1344  }
1345  else
1346  {
1347  /*
1348  * For a base relation fpinfo->attrs_used gives the list of columns
1349  * required to be fetched from the foreign server.
1350  */
1351  RangeTblEntry *rte = planner_rt_fetch(foreignrel->relid, root);
1352 
1353  /*
1354  * Core code already has some lock on each rel being planned, so we
1355  * can use NoLock here.
1356  */
1357  Relation rel = table_open(rte->relid, NoLock);
1358 
1359  deparseTargetList(buf, rte, foreignrel->relid, rel, false,
1360  fpinfo->attrs_used, false, retrieved_attrs);
1361  table_close(rel, NoLock);
1362  }
1363 }
1364 
1365 /*
1366  * Construct a FROM clause and, if needed, a WHERE clause, and append those to
1367  * "buf".
1368  *
1369  * quals is the list of clauses to be included in the WHERE clause.
1370  * (These may or may not include RestrictInfo decoration.)
1371  */
1372 static void
1374 {
1375  StringInfo buf = context->buf;
1376  RelOptInfo *scanrel = context->scanrel;
1377  List *additional_conds = NIL;
1378 
1379  /* For upper relations, scanrel must be either a joinrel or a baserel */
1380  Assert(!IS_UPPER_REL(context->foreignrel) ||
1381  IS_JOIN_REL(scanrel) || IS_SIMPLE_REL(scanrel));
1382 
1383  /* Construct FROM clause */
1384  appendStringInfoString(buf, " FROM ");
1385  deparseFromExprForRel(buf, context->root, scanrel,
1386  (bms_membership(scanrel->relids) == BMS_MULTIPLE),
1387  (Index) 0, NULL, &additional_conds,
1388  context->params_list);
1389  appendWhereClause(quals, additional_conds, context);
1390  if (additional_conds != NIL)
1391  list_free_deep(additional_conds);
1392 }
1393 
1394 /*
1395  * Emit a target list that retrieves the columns specified in attrs_used.
1396  * This is used for both SELECT and RETURNING targetlists; the is_returning
1397  * parameter is true only for a RETURNING targetlist.
1398  *
1399  * The tlist text is appended to buf, and we also create an integer List
1400  * of the columns being retrieved, which is returned to *retrieved_attrs.
1401  *
1402  * If qualify_col is true, add relation alias before the column name.
1403  */
1404 static void
1406  RangeTblEntry *rte,
1407  Index rtindex,
1408  Relation rel,
1409  bool is_returning,
1410  Bitmapset *attrs_used,
1411  bool qualify_col,
1412  List **retrieved_attrs)
1413 {
1414  TupleDesc tupdesc = RelationGetDescr(rel);
1415  bool have_wholerow;
1416  bool first;
1417  int i;
1418 
1419  *retrieved_attrs = NIL;
1420 
1421  /* If there's a whole-row reference, we'll need all the columns. */
1423  attrs_used);
1424 
1425  first = true;
1426  for (i = 1; i <= tupdesc->natts; i++)
1427  {
1428  Form_pg_attribute attr = TupleDescAttr(tupdesc, i - 1);
1429 
1430  /* Ignore dropped attributes. */
1431  if (attr->attisdropped)
1432  continue;
1433 
1434  if (have_wholerow ||
1436  attrs_used))
1437  {
1438  if (!first)
1439  appendStringInfoString(buf, ", ");
1440  else if (is_returning)
1441  appendStringInfoString(buf, " RETURNING ");
1442  first = false;
1443 
1444  deparseColumnRef(buf, rtindex, i, rte, qualify_col);
1445 
1446  *retrieved_attrs = lappend_int(*retrieved_attrs, i);
1447  }
1448  }
1449 
1450  /*
1451  * Add ctid if needed. We currently don't support retrieving any other
1452  * system columns.
1453  */
1455  attrs_used))
1456  {
1457  if (!first)
1458  appendStringInfoString(buf, ", ");
1459  else if (is_returning)
1460  appendStringInfoString(buf, " RETURNING ");
1461  first = false;
1462 
1463  if (qualify_col)
1464  ADD_REL_QUALIFIER(buf, rtindex);
1465  appendStringInfoString(buf, "ctid");
1466 
1467  *retrieved_attrs = lappend_int(*retrieved_attrs,
1469  }
1470 
1471  /* Don't generate bad syntax if no undropped columns */
1472  if (first && !is_returning)
1473  appendStringInfoString(buf, "NULL");
1474 }
1475 
1476 /*
1477  * Deparse the appropriate locking clause (FOR UPDATE or FOR SHARE) for a
1478  * given relation (context->scanrel).
1479  */
1480 static void
1482 {
1483  StringInfo buf = context->buf;
1484  PlannerInfo *root = context->root;
1485  RelOptInfo *rel = context->scanrel;
1486  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) rel->fdw_private;
1487  int relid = -1;
1488 
1489  while ((relid = bms_next_member(rel->relids, relid)) >= 0)
1490  {
1491  /*
1492  * Ignore relation if it appears in a lower subquery. Locking clause
1493  * for such a relation is included in the subquery if necessary.
1494  */
1495  if (bms_is_member(relid, fpinfo->lower_subquery_rels))
1496  continue;
1497 
1498  /*
1499  * Add FOR UPDATE/SHARE if appropriate. We apply locking during the
1500  * initial row fetch, rather than later on as is done for local
1501  * tables. The extra roundtrips involved in trying to duplicate the
1502  * local semantics exactly don't seem worthwhile (see also comments
1503  * for RowMarkType).
1504  *
1505  * Note: because we actually run the query as a cursor, this assumes
1506  * that DECLARE CURSOR ... FOR UPDATE is supported, which it isn't
1507  * before 8.3.
1508  */
1509  if (bms_is_member(relid, root->all_result_relids) &&
1510  (root->parse->commandType == CMD_UPDATE ||
1511  root->parse->commandType == CMD_DELETE))
1512  {
1513  /* Relation is UPDATE/DELETE target, so use FOR UPDATE */
1514  appendStringInfoString(buf, " FOR UPDATE");
1515 
1516  /* Add the relation alias if we are here for a join relation */
1517  if (IS_JOIN_REL(rel))
1518  appendStringInfo(buf, " OF %s%d", REL_ALIAS_PREFIX, relid);
1519  }
1520  else
1521  {
1522  PlanRowMark *rc = get_plan_rowmark(root->rowMarks, relid);
1523 
1524  if (rc)
1525  {
1526  /*
1527  * Relation is specified as a FOR UPDATE/SHARE target, so
1528  * handle that. (But we could also see LCS_NONE, meaning this
1529  * isn't a target relation after all.)
1530  *
1531  * For now, just ignore any [NO] KEY specification, since (a)
1532  * it's not clear what that means for a remote table that we
1533  * don't have complete information about, and (b) it wouldn't
1534  * work anyway on older remote servers. Likewise, we don't
1535  * worry about NOWAIT.
1536  */
1537  switch (rc->strength)
1538  {
1539  case LCS_NONE:
1540  /* No locking needed */
1541  break;
1542  case LCS_FORKEYSHARE:
1543  case LCS_FORSHARE:
1544  appendStringInfoString(buf, " FOR SHARE");
1545  break;
1546  case LCS_FORNOKEYUPDATE:
1547  case LCS_FORUPDATE:
1548  appendStringInfoString(buf, " FOR UPDATE");
1549  break;
1550  }
1551 
1552  /* Add the relation alias if we are here for a join relation */
1553  if (bms_membership(rel->relids) == BMS_MULTIPLE &&
1554  rc->strength != LCS_NONE)
1555  appendStringInfo(buf, " OF %s%d", REL_ALIAS_PREFIX, relid);
1556  }
1557  }
1558  }
1559 }
1560 
1561 /*
1562  * Deparse conditions from the provided list and append them to buf.
1563  *
1564  * The conditions in the list are assumed to be ANDed. This function is used to
1565  * deparse WHERE clauses, JOIN .. ON clauses and HAVING clauses.
1566  *
1567  * Depending on the caller, the list elements might be either RestrictInfos
1568  * or bare clauses.
1569  */
1570 static void
1572 {
1573  int nestlevel;
1574  ListCell *lc;
1575  bool is_first = true;
1576  StringInfo buf = context->buf;
1577 
1578  /* Make sure any constants in the exprs are printed portably */
1579  nestlevel = set_transmission_modes();
1580 
1581  foreach(lc, exprs)
1582  {
1583  Expr *expr = (Expr *) lfirst(lc);
1584 
1585  /* Extract clause from RestrictInfo, if required */
1586  if (IsA(expr, RestrictInfo))
1587  expr = ((RestrictInfo *) expr)->clause;
1588 
1589  /* Connect expressions with "AND" and parenthesize each condition. */
1590  if (!is_first)
1591  appendStringInfoString(buf, " AND ");
1592 
1593  appendStringInfoChar(buf, '(');
1594  deparseExpr(expr, context);
1595  appendStringInfoChar(buf, ')');
1596 
1597  is_first = false;
1598  }
1599 
1600  reset_transmission_modes(nestlevel);
1601 }
1602 
1603 /*
1604  * Append WHERE clause, containing conditions from exprs and additional_conds,
1605  * to context->buf.
1606  */
1607 static void
1609 {
1610  StringInfo buf = context->buf;
1611  bool need_and = false;
1612  ListCell *lc;
1613 
1614  if (exprs != NIL || additional_conds != NIL)
1615  appendStringInfoString(buf, " WHERE ");
1616 
1617  /*
1618  * If there are some filters, append them.
1619  */
1620  if (exprs != NIL)
1621  {
1622  appendConditions(exprs, context);
1623  need_and = true;
1624  }
1625 
1626  /*
1627  * If there are some EXISTS conditions, coming from SEMI-JOINS, append
1628  * them.
1629  */
1630  foreach(lc, additional_conds)
1631  {
1632  if (need_and)
1633  appendStringInfoString(buf, " AND ");
1634  appendStringInfoString(buf, (char *) lfirst(lc));
1635  need_and = true;
1636  }
1637 }
1638 
1639 /* Output join name for given join type */
1640 const char *
1642 {
1643  switch (jointype)
1644  {
1645  case JOIN_INNER:
1646  return "INNER";
1647 
1648  case JOIN_LEFT:
1649  return "LEFT";
1650 
1651  case JOIN_RIGHT:
1652  return "RIGHT";
1653 
1654  case JOIN_FULL:
1655  return "FULL";
1656 
1657  case JOIN_SEMI:
1658  return "SEMI";
1659 
1660  default:
1661  /* Shouldn't come here, but protect from buggy code. */
1662  elog(ERROR, "unsupported join type %d", jointype);
1663  }
1664 
1665  /* Keep compiler happy */
1666  return NULL;
1667 }
1668 
1669 /*
1670  * Deparse given targetlist and append it to context->buf.
1671  *
1672  * tlist is list of TargetEntry's which in turn contain Var nodes.
1673  *
1674  * retrieved_attrs is the list of continuously increasing integers starting
1675  * from 1. It has same number of entries as tlist.
1676  *
1677  * This is used for both SELECT and RETURNING targetlists; the is_returning
1678  * parameter is true only for a RETURNING targetlist.
1679  */
1680 static void
1682  bool is_returning,
1683  List **retrieved_attrs,
1685 {
1686  ListCell *lc;
1687  StringInfo buf = context->buf;
1688  int i = 0;
1689 
1690  *retrieved_attrs = NIL;
1691 
1692  foreach(lc, tlist)
1693  {
1694  TargetEntry *tle = lfirst_node(TargetEntry, lc);
1695 
1696  if (i > 0)
1697  appendStringInfoString(buf, ", ");
1698  else if (is_returning)
1699  appendStringInfoString(buf, " RETURNING ");
1700 
1701  deparseExpr((Expr *) tle->expr, context);
1702 
1703  *retrieved_attrs = lappend_int(*retrieved_attrs, i + 1);
1704  i++;
1705  }
1706 
1707  if (i == 0 && !is_returning)
1708  appendStringInfoString(buf, "NULL");
1709 }
1710 
1711 /*
1712  * Emit expressions specified in the given relation's reltarget.
1713  *
1714  * This is used for deparsing the given relation as a subquery.
1715  */
1716 static void
1718 {
1719  StringInfo buf = context->buf;
1720  RelOptInfo *foreignrel = context->foreignrel;
1721  bool first;
1722  ListCell *lc;
1723 
1724  /* Should only be called in these cases. */
1725  Assert(IS_SIMPLE_REL(foreignrel) || IS_JOIN_REL(foreignrel));
1726 
1727  first = true;
1728  foreach(lc, foreignrel->reltarget->exprs)
1729  {
1730  Node *node = (Node *) lfirst(lc);
1731 
1732  if (!first)
1733  appendStringInfoString(buf, ", ");
1734  first = false;
1735 
1736  deparseExpr((Expr *) node, context);
1737  }
1738 
1739  /* Don't generate bad syntax if no expressions */
1740  if (first)
1741  appendStringInfoString(buf, "NULL");
1742 }
1743 
1744 /*
1745  * Construct FROM clause for given relation
1746  *
1747  * The function constructs ... JOIN ... ON ... for join relation. For a base
1748  * relation it just returns schema-qualified tablename, with the appropriate
1749  * alias if so requested.
1750  *
1751  * 'ignore_rel' is either zero or the RT index of a target relation. In the
1752  * latter case the function constructs FROM clause of UPDATE or USING clause
1753  * of DELETE; it deparses the join relation as if the relation never contained
1754  * the target relation, and creates a List of conditions to be deparsed into
1755  * the top-level WHERE clause, which is returned to *ignore_conds.
1756  *
1757  * 'additional_conds' is a pointer to a list of strings to be appended to
1758  * the WHERE clause, coming from lower-level SEMI-JOINs.
1759  */
1760 static void
1762  bool use_alias, Index ignore_rel, List **ignore_conds,
1763  List **additional_conds, List **params_list)
1764 {
1765  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
1766 
1767  if (IS_JOIN_REL(foreignrel))
1768  {
1769  StringInfoData join_sql_o;
1770  StringInfoData join_sql_i;
1771  RelOptInfo *outerrel = fpinfo->outerrel;
1772  RelOptInfo *innerrel = fpinfo->innerrel;
1773  bool outerrel_is_target = false;
1774  bool innerrel_is_target = false;
1775  List *additional_conds_i = NIL;
1776  List *additional_conds_o = NIL;
1777 
1778  if (ignore_rel > 0 && bms_is_member(ignore_rel, foreignrel->relids))
1779  {
1780  /*
1781  * If this is an inner join, add joinclauses to *ignore_conds and
1782  * set it to empty so that those can be deparsed into the WHERE
1783  * clause. Note that since the target relation can never be
1784  * within the nullable side of an outer join, those could safely
1785  * be pulled up into the WHERE clause (see foreign_join_ok()).
1786  * Note also that since the target relation is only inner-joined
1787  * to any other relation in the query, all conditions in the join
1788  * tree mentioning the target relation could be deparsed into the
1789  * WHERE clause by doing this recursively.
1790  */
1791  if (fpinfo->jointype == JOIN_INNER)
1792  {
1793  *ignore_conds = list_concat(*ignore_conds,
1794  fpinfo->joinclauses);
1795  fpinfo->joinclauses = NIL;
1796  }
1797 
1798  /*
1799  * Check if either of the input relations is the target relation.
1800  */
1801  if (outerrel->relid == ignore_rel)
1802  outerrel_is_target = true;
1803  else if (innerrel->relid == ignore_rel)
1804  innerrel_is_target = true;
1805  }
1806 
1807  /* Deparse outer relation if not the target relation. */
1808  if (!outerrel_is_target)
1809  {
1810  initStringInfo(&join_sql_o);
1811  deparseRangeTblRef(&join_sql_o, root, outerrel,
1812  fpinfo->make_outerrel_subquery,
1813  ignore_rel, ignore_conds, &additional_conds_o,
1814  params_list);
1815 
1816  /*
1817  * If inner relation is the target relation, skip deparsing it.
1818  * Note that since the join of the target relation with any other
1819  * relation in the query is an inner join and can never be within
1820  * the nullable side of an outer join, the join could be
1821  * interchanged with higher-level joins (cf. identity 1 on outer
1822  * join reordering shown in src/backend/optimizer/README), which
1823  * means it's safe to skip the target-relation deparsing here.
1824  */
1825  if (innerrel_is_target)
1826  {
1827  Assert(fpinfo->jointype == JOIN_INNER);
1828  Assert(fpinfo->joinclauses == NIL);
1829  appendBinaryStringInfo(buf, join_sql_o.data, join_sql_o.len);
1830  /* Pass EXISTS conditions to upper level */
1831  if (additional_conds_o != NIL)
1832  {
1833  Assert(*additional_conds == NIL);
1834  *additional_conds = additional_conds_o;
1835  }
1836  return;
1837  }
1838  }
1839 
1840  /* Deparse inner relation if not the target relation. */
1841  if (!innerrel_is_target)
1842  {
1843  initStringInfo(&join_sql_i);
1844  deparseRangeTblRef(&join_sql_i, root, innerrel,
1845  fpinfo->make_innerrel_subquery,
1846  ignore_rel, ignore_conds, &additional_conds_i,
1847  params_list);
1848 
1849  /*
1850  * SEMI-JOIN is deparsed as the EXISTS subquery. It references
1851  * outer and inner relations, so it should be evaluated as the
1852  * condition in the upper-level WHERE clause. We deparse the
1853  * condition and pass it to upper level callers as an
1854  * additional_conds list. Upper level callers are responsible for
1855  * inserting conditions from the list where appropriate.
1856  */
1857  if (fpinfo->jointype == JOIN_SEMI)
1858  {
1861 
1862  /* Construct deparsed condition from this SEMI-JOIN */
1863  initStringInfo(&str);
1864  appendStringInfo(&str, "EXISTS (SELECT NULL FROM %s",
1865  join_sql_i.data);
1866 
1867  context.buf = &str;
1868  context.foreignrel = foreignrel;
1869  context.scanrel = foreignrel;
1870  context.root = root;
1871  context.params_list = params_list;
1872 
1873  /*
1874  * Append SEMI-JOIN clauses and EXISTS conditions from lower
1875  * levels to the current EXISTS subquery
1876  */
1877  appendWhereClause(fpinfo->joinclauses, additional_conds_i, &context);
1878 
1879  /*
1880  * EXISTS conditions, coming from lower join levels, have just
1881  * been processed.
1882  */
1883  if (additional_conds_i != NIL)
1884  {
1885  list_free_deep(additional_conds_i);
1886  additional_conds_i = NIL;
1887  }
1888 
1889  /* Close parentheses for EXISTS subquery */
1890  appendStringInfoChar(&str, ')');
1891 
1892  *additional_conds = lappend(*additional_conds, str.data);
1893  }
1894 
1895  /*
1896  * If outer relation is the target relation, skip deparsing it.
1897  * See the above note about safety.
1898  */
1899  if (outerrel_is_target)
1900  {
1901  Assert(fpinfo->jointype == JOIN_INNER);
1902  Assert(fpinfo->joinclauses == NIL);
1903  appendBinaryStringInfo(buf, join_sql_i.data, join_sql_i.len);
1904  /* Pass EXISTS conditions to the upper call */
1905  if (additional_conds_i != NIL)
1906  {
1907  Assert(*additional_conds == NIL);
1908  *additional_conds = additional_conds_i;
1909  }
1910  return;
1911  }
1912  }
1913 
1914  /* Neither of the relations is the target relation. */
1915  Assert(!outerrel_is_target && !innerrel_is_target);
1916 
1917  /*
1918  * For semijoin FROM clause is deparsed as an outer relation. An inner
1919  * relation and join clauses are converted to EXISTS condition and
1920  * passed to the upper level.
1921  */
1922  if (fpinfo->jointype == JOIN_SEMI)
1923  {
1924  appendBinaryStringInfo(buf, join_sql_o.data, join_sql_o.len);
1925  }
1926  else
1927  {
1928  /*
1929  * For a join relation FROM clause, entry is deparsed as
1930  *
1931  * ((outer relation) <join type> (inner relation) ON
1932  * (joinclauses))
1933  */
1934  appendStringInfo(buf, "(%s %s JOIN %s ON ", join_sql_o.data,
1935  get_jointype_name(fpinfo->jointype), join_sql_i.data);
1936 
1937  /* Append join clause; (TRUE) if no join clause */
1938  if (fpinfo->joinclauses)
1939  {
1941 
1942  context.buf = buf;
1943  context.foreignrel = foreignrel;
1944  context.scanrel = foreignrel;
1945  context.root = root;
1946  context.params_list = params_list;
1947 
1948  appendStringInfoChar(buf, '(');
1950  appendStringInfoChar(buf, ')');
1951  }
1952  else
1953  appendStringInfoString(buf, "(TRUE)");
1954 
1955  /* End the FROM clause entry. */
1956  appendStringInfoChar(buf, ')');
1957  }
1958 
1959  /*
1960  * Construct additional_conds to be passed to the upper caller from
1961  * current level additional_conds and additional_conds, coming from
1962  * inner and outer rels.
1963  */
1964  if (additional_conds_o != NIL)
1965  {
1966  *additional_conds = list_concat(*additional_conds,
1967  additional_conds_o);
1968  list_free(additional_conds_o);
1969  }
1970 
1971  if (additional_conds_i != NIL)
1972  {
1973  *additional_conds = list_concat(*additional_conds,
1974  additional_conds_i);
1975  list_free(additional_conds_i);
1976  }
1977  }
1978  else
1979  {
1980  RangeTblEntry *rte = planner_rt_fetch(foreignrel->relid, root);
1981 
1982  /*
1983  * Core code already has some lock on each rel being planned, so we
1984  * can use NoLock here.
1985  */
1986  Relation rel = table_open(rte->relid, NoLock);
1987 
1988  deparseRelation(buf, rel);
1989 
1990  /*
1991  * Add a unique alias to avoid any conflict in relation names due to
1992  * pulled up subqueries in the query being built for a pushed down
1993  * join.
1994  */
1995  if (use_alias)
1996  appendStringInfo(buf, " %s%d", REL_ALIAS_PREFIX, foreignrel->relid);
1997 
1998  table_close(rel, NoLock);
1999  }
2000 }
2001 
2002 /*
2003  * Append FROM clause entry for the given relation into buf.
2004  * Conditions from lower-level SEMI-JOINs are appended to additional_conds
2005  * and should be added to upper level WHERE clause.
2006  */
2007 static void
2009  bool make_subquery, Index ignore_rel, List **ignore_conds,
2010  List **additional_conds, List **params_list)
2011 {
2012  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
2013 
2014  /* Should only be called in these cases. */
2015  Assert(IS_SIMPLE_REL(foreignrel) || IS_JOIN_REL(foreignrel));
2016 
2017  Assert(fpinfo->local_conds == NIL);
2018 
2019  /* If make_subquery is true, deparse the relation as a subquery. */
2020  if (make_subquery)
2021  {
2022  List *retrieved_attrs;
2023  int ncols;
2024 
2025  /*
2026  * The given relation shouldn't contain the target relation, because
2027  * this should only happen for input relations for a full join, and
2028  * such relations can never contain an UPDATE/DELETE target.
2029  */
2030  Assert(ignore_rel == 0 ||
2031  !bms_is_member(ignore_rel, foreignrel->relids));
2032 
2033  /* Deparse the subquery representing the relation. */
2034  appendStringInfoChar(buf, '(');
2035  deparseSelectStmtForRel(buf, root, foreignrel, NIL,
2036  fpinfo->remote_conds, NIL,
2037  false, false, true,
2038  &retrieved_attrs, params_list);
2039  appendStringInfoChar(buf, ')');
2040 
2041  /* Append the relation alias. */
2043  fpinfo->relation_index);
2044 
2045  /*
2046  * Append the column aliases if needed. Note that the subquery emits
2047  * expressions specified in the relation's reltarget (see
2048  * deparseSubqueryTargetList).
2049  */
2050  ncols = list_length(foreignrel->reltarget->exprs);
2051  if (ncols > 0)
2052  {
2053  int i;
2054 
2055  appendStringInfoChar(buf, '(');
2056  for (i = 1; i <= ncols; i++)
2057  {
2058  if (i > 1)
2059  appendStringInfoString(buf, ", ");
2060 
2062  }
2063  appendStringInfoChar(buf, ')');
2064  }
2065  }
2066  else
2067  deparseFromExprForRel(buf, root, foreignrel, true, ignore_rel,
2068  ignore_conds, additional_conds,
2069  params_list);
2070 }
2071 
2072 /*
2073  * deparse remote INSERT statement
2074  *
2075  * The statement text is appended to buf, and we also create an integer List
2076  * of the columns being retrieved by WITH CHECK OPTION or RETURNING (if any),
2077  * which is returned to *retrieved_attrs.
2078  *
2079  * This also stores end position of the VALUES clause, so that we can rebuild
2080  * an INSERT for a batch of rows later.
2081  */
2082 void
2084  Index rtindex, Relation rel,
2085  List *targetAttrs, bool doNothing,
2086  List *withCheckOptionList, List *returningList,
2087  List **retrieved_attrs, int *values_end_len)
2088 {
2089  TupleDesc tupdesc = RelationGetDescr(rel);
2090  AttrNumber pindex;
2091  bool first;
2092  ListCell *lc;
2093 
2094  appendStringInfoString(buf, "INSERT INTO ");
2095  deparseRelation(buf, rel);
2096 
2097  if (targetAttrs)
2098  {
2099  appendStringInfoChar(buf, '(');
2100 
2101  first = true;
2102  foreach(lc, targetAttrs)
2103  {
2104  int attnum = lfirst_int(lc);
2105 
2106  if (!first)
2107  appendStringInfoString(buf, ", ");
2108  first = false;
2109 
2110  deparseColumnRef(buf, rtindex, attnum, rte, false);
2111  }
2112 
2113  appendStringInfoString(buf, ") VALUES (");
2114 
2115  pindex = 1;
2116  first = true;
2117  foreach(lc, targetAttrs)
2118  {
2119  int attnum = lfirst_int(lc);
2120  Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1);
2121 
2122  if (!first)
2123  appendStringInfoString(buf, ", ");
2124  first = false;
2125 
2126  if (attr->attgenerated)
2127  appendStringInfoString(buf, "DEFAULT");
2128  else
2129  {
2130  appendStringInfo(buf, "$%d", pindex);
2131  pindex++;
2132  }
2133  }
2134 
2135  appendStringInfoChar(buf, ')');
2136  }
2137  else
2138  appendStringInfoString(buf, " DEFAULT VALUES");
2139  *values_end_len = buf->len;
2140 
2141  if (doNothing)
2142  appendStringInfoString(buf, " ON CONFLICT DO NOTHING");
2143 
2144  deparseReturningList(buf, rte, rtindex, rel,
2145  rel->trigdesc && rel->trigdesc->trig_insert_after_row,
2146  withCheckOptionList, returningList, retrieved_attrs);
2147 }
2148 
2149 /*
2150  * rebuild remote INSERT statement
2151  *
2152  * Provided a number of rows in a batch, builds INSERT statement with the
2153  * right number of parameters.
2154  */
2155 void
2157  char *orig_query, List *target_attrs,
2158  int values_end_len, int num_params,
2159  int num_rows)
2160 {
2161  TupleDesc tupdesc = RelationGetDescr(rel);
2162  int i;
2163  int pindex;
2164  bool first;
2165  ListCell *lc;
2166 
2167  /* Make sure the values_end_len is sensible */
2168  Assert((values_end_len > 0) && (values_end_len <= strlen(orig_query)));
2169 
2170  /* Copy up to the end of the first record from the original query */
2171  appendBinaryStringInfo(buf, orig_query, values_end_len);
2172 
2173  /*
2174  * Add records to VALUES clause (we already have parameters for the first
2175  * row, so start at the right offset).
2176  */
2177  pindex = num_params + 1;
2178  for (i = 0; i < num_rows; i++)
2179  {
2180  appendStringInfoString(buf, ", (");
2181 
2182  first = true;
2183  foreach(lc, target_attrs)
2184  {
2185  int attnum = lfirst_int(lc);
2186  Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1);
2187 
2188  if (!first)
2189  appendStringInfoString(buf, ", ");
2190  first = false;
2191 
2192  if (attr->attgenerated)
2193  appendStringInfoString(buf, "DEFAULT");
2194  else
2195  {
2196  appendStringInfo(buf, "$%d", pindex);
2197  pindex++;
2198  }
2199  }
2200 
2201  appendStringInfoChar(buf, ')');
2202  }
2203 
2204  /* Copy stuff after VALUES clause from the original query */
2205  appendStringInfoString(buf, orig_query + values_end_len);
2206 }
2207 
2208 /*
2209  * deparse remote UPDATE statement
2210  *
2211  * The statement text is appended to buf, and we also create an integer List
2212  * of the columns being retrieved by WITH CHECK OPTION or RETURNING (if any),
2213  * which is returned to *retrieved_attrs.
2214  */
2215 void
2217  Index rtindex, Relation rel,
2218  List *targetAttrs,
2219  List *withCheckOptionList, List *returningList,
2220  List **retrieved_attrs)
2221 {
2222  TupleDesc tupdesc = RelationGetDescr(rel);
2223  AttrNumber pindex;
2224  bool first;
2225  ListCell *lc;
2226 
2227  appendStringInfoString(buf, "UPDATE ");
2228  deparseRelation(buf, rel);
2229  appendStringInfoString(buf, " SET ");
2230 
2231  pindex = 2; /* ctid is always the first param */
2232  first = true;
2233  foreach(lc, targetAttrs)
2234  {
2235  int attnum = lfirst_int(lc);
2236  Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1);
2237 
2238  if (!first)
2239  appendStringInfoString(buf, ", ");
2240  first = false;
2241 
2242  deparseColumnRef(buf, rtindex, attnum, rte, false);
2243  if (attr->attgenerated)
2244  appendStringInfoString(buf, " = DEFAULT");
2245  else
2246  {
2247  appendStringInfo(buf, " = $%d", pindex);
2248  pindex++;
2249  }
2250  }
2251  appendStringInfoString(buf, " WHERE ctid = $1");
2252 
2253  deparseReturningList(buf, rte, rtindex, rel,
2254  rel->trigdesc && rel->trigdesc->trig_update_after_row,
2255  withCheckOptionList, returningList, retrieved_attrs);
2256 }
2257 
2258 /*
2259  * deparse remote UPDATE statement
2260  *
2261  * 'buf' is the output buffer to append the statement to
2262  * 'rtindex' is the RT index of the associated target relation
2263  * 'rel' is the relation descriptor for the target relation
2264  * 'foreignrel' is the RelOptInfo for the target relation or the join relation
2265  * containing all base relations in the query
2266  * 'targetlist' is the tlist of the underlying foreign-scan plan node
2267  * (note that this only contains new-value expressions and junk attrs)
2268  * 'targetAttrs' is the target columns of the UPDATE
2269  * 'remote_conds' is the qual clauses that must be evaluated remotely
2270  * '*params_list' is an output list of exprs that will become remote Params
2271  * 'returningList' is the RETURNING targetlist
2272  * '*retrieved_attrs' is an output list of integers of columns being retrieved
2273  * by RETURNING (if any)
2274  */
2275 void
2277  Index rtindex, Relation rel,
2278  RelOptInfo *foreignrel,
2279  List *targetlist,
2280  List *targetAttrs,
2281  List *remote_conds,
2282  List **params_list,
2283  List *returningList,
2284  List **retrieved_attrs)
2285 {
2287  int nestlevel;
2288  bool first;
2289  RangeTblEntry *rte = planner_rt_fetch(rtindex, root);
2290  ListCell *lc,
2291  *lc2;
2292  List *additional_conds = NIL;
2293 
2294  /* Set up context struct for recursion */
2295  context.root = root;
2296  context.foreignrel = foreignrel;
2297  context.scanrel = foreignrel;
2298  context.buf = buf;
2299  context.params_list = params_list;
2300 
2301  appendStringInfoString(buf, "UPDATE ");
2302  deparseRelation(buf, rel);
2303  if (foreignrel->reloptkind == RELOPT_JOINREL)
2304  appendStringInfo(buf, " %s%d", REL_ALIAS_PREFIX, rtindex);
2305  appendStringInfoString(buf, " SET ");
2306 
2307  /* Make sure any constants in the exprs are printed portably */
2308  nestlevel = set_transmission_modes();
2309 
2310  first = true;
2311  forboth(lc, targetlist, lc2, targetAttrs)
2312  {
2313  TargetEntry *tle = lfirst_node(TargetEntry, lc);
2314  int attnum = lfirst_int(lc2);
2315 
2316  /* update's new-value expressions shouldn't be resjunk */
2317  Assert(!tle->resjunk);
2318 
2319  if (!first)
2320  appendStringInfoString(buf, ", ");
2321  first = false;
2322 
2323  deparseColumnRef(buf, rtindex, attnum, rte, false);
2324  appendStringInfoString(buf, " = ");
2325  deparseExpr((Expr *) tle->expr, &context);
2326  }
2327 
2328  reset_transmission_modes(nestlevel);
2329 
2330  if (foreignrel->reloptkind == RELOPT_JOINREL)
2331  {
2332  List *ignore_conds = NIL;
2333 
2334 
2335  appendStringInfoString(buf, " FROM ");
2336  deparseFromExprForRel(buf, root, foreignrel, true, rtindex,
2337  &ignore_conds, &additional_conds, params_list);
2338  remote_conds = list_concat(remote_conds, ignore_conds);
2339  }
2340 
2341  appendWhereClause(remote_conds, additional_conds, &context);
2342 
2343  if (additional_conds != NIL)
2344  list_free_deep(additional_conds);
2345 
2346  if (foreignrel->reloptkind == RELOPT_JOINREL)
2347  deparseExplicitTargetList(returningList, true, retrieved_attrs,
2348  &context);
2349  else
2350  deparseReturningList(buf, rte, rtindex, rel, false,
2351  NIL, returningList, retrieved_attrs);
2352 }
2353 
2354 /*
2355  * deparse remote DELETE statement
2356  *
2357  * The statement text is appended to buf, and we also create an integer List
2358  * of the columns being retrieved by RETURNING (if any), which is returned
2359  * to *retrieved_attrs.
2360  */
2361 void
2363  Index rtindex, Relation rel,
2364  List *returningList,
2365  List **retrieved_attrs)
2366 {
2367  appendStringInfoString(buf, "DELETE FROM ");
2368  deparseRelation(buf, rel);
2369  appendStringInfoString(buf, " WHERE ctid = $1");
2370 
2371  deparseReturningList(buf, rte, rtindex, rel,
2372  rel->trigdesc && rel->trigdesc->trig_delete_after_row,
2373  NIL, returningList, retrieved_attrs);
2374 }
2375 
2376 /*
2377  * deparse remote DELETE statement
2378  *
2379  * 'buf' is the output buffer to append the statement to
2380  * 'rtindex' is the RT index of the associated target relation
2381  * 'rel' is the relation descriptor for the target relation
2382  * 'foreignrel' is the RelOptInfo for the target relation or the join relation
2383  * containing all base relations in the query
2384  * 'remote_conds' is the qual clauses that must be evaluated remotely
2385  * '*params_list' is an output list of exprs that will become remote Params
2386  * 'returningList' is the RETURNING targetlist
2387  * '*retrieved_attrs' is an output list of integers of columns being retrieved
2388  * by RETURNING (if any)
2389  */
2390 void
2392  Index rtindex, Relation rel,
2393  RelOptInfo *foreignrel,
2394  List *remote_conds,
2395  List **params_list,
2396  List *returningList,
2397  List **retrieved_attrs)
2398 {
2400  List *additional_conds = NIL;
2401 
2402  /* Set up context struct for recursion */
2403  context.root = root;
2404  context.foreignrel = foreignrel;
2405  context.scanrel = foreignrel;
2406  context.buf = buf;
2407  context.params_list = params_list;
2408 
2409  appendStringInfoString(buf, "DELETE FROM ");
2410  deparseRelation(buf, rel);
2411  if (foreignrel->reloptkind == RELOPT_JOINREL)
2412  appendStringInfo(buf, " %s%d", REL_ALIAS_PREFIX, rtindex);
2413 
2414  if (foreignrel->reloptkind == RELOPT_JOINREL)
2415  {
2416  List *ignore_conds = NIL;
2417 
2418  appendStringInfoString(buf, " USING ");
2419  deparseFromExprForRel(buf, root, foreignrel, true, rtindex,
2420  &ignore_conds, &additional_conds, params_list);
2421  remote_conds = list_concat(remote_conds, ignore_conds);
2422  }
2423 
2424  appendWhereClause(remote_conds, additional_conds, &context);
2425 
2426  if (additional_conds != NIL)
2427  list_free_deep(additional_conds);
2428 
2429  if (foreignrel->reloptkind == RELOPT_JOINREL)
2430  deparseExplicitTargetList(returningList, true, retrieved_attrs,
2431  &context);
2432  else
2434  rtindex, rel, false,
2435  NIL, returningList, retrieved_attrs);
2436 }
2437 
2438 /*
2439  * Add a RETURNING clause, if needed, to an INSERT/UPDATE/DELETE.
2440  */
2441 static void
2443  Index rtindex, Relation rel,
2444  bool trig_after_row,
2445  List *withCheckOptionList,
2446  List *returningList,
2447  List **retrieved_attrs)
2448 {
2449  Bitmapset *attrs_used = NULL;
2450 
2451  if (trig_after_row)
2452  {
2453  /* whole-row reference acquires all non-system columns */
2454  attrs_used =
2456  }
2457 
2458  if (withCheckOptionList != NIL)
2459  {
2460  /*
2461  * We need the attrs, non-system and system, mentioned in the local
2462  * query's WITH CHECK OPTION list.
2463  *
2464  * Note: we do this to ensure that WCO constraints will be evaluated
2465  * on the data actually inserted/updated on the remote side, which
2466  * might differ from the data supplied by the core code, for example
2467  * as a result of remote triggers.
2468  */
2469  pull_varattnos((Node *) withCheckOptionList, rtindex,
2470  &attrs_used);
2471  }
2472 
2473  if (returningList != NIL)
2474  {
2475  /*
2476  * We need the attrs, non-system and system, mentioned in the local
2477  * query's RETURNING list.
2478  */
2479  pull_varattnos((Node *) returningList, rtindex,
2480  &attrs_used);
2481  }
2482 
2483  if (attrs_used != NULL)
2484  deparseTargetList(buf, rte, rtindex, rel, true, attrs_used, false,
2485  retrieved_attrs);
2486  else
2487  *retrieved_attrs = NIL;
2488 }
2489 
2490 /*
2491  * Construct SELECT statement to acquire size in blocks of given relation.
2492  *
2493  * Note: we use local definition of block size, not remote definition.
2494  * This is perhaps debatable.
2495  *
2496  * Note: pg_relation_size() exists in 8.1 and later.
2497  */
2498 void
2500 {
2502 
2503  /* We'll need the remote relation name as a literal. */
2505  deparseRelation(&relname, rel);
2506 
2507  appendStringInfoString(buf, "SELECT pg_catalog.pg_relation_size(");
2509  appendStringInfo(buf, "::pg_catalog.regclass) / %d", BLCKSZ);
2510 }
2511 
2512 /*
2513  * Construct SELECT statement to acquire the number of rows and the relkind of
2514  * a relation.
2515  *
2516  * Note: we just return the remote server's reltuples value, which might
2517  * be off a good deal, but it doesn't seem worth working harder. See
2518  * comments in postgresAcquireSampleRowsFunc.
2519  */
2520 void
2522 {
2524 
2525  /* We'll need the remote relation name as a literal. */
2527  deparseRelation(&relname, rel);
2528 
2529  appendStringInfoString(buf, "SELECT reltuples, relkind FROM pg_catalog.pg_class WHERE oid = ");
2531  appendStringInfoString(buf, "::pg_catalog.regclass");
2532 }
2533 
2534 /*
2535  * Construct SELECT statement to acquire sample rows of given relation.
2536  *
2537  * SELECT command is appended to buf, and list of columns retrieved
2538  * is returned to *retrieved_attrs.
2539  *
2540  * We only support sampling methods we can decide based on server version.
2541  * Allowing custom TSM modules (like tsm_system_rows) might be useful, but it
2542  * would require detecting which extensions are installed, to allow automatic
2543  * fall-back. Moreover, the methods may use different parameters like number
2544  * of rows (and not sampling rate). So we leave this for future improvements.
2545  *
2546  * Using random() to sample rows on the remote server has the advantage that
2547  * this works on all PostgreSQL versions (unlike TABLESAMPLE), and that it
2548  * does the sampling on the remote side (without transferring everything and
2549  * then discarding most rows).
2550  *
2551  * The disadvantage is that we still have to read all rows and evaluate the
2552  * random(), while TABLESAMPLE (at least with the "system" method) may skip.
2553  * It's not that different from the "bernoulli" method, though.
2554  *
2555  * We could also do "ORDER BY random() LIMIT x", which would always pick
2556  * the expected number of rows, but it requires sorting so it may be much
2557  * more expensive (particularly on large tables, which is what the
2558  * remote sampling is meant to improve).
2559  */
2560 void
2562  PgFdwSamplingMethod sample_method, double sample_frac,
2563  List **retrieved_attrs)
2564 {
2565  Oid relid = RelationGetRelid(rel);
2566  TupleDesc tupdesc = RelationGetDescr(rel);
2567  int i;
2568  char *colname;
2569  List *options;
2570  ListCell *lc;
2571  bool first = true;
2572 
2573  *retrieved_attrs = NIL;
2574 
2575  appendStringInfoString(buf, "SELECT ");
2576  for (i = 0; i < tupdesc->natts; i++)
2577  {
2578  /* Ignore dropped columns. */
2579  if (TupleDescAttr(tupdesc, i)->attisdropped)
2580  continue;
2581 
2582  if (!first)
2583  appendStringInfoString(buf, ", ");
2584  first = false;
2585 
2586  /* Use attribute name or column_name option. */
2587  colname = NameStr(TupleDescAttr(tupdesc, i)->attname);
2588  options = GetForeignColumnOptions(relid, i + 1);
2589 
2590  foreach(lc, options)
2591  {
2592  DefElem *def = (DefElem *) lfirst(lc);
2593 
2594  if (strcmp(def->defname, "column_name") == 0)
2595  {
2596  colname = defGetString(def);
2597  break;
2598  }
2599  }
2600 
2602 
2603  *retrieved_attrs = lappend_int(*retrieved_attrs, i + 1);
2604  }
2605 
2606  /* Don't generate bad syntax for zero-column relation. */
2607  if (first)
2608  appendStringInfoString(buf, "NULL");
2609 
2610  /*
2611  * Construct FROM clause, and perhaps WHERE clause too, depending on the
2612  * selected sampling method.
2613  */
2614  appendStringInfoString(buf, " FROM ");
2615  deparseRelation(buf, rel);
2616 
2617  switch (sample_method)
2618  {
2619  case ANALYZE_SAMPLE_OFF:
2620  /* nothing to do here */
2621  break;
2622 
2623  case ANALYZE_SAMPLE_RANDOM:
2624  appendStringInfo(buf, " WHERE pg_catalog.random() < %f", sample_frac);
2625  break;
2626 
2627  case ANALYZE_SAMPLE_SYSTEM:
2628  appendStringInfo(buf, " TABLESAMPLE SYSTEM(%f)", (100.0 * sample_frac));
2629  break;
2630 
2632  appendStringInfo(buf, " TABLESAMPLE BERNOULLI(%f)", (100.0 * sample_frac));
2633  break;
2634 
2635  case ANALYZE_SAMPLE_AUTO:
2636  /* should have been resolved into actual method */
2637  elog(ERROR, "unexpected sampling method");
2638  break;
2639  }
2640 }
2641 
2642 /*
2643  * Construct a simple "TRUNCATE rel" statement
2644  */
2645 void
2647  List *rels,
2648  DropBehavior behavior,
2649  bool restart_seqs)
2650 {
2651  ListCell *cell;
2652 
2653  appendStringInfoString(buf, "TRUNCATE ");
2654 
2655  foreach(cell, rels)
2656  {
2657  Relation rel = lfirst(cell);
2658 
2659  if (cell != list_head(rels))
2660  appendStringInfoString(buf, ", ");
2661 
2662  deparseRelation(buf, rel);
2663  }
2664 
2665  appendStringInfo(buf, " %s IDENTITY",
2666  restart_seqs ? "RESTART" : "CONTINUE");
2667 
2668  if (behavior == DROP_RESTRICT)
2669  appendStringInfoString(buf, " RESTRICT");
2670  else if (behavior == DROP_CASCADE)
2671  appendStringInfoString(buf, " CASCADE");
2672 }
2673 
2674 /*
2675  * Construct name to use for given column, and emit it into buf.
2676  * If it has a column_name FDW option, use that instead of attribute name.
2677  *
2678  * If qualify_col is true, qualify column name with the alias of relation.
2679  */
2680 static void
2681 deparseColumnRef(StringInfo buf, int varno, int varattno, RangeTblEntry *rte,
2682  bool qualify_col)
2683 {
2684  /* We support fetching the remote side's CTID and OID. */
2685  if (varattno == SelfItemPointerAttributeNumber)
2686  {
2687  if (qualify_col)
2688  ADD_REL_QUALIFIER(buf, varno);
2689  appendStringInfoString(buf, "ctid");
2690  }
2691  else if (varattno < 0)
2692  {
2693  /*
2694  * All other system attributes are fetched as 0, except for table OID,
2695  * which is fetched as the local table OID. However, we must be
2696  * careful; the table could be beneath an outer join, in which case it
2697  * must go to NULL whenever the rest of the row does.
2698  */
2699  Oid fetchval = 0;
2700 
2701  if (varattno == TableOidAttributeNumber)
2702  fetchval = rte->relid;
2703 
2704  if (qualify_col)
2705  {
2706  appendStringInfoString(buf, "CASE WHEN (");
2707  ADD_REL_QUALIFIER(buf, varno);
2708  appendStringInfo(buf, "*)::text IS NOT NULL THEN %u END", fetchval);
2709  }
2710  else
2711  appendStringInfo(buf, "%u", fetchval);
2712  }
2713  else if (varattno == 0)
2714  {
2715  /* Whole row reference */
2716  Relation rel;
2717  Bitmapset *attrs_used;
2718 
2719  /* Required only to be passed down to deparseTargetList(). */
2720  List *retrieved_attrs;
2721 
2722  /*
2723  * The lock on the relation will be held by upper callers, so it's
2724  * fine to open it with no lock here.
2725  */
2726  rel = table_open(rte->relid, NoLock);
2727 
2728  /*
2729  * The local name of the foreign table can not be recognized by the
2730  * foreign server and the table it references on foreign server might
2731  * have different column ordering or different columns than those
2732  * declared locally. Hence we have to deparse whole-row reference as
2733  * ROW(columns referenced locally). Construct this by deparsing a
2734  * "whole row" attribute.
2735  */
2736  attrs_used = bms_add_member(NULL,
2738 
2739  /*
2740  * In case the whole-row reference is under an outer join then it has
2741  * to go NULL whenever the rest of the row goes NULL. Deparsing a join
2742  * query would always involve multiple relations, thus qualify_col
2743  * would be true.
2744  */
2745  if (qualify_col)
2746  {
2747  appendStringInfoString(buf, "CASE WHEN (");
2748  ADD_REL_QUALIFIER(buf, varno);
2749  appendStringInfoString(buf, "*)::text IS NOT NULL THEN ");
2750  }
2751 
2752  appendStringInfoString(buf, "ROW(");
2753  deparseTargetList(buf, rte, varno, rel, false, attrs_used, qualify_col,
2754  &retrieved_attrs);
2755  appendStringInfoChar(buf, ')');
2756 
2757  /* Complete the CASE WHEN statement started above. */
2758  if (qualify_col)
2759  appendStringInfoString(buf, " END");
2760 
2761  table_close(rel, NoLock);
2762  bms_free(attrs_used);
2763  }
2764  else
2765  {
2766  char *colname = NULL;
2767  List *options;
2768  ListCell *lc;
2769 
2770  /* varno must not be any of OUTER_VAR, INNER_VAR and INDEX_VAR. */
2771  Assert(!IS_SPECIAL_VARNO(varno));
2772 
2773  /*
2774  * If it's a column of a foreign table, and it has the column_name FDW
2775  * option, use that value.
2776  */
2777  options = GetForeignColumnOptions(rte->relid, varattno);
2778  foreach(lc, options)
2779  {
2780  DefElem *def = (DefElem *) lfirst(lc);
2781 
2782  if (strcmp(def->defname, "column_name") == 0)
2783  {
2784  colname = defGetString(def);
2785  break;
2786  }
2787  }
2788 
2789  /*
2790  * If it's a column of a regular table or it doesn't have column_name
2791  * FDW option, use attribute name.
2792  */
2793  if (colname == NULL)
2794  colname = get_attname(rte->relid, varattno, false);
2795 
2796  if (qualify_col)
2797  ADD_REL_QUALIFIER(buf, varno);
2798 
2800  }
2801 }
2802 
2803 /*
2804  * Append remote name of specified foreign table to buf.
2805  * Use value of table_name FDW option (if any) instead of relation's name.
2806  * Similarly, schema_name FDW option overrides schema name.
2807  */
2808 static void
2810 {
2811  ForeignTable *table;
2812  const char *nspname = NULL;
2813  const char *relname = NULL;
2814  ListCell *lc;
2815 
2816  /* obtain additional catalog information. */
2817  table = GetForeignTable(RelationGetRelid(rel));
2818 
2819  /*
2820  * Use value of FDW options if any, instead of the name of object itself.
2821  */
2822  foreach(lc, table->options)
2823  {
2824  DefElem *def = (DefElem *) lfirst(lc);
2825 
2826  if (strcmp(def->defname, "schema_name") == 0)
2827  nspname = defGetString(def);
2828  else if (strcmp(def->defname, "table_name") == 0)
2829  relname = defGetString(def);
2830  }
2831 
2832  /*
2833  * Note: we could skip printing the schema name if it's pg_catalog, but
2834  * that doesn't seem worth the trouble.
2835  */
2836  if (nspname == NULL)
2837  nspname = get_namespace_name(RelationGetNamespace(rel));
2838  if (relname == NULL)
2840 
2841  appendStringInfo(buf, "%s.%s",
2843 }
2844 
2845 /*
2846  * Append a SQL string literal representing "val" to buf.
2847  */
2848 void
2850 {
2851  const char *valptr;
2852 
2853  /*
2854  * Rather than making assumptions about the remote server's value of
2855  * standard_conforming_strings, always use E'foo' syntax if there are any
2856  * backslashes. This will fail on remote servers before 8.1, but those
2857  * are long out of support.
2858  */
2859  if (strchr(val, '\\') != NULL)
2861  appendStringInfoChar(buf, '\'');
2862  for (valptr = val; *valptr; valptr++)
2863  {
2864  char ch = *valptr;
2865 
2866  if (SQL_STR_DOUBLE(ch, true))
2869  }
2870  appendStringInfoChar(buf, '\'');
2871 }
2872 
2873 /*
2874  * Deparse given expression into context->buf.
2875  *
2876  * This function must support all the same node types that foreign_expr_walker
2877  * accepts.
2878  *
2879  * Note: unlike ruleutils.c, we just use a simple hard-wired parenthesization
2880  * scheme: anything more complex than a Var, Const, function call or cast
2881  * should be self-parenthesized.
2882  */
2883 static void
2885 {
2886  if (node == NULL)
2887  return;
2888 
2889  switch (nodeTag(node))
2890  {
2891  case T_Var:
2892  deparseVar((Var *) node, context);
2893  break;
2894  case T_Const:
2895  deparseConst((Const *) node, context, 0);
2896  break;
2897  case T_Param:
2898  deparseParam((Param *) node, context);
2899  break;
2900  case T_SubscriptingRef:
2902  break;
2903  case T_FuncExpr:
2904  deparseFuncExpr((FuncExpr *) node, context);
2905  break;
2906  case T_OpExpr:
2907  deparseOpExpr((OpExpr *) node, context);
2908  break;
2909  case T_DistinctExpr:
2911  break;
2912  case T_ScalarArrayOpExpr:
2914  break;
2915  case T_RelabelType:
2917  break;
2918  case T_BoolExpr:
2919  deparseBoolExpr((BoolExpr *) node, context);
2920  break;
2921  case T_NullTest:
2922  deparseNullTest((NullTest *) node, context);
2923  break;
2924  case T_CaseExpr:
2925  deparseCaseExpr((CaseExpr *) node, context);
2926  break;
2927  case T_ArrayExpr:
2928  deparseArrayExpr((ArrayExpr *) node, context);
2929  break;
2930  case T_Aggref:
2931  deparseAggref((Aggref *) node, context);
2932  break;
2933  default:
2934  elog(ERROR, "unsupported expression type for deparse: %d",
2935  (int) nodeTag(node));
2936  break;
2937  }
2938 }
2939 
2940 /*
2941  * Deparse given Var node into context->buf.
2942  *
2943  * If the Var belongs to the foreign relation, just print its remote name.
2944  * Otherwise, it's effectively a Param (and will in fact be a Param at
2945  * run time). Handle it the same way we handle plain Params --- see
2946  * deparseParam for comments.
2947  */
2948 static void
2950 {
2951  Relids relids = context->scanrel->relids;
2952  int relno;
2953  int colno;
2954 
2955  /* Qualify columns when multiple relations are involved. */
2956  bool qualify_col = (bms_membership(relids) == BMS_MULTIPLE);
2957 
2958  /*
2959  * If the Var belongs to the foreign relation that is deparsed as a
2960  * subquery, use the relation and column alias to the Var provided by the
2961  * subquery, instead of the remote name.
2962  */
2963  if (is_subquery_var(node, context->scanrel, &relno, &colno))
2964  {
2965  appendStringInfo(context->buf, "%s%d.%s%d",
2967  SUBQUERY_COL_ALIAS_PREFIX, colno);
2968  return;
2969  }
2970 
2971  if (bms_is_member(node->varno, relids) && node->varlevelsup == 0)
2972  deparseColumnRef(context->buf, node->varno, node->varattno,
2973  planner_rt_fetch(node->varno, context->root),
2974  qualify_col);
2975  else
2976  {
2977  /* Treat like a Param */
2978  if (context->params_list)
2979  {
2980  int pindex = 0;
2981  ListCell *lc;
2982 
2983  /* find its index in params_list */
2984  foreach(lc, *context->params_list)
2985  {
2986  pindex++;
2987  if (equal(node, (Node *) lfirst(lc)))
2988  break;
2989  }
2990  if (lc == NULL)
2991  {
2992  /* not in list, so add it */
2993  pindex++;
2994  *context->params_list = lappend(*context->params_list, node);
2995  }
2996 
2997  printRemoteParam(pindex, node->vartype, node->vartypmod, context);
2998  }
2999  else
3000  {
3001  printRemotePlaceholder(node->vartype, node->vartypmod, context);
3002  }
3003  }
3004 }
3005 
3006 /*
3007  * Deparse given constant value into context->buf.
3008  *
3009  * This function has to be kept in sync with ruleutils.c's get_const_expr.
3010  *
3011  * As in that function, showtype can be -1 to never show "::typename"
3012  * decoration, +1 to always show it, or 0 to show it only if the constant
3013  * wouldn't be assumed to be the right type by default.
3014  *
3015  * In addition, this code allows showtype to be -2 to indicate that we should
3016  * not show "::typename" decoration if the constant is printed as an untyped
3017  * literal or NULL (while in other cases, behaving as for showtype == 0).
3018  */
3019 static void
3021 {
3022  StringInfo buf = context->buf;
3023  Oid typoutput;
3024  bool typIsVarlena;
3025  char *extval;
3026  bool isfloat = false;
3027  bool isstring = false;
3028  bool needlabel;
3029 
3030  if (node->constisnull)
3031  {
3032  appendStringInfoString(buf, "NULL");
3033  if (showtype >= 0)
3034  appendStringInfo(buf, "::%s",
3036  node->consttypmod));
3037  return;
3038  }
3039 
3041  &typoutput, &typIsVarlena);
3042  extval = OidOutputFunctionCall(typoutput, node->constvalue);
3043 
3044  switch (node->consttype)
3045  {
3046  case INT2OID:
3047  case INT4OID:
3048  case INT8OID:
3049  case OIDOID:
3050  case FLOAT4OID:
3051  case FLOAT8OID:
3052  case NUMERICOID:
3053  {
3054  /*
3055  * No need to quote unless it's a special value such as 'NaN'.
3056  * See comments in get_const_expr().
3057  */
3058  if (strspn(extval, "0123456789+-eE.") == strlen(extval))
3059  {
3060  if (extval[0] == '+' || extval[0] == '-')
3061  appendStringInfo(buf, "(%s)", extval);
3062  else
3063  appendStringInfoString(buf, extval);
3064  if (strcspn(extval, "eE.") != strlen(extval))
3065  isfloat = true; /* it looks like a float */
3066  }
3067  else
3068  appendStringInfo(buf, "'%s'", extval);
3069  }
3070  break;
3071  case BITOID:
3072  case VARBITOID:
3073  appendStringInfo(buf, "B'%s'", extval);
3074  break;
3075  case BOOLOID:
3076  if (strcmp(extval, "t") == 0)
3077  appendStringInfoString(buf, "true");
3078  else
3079  appendStringInfoString(buf, "false");
3080  break;
3081  default:
3082  deparseStringLiteral(buf, extval);
3083  isstring = true;
3084  break;
3085  }
3086 
3087  pfree(extval);
3088 
3089  if (showtype == -1)
3090  return; /* never print type label */
3091 
3092  /*
3093  * For showtype == 0, append ::typename unless the constant will be
3094  * implicitly typed as the right type when it is read in.
3095  *
3096  * XXX this code has to be kept in sync with the behavior of the parser,
3097  * especially make_const.
3098  */
3099  switch (node->consttype)
3100  {
3101  case BOOLOID:
3102  case INT4OID:
3103  case UNKNOWNOID:
3104  needlabel = false;
3105  break;
3106  case NUMERICOID:
3107  needlabel = !isfloat || (node->consttypmod >= 0);
3108  break;
3109  default:
3110  if (showtype == -2)
3111  {
3112  /* label unless we printed it as an untyped string */
3113  needlabel = !isstring;
3114  }
3115  else
3116  needlabel = true;
3117  break;
3118  }
3119  if (needlabel || showtype > 0)
3120  appendStringInfo(buf, "::%s",
3122  node->consttypmod));
3123 }
3124 
3125 /*
3126  * Deparse given Param node.
3127  *
3128  * If we're generating the query "for real", add the Param to
3129  * context->params_list if it's not already present, and then use its index
3130  * in that list as the remote parameter number. During EXPLAIN, there's
3131  * no need to identify a parameter number.
3132  */
3133 static void
3135 {
3136  if (context->params_list)
3137  {
3138  int pindex = 0;
3139  ListCell *lc;
3140 
3141  /* find its index in params_list */
3142  foreach(lc, *context->params_list)
3143  {
3144  pindex++;
3145  if (equal(node, (Node *) lfirst(lc)))
3146  break;
3147  }
3148  if (lc == NULL)
3149  {
3150  /* not in list, so add it */
3151  pindex++;
3152  *context->params_list = lappend(*context->params_list, node);
3153  }
3154 
3155  printRemoteParam(pindex, node->paramtype, node->paramtypmod, context);
3156  }
3157  else
3158  {
3159  printRemotePlaceholder(node->paramtype, node->paramtypmod, context);
3160  }
3161 }
3162 
3163 /*
3164  * Deparse a container subscript expression.
3165  */
3166 static void
3168 {
3169  StringInfo buf = context->buf;
3170  ListCell *lowlist_item;
3171  ListCell *uplist_item;
3172 
3173  /* Always parenthesize the expression. */
3174  appendStringInfoChar(buf, '(');
3175 
3176  /*
3177  * Deparse referenced array expression first. If that expression includes
3178  * a cast, we have to parenthesize to prevent the array subscript from
3179  * being taken as typename decoration. We can avoid that in the typical
3180  * case of subscripting a Var, but otherwise do it.
3181  */
3182  if (IsA(node->refexpr, Var))
3183  deparseExpr(node->refexpr, context);
3184  else
3185  {
3186  appendStringInfoChar(buf, '(');
3187  deparseExpr(node->refexpr, context);
3188  appendStringInfoChar(buf, ')');
3189  }
3190 
3191  /* Deparse subscript expressions. */
3192  lowlist_item = list_head(node->reflowerindexpr); /* could be NULL */
3193  foreach(uplist_item, node->refupperindexpr)
3194  {
3195  appendStringInfoChar(buf, '[');
3196  if (lowlist_item)
3197  {
3198  deparseExpr(lfirst(lowlist_item), context);
3199  appendStringInfoChar(buf, ':');
3200  lowlist_item = lnext(node->reflowerindexpr, lowlist_item);
3201  }
3202  deparseExpr(lfirst(uplist_item), context);
3203  appendStringInfoChar(buf, ']');
3204  }
3205 
3206  appendStringInfoChar(buf, ')');
3207 }
3208 
3209 /*
3210  * Deparse a function call.
3211  */
3212 static void
3214 {
3215  StringInfo buf = context->buf;
3216  bool use_variadic;
3217  bool first;
3218  ListCell *arg;
3219 
3220  /*
3221  * If the function call came from an implicit coercion, then just show the
3222  * first argument.
3223  */
3224  if (node->funcformat == COERCE_IMPLICIT_CAST)
3225  {
3226  deparseExpr((Expr *) linitial(node->args), context);
3227  return;
3228  }
3229 
3230  /*
3231  * If the function call came from a cast, then show the first argument
3232  * plus an explicit cast operation.
3233  */
3234  if (node->funcformat == COERCE_EXPLICIT_CAST)
3235  {
3236  Oid rettype = node->funcresulttype;
3237  int32 coercedTypmod;
3238 
3239  /* Get the typmod if this is a length-coercion function */
3240  (void) exprIsLengthCoercion((Node *) node, &coercedTypmod);
3241 
3242  deparseExpr((Expr *) linitial(node->args), context);
3243  appendStringInfo(buf, "::%s",
3244  deparse_type_name(rettype, coercedTypmod));
3245  return;
3246  }
3247 
3248  /* Check if need to print VARIADIC (cf. ruleutils.c) */
3249  use_variadic = node->funcvariadic;
3250 
3251  /*
3252  * Normal function: display as proname(args).
3253  */
3255  appendStringInfoChar(buf, '(');
3256 
3257  /* ... and all the arguments */
3258  first = true;
3259  foreach(arg, node->args)
3260  {
3261  if (!first)
3262  appendStringInfoString(buf, ", ");
3263  if (use_variadic && lnext(node->args, arg) == NULL)
3264  appendStringInfoString(buf, "VARIADIC ");
3266  first = false;
3267  }
3268  appendStringInfoChar(buf, ')');
3269 }
3270 
3271 /*
3272  * Deparse given operator expression. To avoid problems around
3273  * priority of operations, we always parenthesize the arguments.
3274  */
3275 static void
3277 {
3278  StringInfo buf = context->buf;
3279  HeapTuple tuple;
3280  Form_pg_operator form;
3281  Expr *right;
3282  bool canSuppressRightConstCast = false;
3283  char oprkind;
3284 
3285  /* Retrieve information about the operator from system catalog. */
3286  tuple = SearchSysCache1(OPEROID, ObjectIdGetDatum(node->opno));
3287  if (!HeapTupleIsValid(tuple))
3288  elog(ERROR, "cache lookup failed for operator %u", node->opno);
3289  form = (Form_pg_operator) GETSTRUCT(tuple);
3290  oprkind = form->oprkind;
3291 
3292  /* Sanity check. */
3293  Assert((oprkind == 'l' && list_length(node->args) == 1) ||
3294  (oprkind == 'b' && list_length(node->args) == 2));
3295 
3296  right = llast(node->args);
3297 
3298  /* Always parenthesize the expression. */
3299  appendStringInfoChar(buf, '(');
3300 
3301  /* Deparse left operand, if any. */
3302  if (oprkind == 'b')
3303  {
3304  Expr *left = linitial(node->args);
3305  Oid leftType = exprType((Node *) left);
3306  Oid rightType = exprType((Node *) right);
3307  bool canSuppressLeftConstCast = false;
3308 
3309  /*
3310  * When considering a binary operator, if one operand is a Const that
3311  * can be printed as a bare string literal or NULL (i.e., it will look
3312  * like type UNKNOWN to the remote parser), the Const normally
3313  * receives an explicit cast to the operator's input type. However,
3314  * in Const-to-Var comparisons where both operands are of the same
3315  * type, we prefer to suppress the explicit cast, leaving the Const's
3316  * type resolution up to the remote parser. The remote's resolution
3317  * heuristic will assume that an unknown input type being compared to
3318  * a known input type is of that known type as well.
3319  *
3320  * This hack allows some cases to succeed where a remote column is
3321  * declared with a different type in the local (foreign) table. By
3322  * emitting "foreigncol = 'foo'" not "foreigncol = 'foo'::text" or the
3323  * like, we allow the remote parser to pick an "=" operator that's
3324  * compatible with whatever type the remote column really is, such as
3325  * an enum.
3326  *
3327  * We allow cast suppression to happen only when the other operand is
3328  * a plain foreign Var. Although the remote's unknown-type heuristic
3329  * would apply to other cases just as well, we would be taking a
3330  * bigger risk that the inferred type is something unexpected. With
3331  * this restriction, if anything goes wrong it's the user's fault for
3332  * not declaring the local column with the same type as the remote
3333  * column.
3334  */
3335  if (leftType == rightType)
3336  {
3337  if (IsA(left, Const))
3338  canSuppressLeftConstCast = isPlainForeignVar(right, context);
3339  else if (IsA(right, Const))
3340  canSuppressRightConstCast = isPlainForeignVar(left, context);
3341  }
3342 
3343  if (canSuppressLeftConstCast)
3344  deparseConst((Const *) left, context, -2);
3345  else
3346  deparseExpr(left, context);
3347 
3348  appendStringInfoChar(buf, ' ');
3349  }
3350 
3351  /* Deparse operator name. */
3352  deparseOperatorName(buf, form);
3353 
3354  /* Deparse right operand. */
3355  appendStringInfoChar(buf, ' ');
3356 
3357  if (canSuppressRightConstCast)
3358  deparseConst((Const *) right, context, -2);
3359  else
3360  deparseExpr(right, context);
3361 
3362  appendStringInfoChar(buf, ')');
3363 
3364  ReleaseSysCache(tuple);
3365 }
3366 
3367 /*
3368  * Will "node" deparse as a plain foreign Var?
3369  */
3370 static bool
3372 {
3373  /*
3374  * We allow the foreign Var to have an implicit RelabelType, mainly so
3375  * that this'll work with varchar columns. Note that deparseRelabelType
3376  * will not print such a cast, so we're not breaking the restriction that
3377  * the expression print as a plain Var. We won't risk it for an implicit
3378  * cast that requires a function, nor for non-implicit RelabelType; such
3379  * cases seem too likely to involve semantics changes compared to what
3380  * would happen on the remote side.
3381  */
3382  if (IsA(node, RelabelType) &&
3383  ((RelabelType *) node)->relabelformat == COERCE_IMPLICIT_CAST)
3384  node = ((RelabelType *) node)->arg;
3385 
3386  if (IsA(node, Var))
3387  {
3388  /*
3389  * The Var must be one that'll deparse as a foreign column reference
3390  * (cf. deparseVar).
3391  */
3392  Var *var = (Var *) node;
3393  Relids relids = context->scanrel->relids;
3394 
3395  if (bms_is_member(var->varno, relids) && var->varlevelsup == 0)
3396  return true;
3397  }
3398 
3399  return false;
3400 }
3401 
3402 /*
3403  * Print the name of an operator.
3404  */
3405 static void
3407 {
3408  char *opname;
3409 
3410  /* opname is not a SQL identifier, so we should not quote it. */
3411  opname = NameStr(opform->oprname);
3412 
3413  /* Print schema name only if it's not pg_catalog */
3414  if (opform->oprnamespace != PG_CATALOG_NAMESPACE)
3415  {
3416  const char *opnspname;
3417 
3418  opnspname = get_namespace_name(opform->oprnamespace);
3419  /* Print fully qualified operator name. */
3420  appendStringInfo(buf, "OPERATOR(%s.%s)",
3421  quote_identifier(opnspname), opname);
3422  }
3423  else
3424  {
3425  /* Just print operator name. */
3426  appendStringInfoString(buf, opname);
3427  }
3428 }
3429 
3430 /*
3431  * Deparse IS DISTINCT FROM.
3432  */
3433 static void
3435 {
3436  StringInfo buf = context->buf;
3437 
3438  Assert(list_length(node->args) == 2);
3439 
3440  appendStringInfoChar(buf, '(');
3441  deparseExpr(linitial(node->args), context);
3442  appendStringInfoString(buf, " IS DISTINCT FROM ");
3443  deparseExpr(lsecond(node->args), context);
3444  appendStringInfoChar(buf, ')');
3445 }
3446 
3447 /*
3448  * Deparse given ScalarArrayOpExpr expression. To avoid problems
3449  * around priority of operations, we always parenthesize the arguments.
3450  */
3451 static void
3453 {
3454  StringInfo buf = context->buf;
3455  HeapTuple tuple;
3456  Form_pg_operator form;
3457  Expr *arg1;
3458  Expr *arg2;
3459 
3460  /* Retrieve information about the operator from system catalog. */
3461  tuple = SearchSysCache1(OPEROID, ObjectIdGetDatum(node->opno));
3462  if (!HeapTupleIsValid(tuple))
3463  elog(ERROR, "cache lookup failed for operator %u", node->opno);
3464  form = (Form_pg_operator) GETSTRUCT(tuple);
3465 
3466  /* Sanity check. */
3467  Assert(list_length(node->args) == 2);
3468 
3469  /* Always parenthesize the expression. */
3470  appendStringInfoChar(buf, '(');
3471 
3472  /* Deparse left operand. */
3473  arg1 = linitial(node->args);
3474  deparseExpr(arg1, context);
3475  appendStringInfoChar(buf, ' ');
3476 
3477  /* Deparse operator name plus decoration. */
3478  deparseOperatorName(buf, form);
3479  appendStringInfo(buf, " %s (", node->useOr ? "ANY" : "ALL");
3480 
3481  /* Deparse right operand. */
3482  arg2 = lsecond(node->args);
3483  deparseExpr(arg2, context);
3484 
3485  appendStringInfoChar(buf, ')');
3486 
3487  /* Always parenthesize the expression. */
3488  appendStringInfoChar(buf, ')');
3489 
3490  ReleaseSysCache(tuple);
3491 }
3492 
3493 /*
3494  * Deparse a RelabelType (binary-compatible cast) node.
3495  */
3496 static void
3498 {
3499  deparseExpr(node->arg, context);
3500  if (node->relabelformat != COERCE_IMPLICIT_CAST)
3501  appendStringInfo(context->buf, "::%s",
3503  node->resulttypmod));
3504 }
3505 
3506 /*
3507  * Deparse a BoolExpr node.
3508  */
3509 static void
3511 {
3512  StringInfo buf = context->buf;
3513  const char *op = NULL; /* keep compiler quiet */
3514  bool first;
3515  ListCell *lc;
3516 
3517  switch (node->boolop)
3518  {
3519  case AND_EXPR:
3520  op = "AND";
3521  break;
3522  case OR_EXPR:
3523  op = "OR";
3524  break;
3525  case NOT_EXPR:
3526  appendStringInfoString(buf, "(NOT ");
3527  deparseExpr(linitial(node->args), context);
3528  appendStringInfoChar(buf, ')');
3529  return;
3530  }
3531 
3532  appendStringInfoChar(buf, '(');
3533  first = true;
3534  foreach(lc, node->args)
3535  {
3536  if (!first)
3537  appendStringInfo(buf, " %s ", op);
3538  deparseExpr((Expr *) lfirst(lc), context);
3539  first = false;
3540  }
3541  appendStringInfoChar(buf, ')');
3542 }
3543 
3544 /*
3545  * Deparse IS [NOT] NULL expression.
3546  */
3547 static void
3549 {
3550  StringInfo buf = context->buf;
3551 
3552  appendStringInfoChar(buf, '(');
3553  deparseExpr(node->arg, context);
3554 
3555  /*
3556  * For scalar inputs, we prefer to print as IS [NOT] NULL, which is
3557  * shorter and traditional. If it's a rowtype input but we're applying a
3558  * scalar test, must print IS [NOT] DISTINCT FROM NULL to be semantically
3559  * correct.
3560  */
3561  if (node->argisrow || !type_is_rowtype(exprType((Node *) node->arg)))
3562  {
3563  if (node->nulltesttype == IS_NULL)
3564  appendStringInfoString(buf, " IS NULL)");
3565  else
3566  appendStringInfoString(buf, " IS NOT NULL)");
3567  }
3568  else
3569  {
3570  if (node->nulltesttype == IS_NULL)
3571  appendStringInfoString(buf, " IS NOT DISTINCT FROM NULL)");
3572  else
3573  appendStringInfoString(buf, " IS DISTINCT FROM NULL)");
3574  }
3575 }
3576 
3577 /*
3578  * Deparse CASE expression
3579  */
3580 static void
3582 {
3583  StringInfo buf = context->buf;
3584  ListCell *lc;
3585 
3586  appendStringInfoString(buf, "(CASE");
3587 
3588  /* If this is a CASE arg WHEN then emit the arg expression */
3589  if (node->arg != NULL)
3590  {
3591  appendStringInfoChar(buf, ' ');
3592  deparseExpr(node->arg, context);
3593  }
3594 
3595  /* Add each condition/result of the CASE clause */
3596  foreach(lc, node->args)
3597  {
3598  CaseWhen *whenclause = (CaseWhen *) lfirst(lc);
3599 
3600  /* WHEN */
3601  appendStringInfoString(buf, " WHEN ");
3602  if (node->arg == NULL) /* CASE WHEN */
3603  deparseExpr(whenclause->expr, context);
3604  else /* CASE arg WHEN */
3605  {
3606  /* Ignore the CaseTestExpr and equality operator. */
3607  deparseExpr(lsecond(castNode(OpExpr, whenclause->expr)->args),
3608  context);
3609  }
3610 
3611  /* THEN */
3612  appendStringInfoString(buf, " THEN ");
3613  deparseExpr(whenclause->result, context);
3614  }
3615 
3616  /* add ELSE if present */
3617  if (node->defresult != NULL)
3618  {
3619  appendStringInfoString(buf, " ELSE ");
3620  deparseExpr(node->defresult, context);
3621  }
3622 
3623  /* append END */
3624  appendStringInfoString(buf, " END)");
3625 }
3626 
3627 /*
3628  * Deparse ARRAY[...] construct.
3629  */
3630 static void
3632 {
3633  StringInfo buf = context->buf;
3634  bool first = true;
3635  ListCell *lc;
3636 
3637  appendStringInfoString(buf, "ARRAY[");
3638  foreach(lc, node->elements)
3639  {
3640  if (!first)
3641  appendStringInfoString(buf, ", ");
3642  deparseExpr(lfirst(lc), context);
3643  first = false;
3644  }
3645  appendStringInfoChar(buf, ']');
3646 
3647  /* If the array is empty, we need an explicit cast to the array type. */
3648  if (node->elements == NIL)
3649  appendStringInfo(buf, "::%s",
3650  deparse_type_name(node->array_typeid, -1));
3651 }
3652 
3653 /*
3654  * Deparse an Aggref node.
3655  */
3656 static void
3658 {
3659  StringInfo buf = context->buf;
3660  bool use_variadic;
3661 
3662  /* Only basic, non-split aggregation accepted. */
3663  Assert(node->aggsplit == AGGSPLIT_SIMPLE);
3664 
3665  /* Check if need to print VARIADIC (cf. ruleutils.c) */
3666  use_variadic = node->aggvariadic;
3667 
3668  /* Find aggregate name from aggfnoid which is a pg_proc entry */
3670  appendStringInfoChar(buf, '(');
3671 
3672  /* Add DISTINCT */
3673  appendStringInfoString(buf, (node->aggdistinct != NIL) ? "DISTINCT " : "");
3674 
3675  if (AGGKIND_IS_ORDERED_SET(node->aggkind))
3676  {
3677  /* Add WITHIN GROUP (ORDER BY ..) */
3678  ListCell *arg;
3679  bool first = true;
3680 
3681  Assert(!node->aggvariadic);
3682  Assert(node->aggorder != NIL);
3683 
3684  foreach(arg, node->aggdirectargs)
3685  {
3686  if (!first)
3687  appendStringInfoString(buf, ", ");
3688  first = false;
3689 
3691  }
3692 
3693  appendStringInfoString(buf, ") WITHIN GROUP (ORDER BY ");
3694  appendAggOrderBy(node->aggorder, node->args, context);
3695  }
3696  else
3697  {
3698  /* aggstar can be set only in zero-argument aggregates */
3699  if (node->aggstar)
3700  appendStringInfoChar(buf, '*');
3701  else
3702  {
3703  ListCell *arg;
3704  bool first = true;
3705 
3706  /* Add all the arguments */
3707  foreach(arg, node->args)
3708  {
3709  TargetEntry *tle = (TargetEntry *) lfirst(arg);
3710  Node *n = (Node *) tle->expr;
3711 
3712  if (tle->resjunk)
3713  continue;
3714 
3715  if (!first)
3716  appendStringInfoString(buf, ", ");
3717  first = false;
3718 
3719  /* Add VARIADIC */
3720  if (use_variadic && lnext(node->args, arg) == NULL)
3721  appendStringInfoString(buf, "VARIADIC ");
3722 
3723  deparseExpr((Expr *) n, context);
3724  }
3725  }
3726 
3727  /* Add ORDER BY */
3728  if (node->aggorder != NIL)
3729  {
3730  appendStringInfoString(buf, " ORDER BY ");
3731  appendAggOrderBy(node->aggorder, node->args, context);
3732  }
3733  }
3734 
3735  /* Add FILTER (WHERE ..) */
3736  if (node->aggfilter != NULL)
3737  {
3738  appendStringInfoString(buf, ") FILTER (WHERE ");
3739  deparseExpr((Expr *) node->aggfilter, context);
3740  }
3741 
3742  appendStringInfoChar(buf, ')');
3743 }
3744 
3745 /*
3746  * Append ORDER BY within aggregate function.
3747  */
3748 static void
3750 {
3751  StringInfo buf = context->buf;
3752  ListCell *lc;
3753  bool first = true;
3754 
3755  foreach(lc, orderList)
3756  {
3757  SortGroupClause *srt = (SortGroupClause *) lfirst(lc);
3758  Node *sortexpr;
3759 
3760  if (!first)
3761  appendStringInfoString(buf, ", ");
3762  first = false;
3763 
3764  /* Deparse the sort expression proper. */
3765  sortexpr = deparseSortGroupClause(srt->tleSortGroupRef, targetList,
3766  false, context);
3767  /* Add decoration as needed. */
3768  appendOrderBySuffix(srt->sortop, exprType(sortexpr), srt->nulls_first,
3769  context);
3770  }
3771 }
3772 
3773 /*
3774  * Append the ASC, DESC, USING <OPERATOR> and NULLS FIRST / NULLS LAST parts
3775  * of an ORDER BY clause.
3776  */
3777 static void
3778 appendOrderBySuffix(Oid sortop, Oid sortcoltype, bool nulls_first,
3780 {
3781  StringInfo buf = context->buf;
3782  TypeCacheEntry *typentry;
3783 
3784  /* See whether operator is default < or > for sort expr's datatype. */
3785  typentry = lookup_type_cache(sortcoltype,
3787 
3788  if (sortop == typentry->lt_opr)
3789  appendStringInfoString(buf, " ASC");
3790  else if (sortop == typentry->gt_opr)
3791  appendStringInfoString(buf, " DESC");
3792  else
3793  {
3794  HeapTuple opertup;
3795  Form_pg_operator operform;
3796 
3797  appendStringInfoString(buf, " USING ");
3798 
3799  /* Append operator name. */
3800  opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(sortop));
3801  if (!HeapTupleIsValid(opertup))
3802  elog(ERROR, "cache lookup failed for operator %u", sortop);
3803  operform = (Form_pg_operator) GETSTRUCT(opertup);
3804  deparseOperatorName(buf, operform);
3805  ReleaseSysCache(opertup);
3806  }
3807 
3808  if (nulls_first)
3809  appendStringInfoString(buf, " NULLS FIRST");
3810  else
3811  appendStringInfoString(buf, " NULLS LAST");
3812 }
3813 
3814 /*
3815  * Print the representation of a parameter to be sent to the remote side.
3816  *
3817  * Note: we always label the Param's type explicitly rather than relying on
3818  * transmitting a numeric type OID in PQsendQueryParams(). This allows us to
3819  * avoid assuming that types have the same OIDs on the remote side as they
3820  * do locally --- they need only have the same names.
3821  */
3822 static void
3823 printRemoteParam(int paramindex, Oid paramtype, int32 paramtypmod,
3825 {
3826  StringInfo buf = context->buf;
3827  char *ptypename = deparse_type_name(paramtype, paramtypmod);
3828 
3829  appendStringInfo(buf, "$%d::%s", paramindex, ptypename);
3830 }
3831 
3832 /*
3833  * Print the representation of a placeholder for a parameter that will be
3834  * sent to the remote side at execution time.
3835  *
3836  * This is used when we're just trying to EXPLAIN the remote query.
3837  * We don't have the actual value of the runtime parameter yet, and we don't
3838  * want the remote planner to generate a plan that depends on such a value
3839  * anyway. Thus, we can't do something simple like "$1::paramtype".
3840  * Instead, we emit "((SELECT null::paramtype)::paramtype)".
3841  * In all extant versions of Postgres, the planner will see that as an unknown
3842  * constant value, which is what we want. This might need adjustment if we
3843  * ever make the planner flatten scalar subqueries. Note: the reason for the
3844  * apparently useless outer cast is to ensure that the representation as a
3845  * whole will be parsed as an a_expr and not a select_with_parens; the latter
3846  * would do the wrong thing in the context "x = ANY(...)".
3847  */
3848 static void
3849 printRemotePlaceholder(Oid paramtype, int32 paramtypmod,
3851 {
3852  StringInfo buf = context->buf;
3853  char *ptypename = deparse_type_name(paramtype, paramtypmod);
3854 
3855  appendStringInfo(buf, "((SELECT null::%s)::%s)", ptypename, ptypename);
3856 }
3857 
3858 /*
3859  * Deparse GROUP BY clause.
3860  */
3861 static void
3863 {
3864  StringInfo buf = context->buf;
3865  Query *query = context->root->parse;
3866  ListCell *lc;
3867  bool first = true;
3868 
3869  /* Nothing to be done, if there's no GROUP BY clause in the query. */
3870  if (!query->groupClause)
3871  return;
3872 
3873  appendStringInfoString(buf, " GROUP BY ");
3874 
3875  /*
3876  * Queries with grouping sets are not pushed down, so we don't expect
3877  * grouping sets here.
3878  */
3879  Assert(!query->groupingSets);
3880 
3881  /*
3882  * We intentionally print query->groupClause not processed_groupClause,
3883  * leaving it to the remote planner to get rid of any redundant GROUP BY
3884  * items again. This is necessary in case processed_groupClause reduced
3885  * to empty, and in any case the redundancy situation on the remote might
3886  * be different than what we think here.
3887  */
3888  foreach(lc, query->groupClause)
3889  {
3890  SortGroupClause *grp = (SortGroupClause *) lfirst(lc);
3891 
3892  if (!first)
3893  appendStringInfoString(buf, ", ");
3894  first = false;
3895 
3896  deparseSortGroupClause(grp->tleSortGroupRef, tlist, true, context);
3897  }
3898 }
3899 
3900 /*
3901  * Deparse ORDER BY clause defined by the given pathkeys.
3902  *
3903  * The clause should use Vars from context->scanrel if !has_final_sort,
3904  * or from context->foreignrel's targetlist if has_final_sort.
3905  *
3906  * We find a suitable pathkey expression (some earlier step
3907  * should have verified that there is one) and deparse it.
3908  */
3909 static void
3910 appendOrderByClause(List *pathkeys, bool has_final_sort,
3912 {
3913  ListCell *lcell;
3914  int nestlevel;
3915  StringInfo buf = context->buf;
3916  bool gotone = false;
3917 
3918  /* Make sure any constants in the exprs are printed portably */
3919  nestlevel = set_transmission_modes();
3920 
3921  foreach(lcell, pathkeys)
3922  {
3923  PathKey *pathkey = lfirst(lcell);
3924  EquivalenceMember *em;
3925  Expr *em_expr;
3926  Oid oprid;
3927 
3928  if (has_final_sort)
3929  {
3930  /*
3931  * By construction, context->foreignrel is the input relation to
3932  * the final sort.
3933  */
3934  em = find_em_for_rel_target(context->root,
3935  pathkey->pk_eclass,
3936  context->foreignrel);
3937  }
3938  else
3939  em = find_em_for_rel(context->root,
3940  pathkey->pk_eclass,
3941  context->scanrel);
3942 
3943  /*
3944  * We don't expect any error here; it would mean that shippability
3945  * wasn't verified earlier. For the same reason, we don't recheck
3946  * shippability of the sort operator.
3947  */
3948  if (em == NULL)
3949  elog(ERROR, "could not find pathkey item to sort");
3950 
3951  em_expr = em->em_expr;
3952 
3953  /*
3954  * If the member is a Const expression then we needn't add it to the
3955  * ORDER BY clause. This can happen in UNION ALL queries where the
3956  * union child targetlist has a Const. Adding these would be
3957  * wasteful, but also, for INT columns, an integer literal would be
3958  * seen as an ordinal column position rather than a value to sort by.
3959  * deparseConst() does have code to handle this, but it seems less
3960  * effort on all accounts just to skip these for ORDER BY clauses.
3961  */
3962  if (IsA(em_expr, Const))
3963  continue;
3964 
3965  if (!gotone)
3966  {
3967  appendStringInfoString(buf, " ORDER BY ");
3968  gotone = true;
3969  }
3970  else
3971  appendStringInfoString(buf, ", ");
3972 
3973  /*
3974  * Lookup the operator corresponding to the strategy in the opclass.
3975  * The datatype used by the opfamily is not necessarily the same as
3976  * the expression type (for array types for example).
3977  */
3979  em->em_datatype,
3980  em->em_datatype,
3981  pathkey->pk_strategy);
3982  if (!OidIsValid(oprid))
3983  elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
3984  pathkey->pk_strategy, em->em_datatype, em->em_datatype,
3985  pathkey->pk_opfamily);
3986 
3987  deparseExpr(em_expr, context);
3988 
3989  /*
3990  * Here we need to use the expression's actual type to discover
3991  * whether the desired operator will be the default or not.
3992  */
3993  appendOrderBySuffix(oprid, exprType((Node *) em_expr),
3994  pathkey->pk_nulls_first, context);
3995 
3996  }
3997  reset_transmission_modes(nestlevel);
3998 }
3999 
4000 /*
4001  * Deparse LIMIT/OFFSET clause.
4002  */
4003 static void
4005 {
4006  PlannerInfo *root = context->root;
4007  StringInfo buf = context->buf;
4008  int nestlevel;
4009 
4010  /* Make sure any constants in the exprs are printed portably */
4011  nestlevel = set_transmission_modes();
4012 
4013  if (root->parse->limitCount)
4014  {
4015  appendStringInfoString(buf, " LIMIT ");
4016  deparseExpr((Expr *) root->parse->limitCount, context);
4017  }
4018  if (root->parse->limitOffset)
4019  {
4020  appendStringInfoString(buf, " OFFSET ");
4021  deparseExpr((Expr *) root->parse->limitOffset, context);
4022  }
4023 
4024  reset_transmission_modes(nestlevel);
4025 }
4026 
4027 /*
4028  * appendFunctionName
4029  * Deparses function name from given function oid.
4030  */
4031 static void
4033 {
4034  StringInfo buf = context->buf;
4035  HeapTuple proctup;
4036  Form_pg_proc procform;
4037  const char *proname;
4038 
4039  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
4040  if (!HeapTupleIsValid(proctup))
4041  elog(ERROR, "cache lookup failed for function %u", funcid);
4042  procform = (Form_pg_proc) GETSTRUCT(proctup);
4043 
4044  /* Print schema name only if it's not pg_catalog */
4045  if (procform->pronamespace != PG_CATALOG_NAMESPACE)
4046  {
4047  const char *schemaname;
4048 
4049  schemaname = get_namespace_name(procform->pronamespace);
4050  appendStringInfo(buf, "%s.", quote_identifier(schemaname));
4051  }
4052 
4053  /* Always print the function name */
4054  proname = NameStr(procform->proname);
4056 
4057  ReleaseSysCache(proctup);
4058 }
4059 
4060 /*
4061  * Appends a sort or group clause.
4062  *
4063  * Like get_rule_sortgroupclause(), returns the expression tree, so caller
4064  * need not find it again.
4065  */
4066 static Node *
4067 deparseSortGroupClause(Index ref, List *tlist, bool force_colno,
4069 {
4070  StringInfo buf = context->buf;
4071  TargetEntry *tle;
4072  Expr *expr;
4073 
4074  tle = get_sortgroupref_tle(ref, tlist);
4075  expr = tle->expr;
4076 
4077  if (force_colno)
4078  {
4079  /* Use column-number form when requested by caller. */
4080  Assert(!tle->resjunk);
4081  appendStringInfo(buf, "%d", tle->resno);
4082  }
4083  else if (expr && IsA(expr, Const))
4084  {
4085  /*
4086  * Force a typecast here so that we don't emit something like "GROUP
4087  * BY 2", which will be misconstrued as a column position rather than
4088  * a constant.
4089  */
4090  deparseConst((Const *) expr, context, 1);
4091  }
4092  else if (!expr || IsA(expr, Var))
4093  deparseExpr(expr, context);
4094  else
4095  {
4096  /* Always parenthesize the expression. */
4097  appendStringInfoChar(buf, '(');
4098  deparseExpr(expr, context);
4099  appendStringInfoChar(buf, ')');
4100  }
4101 
4102  return (Node *) expr;
4103 }
4104 
4105 
4106 /*
4107  * Returns true if given Var is deparsed as a subquery output column, in
4108  * which case, *relno and *colno are set to the IDs for the relation and
4109  * column alias to the Var provided by the subquery.
4110  */
4111 static bool
4112 is_subquery_var(Var *node, RelOptInfo *foreignrel, int *relno, int *colno)
4113 {
4114  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
4115  RelOptInfo *outerrel = fpinfo->outerrel;
4116  RelOptInfo *innerrel = fpinfo->innerrel;
4117 
4118  /* Should only be called in these cases. */
4119  Assert(IS_SIMPLE_REL(foreignrel) || IS_JOIN_REL(foreignrel));
4120 
4121  /*
4122  * If the given relation isn't a join relation, it doesn't have any lower
4123  * subqueries, so the Var isn't a subquery output column.
4124  */
4125  if (!IS_JOIN_REL(foreignrel))
4126  return false;
4127 
4128  /*
4129  * If the Var doesn't belong to any lower subqueries, it isn't a subquery
4130  * output column.
4131  */
4132  if (!bms_is_member(node->varno, fpinfo->lower_subquery_rels))
4133  return false;
4134 
4135  if (bms_is_member(node->varno, outerrel->relids))
4136  {
4137  /*
4138  * If outer relation is deparsed as a subquery, the Var is an output
4139  * column of the subquery; get the IDs for the relation/column alias.
4140  */
4141  if (fpinfo->make_outerrel_subquery)
4142  {
4143  get_relation_column_alias_ids(node, outerrel, relno, colno);
4144  return true;
4145  }
4146 
4147  /* Otherwise, recurse into the outer relation. */
4148  return is_subquery_var(node, outerrel, relno, colno);
4149  }
4150  else
4151  {
4152  Assert(bms_is_member(node->varno, innerrel->relids));
4153 
4154  /*
4155  * If inner relation is deparsed as a subquery, the Var is an output
4156  * column of the subquery; get the IDs for the relation/column alias.
4157  */
4158  if (fpinfo->make_innerrel_subquery)
4159  {
4160  get_relation_column_alias_ids(node, innerrel, relno, colno);
4161  return true;
4162  }
4163 
4164  /* Otherwise, recurse into the inner relation. */
4165  return is_subquery_var(node, innerrel, relno, colno);
4166  }
4167 }
4168 
4169 /*
4170  * Get the IDs for the relation and column alias to given Var belonging to
4171  * given relation, which are returned into *relno and *colno.
4172  */
4173 static void
4175  int *relno, int *colno)
4176 {
4177  PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
4178  int i;
4179  ListCell *lc;
4180 
4181  /* Get the relation alias ID */
4182  *relno = fpinfo->relation_index;
4183 
4184  /* Get the column alias ID */
4185  i = 1;
4186  foreach(lc, foreignrel->reltarget->exprs)
4187  {
4188  Var *tlvar = (Var *) lfirst(lc);
4189 
4190  /*
4191  * Match reltarget entries only on varno/varattno. Ideally there
4192  * would be some cross-check on varnullingrels, but it's unclear what
4193  * to do exactly; we don't have enough context to know what that value
4194  * should be.
4195  */
4196  if (IsA(tlvar, Var) &&
4197  tlvar->varno == node->varno &&
4198  tlvar->varattno == node->varattno)
4199  {
4200  *colno = i;
4201  return;
4202  }
4203  i++;
4204  }
4205 
4206  /* Shouldn't get here */
4207  elog(ERROR, "unexpected expression in subquery output");
4208 }
int16 AttrNumber
Definition: attnum.h:21
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1306
void bms_free(Bitmapset *a)
Definition: bitmapset.c:239
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:510
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:216
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:815
BMS_Membership bms_membership(const Bitmapset *a)
Definition: bitmapset.c:781
@ BMS_MULTIPLE
Definition: bitmapset.h:73
#define FORMAT_TYPE_TYPEMOD_GIVEN
Definition: builtins.h:124
#define FORMAT_TYPE_FORCE_QUALIFY
Definition: builtins.h:126
#define NameStr(name)
Definition: c.h:746
uint16 bits16
Definition: c.h:514
signed int int32
Definition: c.h:494
#define Assert(condition)
Definition: c.h:858
#define ESCAPE_STRING_SYNTAX
Definition: c.h:1166
#define SQL_STR_DOUBLE(ch, escape_backslash)
Definition: c.h:1163
unsigned int Index
Definition: c.h:614
#define OidIsValid(objectId)
Definition: c.h:775
bool contain_mutable_functions(Node *clause)
Definition: clauses.c:370
char * defGetString(DefElem *def)
Definition: define.c:48
static void deparseRangeTblRef(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel, bool make_subquery, Index ignore_rel, List **ignore_conds, List **additional_conds, List **params_list)
Definition: deparse.c:2008
static void deparseCaseExpr(CaseExpr *node, deparse_expr_cxt *context)
Definition: deparse.c:3581
void deparseAnalyzeSizeSql(StringInfo buf, Relation rel)
Definition: deparse.c:2499
static void deparseBoolExpr(BoolExpr *node, deparse_expr_cxt *context)
Definition: deparse.c:3510
static void appendGroupByClause(List *tlist, deparse_expr_cxt *context)
Definition: deparse.c:3862
static void deparseTargetList(StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, bool is_returning, Bitmapset *attrs_used, bool qualify_col, List **retrieved_attrs)
Definition: deparse.c:1405
#define SUBQUERY_REL_ALIAS_PREFIX
Definition: deparse.c:114
static void deparseFromExpr(List *quals, deparse_expr_cxt *context)
Definition: deparse.c:1373
static Node * deparseSortGroupClause(Index ref, List *tlist, bool force_colno, deparse_expr_cxt *context)
Definition: deparse.c:4067
static void deparseLockingClause(deparse_expr_cxt *context)
Definition: deparse.c:1481
const char * get_jointype_name(JoinType jointype)
Definition: deparse.c:1641
void deparseAnalyzeInfoSql(StringInfo buf, Relation rel)
Definition: deparse.c:2521
static void deparseAggref(Aggref *node, deparse_expr_cxt *context)
Definition: deparse.c:3657
static void appendOrderBySuffix(Oid sortop, Oid sortcoltype, bool nulls_first, deparse_expr_cxt *context)
Definition: deparse.c:3778
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:2391
#define REL_ALIAS_PREFIX
Definition: deparse.c:110
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:2276
struct deparse_expr_cxt deparse_expr_cxt
static void get_relation_column_alias_ids(Var *node, RelOptInfo *foreignrel, int *relno, int *colno)
Definition: deparse.c:4174
FDWCollateState
Definition: deparse.c:81
@ FDW_COLLATE_SAFE
Definition: deparse.c:85
@ FDW_COLLATE_UNSAFE
Definition: deparse.c:86
@ FDW_COLLATE_NONE
Definition: deparse.c:82
static void printRemoteParam(int paramindex, Oid paramtype, int32 paramtypmod, deparse_expr_cxt *context)
Definition: deparse.c:3823
static bool is_subquery_var(Var *node, RelOptInfo *foreignrel, int *relno, int *colno)
Definition: deparse.c:4112
bool is_foreign_param(PlannerInfo *root, RelOptInfo *baserel, Expr *expr)
Definition: deparse.c:1082
static void printRemotePlaceholder(Oid paramtype, int32 paramtypmod, deparse_expr_cxt *context)
Definition: deparse.c:3849
static void appendOrderByClause(List *pathkeys, bool has_final_sort, deparse_expr_cxt *context)
Definition: deparse.c:3910
static bool foreign_expr_walker(Node *node, foreign_glob_cxt *glob_cxt, foreign_loc_cxt *outer_cxt, foreign_loc_cxt *case_arg_cxt)
Definition: deparse.c:312
static void deparseColumnRef(StringInfo buf, int varno, int varattno, RangeTblEntry *rte, bool qualify_col)
Definition: deparse.c:2681
static void deparseRelabelType(RelabelType *node, deparse_expr_cxt *context)
Definition: deparse.c:3497
static void deparseNullTest(NullTest *node, deparse_expr_cxt *context)
Definition: deparse.c:3548
static void deparseOperatorName(StringInfo buf, Form_pg_operator opform)
Definition: deparse.c:3406
static void deparseOpExpr(OpExpr *node, deparse_expr_cxt *context)
Definition: deparse.c:3276
static void deparseConst(Const *node, deparse_expr_cxt *context, int showtype)
Definition: deparse.c:3020
static bool isPlainForeignVar(Expr *node, deparse_expr_cxt *context)
Definition: deparse.c:3371
static void deparseDistinctExpr(DistinctExpr *node, deparse_expr_cxt *context)
Definition: deparse.c:3434
void deparseSelectStmtForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *rel, List *tlist, List *remote_conds, List *pathkeys, bool has_final_sort, bool has_limit, bool is_subquery, List **retrieved_attrs, List **params_list)
Definition: deparse.c:1233
static void deparseFuncExpr(FuncExpr *node, deparse_expr_cxt *context)
Definition: deparse.c:3213
void deparseStringLiteral(StringInfo buf, const char *val)
Definition: deparse.c:2849
void rebuildInsertSql(StringInfo buf, Relation rel, char *orig_query, List *target_attrs, int values_end_len, int num_params, int num_rows)
Definition: deparse.c:2156
struct foreign_glob_cxt foreign_glob_cxt
static void deparseArrayExpr(ArrayExpr *node, deparse_expr_cxt *context)
Definition: deparse.c:3631
void deparseInsertSql(StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, List *targetAttrs, bool doNothing, List *withCheckOptionList, List *returningList, List **retrieved_attrs, int *values_end_len)
Definition: deparse.c:2083
static void deparseReturningList(StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, bool trig_after_row, List *withCheckOptionList, List *returningList, List **retrieved_attrs)
Definition: deparse.c:2442
void deparseUpdateSql(StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, List *targetAttrs, List *withCheckOptionList, List *returningList, List **retrieved_attrs)
Definition: deparse.c:2216
static void deparseVar(Var *node, deparse_expr_cxt *context)
Definition: deparse.c:2949
static void appendFunctionName(Oid funcid, deparse_expr_cxt *context)
Definition: deparse.c:4032
static void appendConditions(List *exprs, deparse_expr_cxt *context)
Definition: deparse.c:1571
struct foreign_loc_cxt foreign_loc_cxt
void deparseDeleteSql(StringInfo buf, RangeTblEntry *rte, Index rtindex, Relation rel, List *returningList, List **retrieved_attrs)
Definition: deparse.c:2362
void deparseAnalyzeSql(StringInfo buf, Relation rel, PgFdwSamplingMethod sample_method, double sample_frac, List **retrieved_attrs)
Definition: deparse.c:2561
static void deparseSubscriptingRef(SubscriptingRef *node, deparse_expr_cxt *context)
Definition: deparse.c:3167
static void deparseRelation(StringInfo buf, Relation rel)
Definition: deparse.c:2809
static void deparseExplicitTargetList(List *tlist, bool is_returning, List **retrieved_attrs, deparse_expr_cxt *context)
Definition: deparse.c:1681
static char * deparse_type_name(Oid type_oid, int32 typemod)
Definition: deparse.c:1157
#define ADD_REL_QUALIFIER(buf, varno)
Definition: deparse.c:112
static void appendLimitClause(deparse_expr_cxt *context)
Definition: deparse.c:4004
static void deparseExpr(Expr *node, deparse_expr_cxt *context)
Definition: deparse.c:2884
bool is_foreign_expr(PlannerInfo *root, RelOptInfo *baserel, Expr *expr)
Definition: deparse.c:244
List * build_tlist_to_deparse(RelOptInfo *foreignrel)
Definition: deparse.c:1176
static void deparseFromExprForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel, bool use_alias, Index ignore_rel, List **ignore_conds, List **additional_conds, List **params_list)
Definition: deparse.c:1761
#define SUBQUERY_COL_ALIAS_PREFIX
Definition: deparse.c:115
void classifyConditions(PlannerInfo *root, RelOptInfo *baserel, List *input_conds, List **remote_conds, List **local_conds)
Definition: deparse.c:218
static void deparseScalarArrayOpExpr(ScalarArrayOpExpr *node, deparse_expr_cxt *context)
Definition: deparse.c:3452
static void appendWhereClause(List *exprs, List *additional_conds, deparse_expr_cxt *context)
Definition: deparse.c:1608
void deparseTruncateSql(StringInfo buf, List *rels, DropBehavior behavior, bool restart_seqs)
Definition: deparse.c:2646
static void deparseSubqueryTargetList(deparse_expr_cxt *context)
Definition: deparse.c:1717
bool is_foreign_pathkey(PlannerInfo *root, RelOptInfo *baserel, PathKey *pathkey)
Definition: deparse.c:1123
static void deparseSelectSql(List *tlist, bool is_subquery, List **retrieved_attrs, deparse_expr_cxt *context)
Definition: deparse.c:1315
static void deparseParam(Param *node, deparse_expr_cxt *context)
Definition: deparse.c:3134
static void appendAggOrderBy(List *orderList, List *targetList, deparse_expr_cxt *context)
Definition: deparse.c:3749
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:223
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1763
ForeignTable * GetForeignTable(Oid relid)
Definition: foreign.c:253
List * GetForeignColumnOptions(Oid relid, AttrNumber attnum)
Definition: foreign.c:291
char * format_type_extended(Oid type_oid, int32 typemod, bits16 flags)
Definition: format_type.c:112
const char * str
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
long val
Definition: informix.c:670
int b
Definition: isn.c:70
int a
Definition: isn.c:69
int i
Definition: isn.c:73
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
List * lappend(List *list, void *datum)
Definition: list.c:339
List * lappend_int(List *list, int datum)
Definition: list.c:357
void list_free(List *list)
Definition: list.c:1546
List * list_concat(List *list1, const List *list2)
Definition: list.c:561
void list_free_deep(List *list)
Definition: list.c:1560
#define NoLock
Definition: lockdefs.h:34
@ LCS_FORUPDATE
Definition: lockoptions.h:27
@ LCS_NONE
Definition: lockoptions.h:23
@ LCS_FORSHARE
Definition: lockoptions.h:25
@ LCS_FORKEYSHARE
Definition: lockoptions.h:24
@ LCS_FORNOKEYUPDATE
Definition: lockoptions.h:26
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2655
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3366
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2907
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition: lsyscache.c:166
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:827
void pfree(void *pointer)
Definition: mcxt.c:1520
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
bool exprIsLengthCoercion(const Node *expr, int32 *coercedTypmod)
Definition: nodeFuncs.c:552
Node * strip_implicit_coercions(Node *node)
Definition: nodeFuncs.c:700
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
#define nodeTag(nodeptr)
Definition: nodes.h:133
@ CMD_DELETE
Definition: nodes.h:268
@ CMD_UPDATE
Definition: nodes.h:266
@ AGGSPLIT_SIMPLE
Definition: nodes.h:376
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
JoinType
Definition: nodes.h:288
@ JOIN_SEMI
Definition: nodes.h:307
@ JOIN_FULL
Definition: nodes.h:295
@ JOIN_INNER
Definition: nodes.h:293
@ JOIN_RIGHT
Definition: nodes.h:296
@ JOIN_LEFT
Definition: nodes.h:294
#define PVC_RECURSE_PLACEHOLDERS
Definition: optimizer.h:191
Oid oprid(Operator op)
Definition: parse_oper.c:238
DropBehavior
Definition: parsenodes.h:2335
@ DROP_CASCADE
Definition: parsenodes.h:2337
@ DROP_RESTRICT
Definition: parsenodes.h:2336
#define IS_SIMPLE_REL(rel)
Definition: pathnodes.h:829
#define IS_JOIN_REL(rel)
Definition: pathnodes.h:834
#define planner_rt_fetch(rti, root)
Definition: pathnodes.h:560
@ RELOPT_JOINREL
Definition: pathnodes.h:818
#define IS_UPPER_REL(rel)
Definition: pathnodes.h:839
NameData attname
Definition: pg_attribute.h:41
int16 attnum
Definition: pg_attribute.h:74
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
void * arg
NameData relname
Definition: pg_class.h:38
while(p+4<=pend)
#define lfirst(lc)
Definition: pg_list.h:172
#define llast(l)
Definition: pg_list.h:198
#define lfirst_node(type, lc)
Definition: pg_list.h:176
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:518
#define lfirst_int(lc)
Definition: pg_list.h:173
static ListCell * list_head(const List *l)
Definition: pg_list.h:128
#define linitial(l)
Definition: pg_list.h:178
#define lsecond(l)
Definition: pg_list.h:183
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:343
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:83
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
NameData proname
Definition: pg_proc.h:35
static char ** options
static char * buf
Definition: pg_test_fsync.c:73
static Oid DatumGetObjectId(Datum X)
Definition: postgres.h:242
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
void reset_transmission_modes(int nestlevel)
int set_transmission_modes(void)
EquivalenceMember * find_em_for_rel(PlannerInfo *root, EquivalenceClass *ec, RelOptInfo *rel)
EquivalenceMember * find_em_for_rel_target(PlannerInfo *root, EquivalenceClass *ec, RelOptInfo *rel)
bool is_shippable(Oid objectId, Oid classId, PgFdwRelationInfo *fpinfo)
Definition: shippable.c:162
bool is_builtin(Oid objectId)
Definition: shippable.c:152
PgFdwSamplingMethod
Definition: postgres_fdw.h:145
@ ANALYZE_SAMPLE_AUTO
Definition: postgres_fdw.h:147
@ ANALYZE_SAMPLE_OFF
Definition: postgres_fdw.h:146
@ ANALYZE_SAMPLE_BERNOULLI
Definition: postgres_fdw.h:150
@ ANALYZE_SAMPLE_SYSTEM
Definition: postgres_fdw.h:149
@ ANALYZE_SAMPLE_RANDOM
Definition: postgres_fdw.h:148
char * c
static int fe(enum e x)
Definition: preproc-init.c:111
PlanRowMark * get_plan_rowmark(List *rowmarks, Index rtindex)
Definition: preptlist.c:509
@ AND_EXPR
Definition: primnodes.h:901
@ OR_EXPR
Definition: primnodes.h:901
@ NOT_EXPR
Definition: primnodes.h:901
@ PARAM_MULTIEXPR
Definition: primnodes.h:370
#define IS_SPECIAL_VARNO(varno)
Definition: primnodes.h:241
@ COERCE_IMPLICIT_CAST
Definition: primnodes.h:706
@ COERCE_EXPLICIT_CAST
Definition: primnodes.h:705
@ IS_NULL
Definition: primnodes.h:1924
tree context
Definition: radixtree.h:1833
tree ctl root
Definition: radixtree.h:1884
#define RelationGetRelid(relation)
Definition: rel.h:505
#define RelationGetDescr(relation)
Definition: rel.h:531
#define RelationGetRelationName(relation)
Definition: rel.h:539
#define RelationGetNamespace(relation)
Definition: rel.h:546
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:12623
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:97
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:233
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:182
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:194
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
Oid aggfnoid
Definition: primnodes.h:444
List * aggdistinct
Definition: primnodes.h:474
List * aggdirectargs
Definition: primnodes.h:465
List * args
Definition: primnodes.h:468
Expr * aggfilter
Definition: primnodes.h:477
List * aggorder
Definition: primnodes.h:471
List * elements
Definition: primnodes.h:1350
BoolExprType boolop
Definition: primnodes.h:909
List * args
Definition: primnodes.h:910
Expr * arg
Definition: primnodes.h:1283
Expr * defresult
Definition: primnodes.h:1285
List * args
Definition: primnodes.h:1284
Expr * result
Definition: primnodes.h:1296
Expr * expr
Definition: primnodes.h:1295
Oid consttype
Definition: primnodes.h:312
char * defname
Definition: parsenodes.h:815
List * options
Definition: foreign.h:57
Oid funcid
Definition: primnodes.h:720
List * args
Definition: primnodes.h:738
Definition: pg_list.h:54
Definition: nodes.h:129
NullTestType nulltesttype
Definition: primnodes.h:1931
Expr * arg
Definition: primnodes.h:1930
Oid opno
Definition: primnodes.h:788
List * args
Definition: primnodes.h:806
Oid paramtype
Definition: primnodes.h:378
ParamKind paramkind
Definition: primnodes.h:376
bool pk_nulls_first
Definition: pathnodes.h:1467
int pk_strategy
Definition: pathnodes.h:1466
Oid pk_opfamily
Definition: pathnodes.h:1465
List * exprs
Definition: pathnodes.h:1522
Relids lower_subquery_rels
Definition: postgres_fdw.h:119
RelOptInfo * outerrel
Definition: postgres_fdw.h:102
Bitmapset * attrs_used
Definition: postgres_fdw.h:50
RelOptInfo * innerrel
Definition: postgres_fdw.h:103
LockClauseStrength strength
Definition: plannodes.h:1387
List * groupClause
Definition: parsenodes.h:200
List * groupingSets
Definition: parsenodes.h:203
Relids relids
Definition: pathnodes.h:861
struct PathTarget * reltarget
Definition: pathnodes.h:883
Index relid
Definition: pathnodes.h:908
RelOptKind reloptkind
Definition: pathnodes.h:855
Oid resulttype
Definition: primnodes.h:1155
Expr * arg
Definition: primnodes.h:1154
TriggerDesc * trigdesc
Definition: rel.h:117
Expr * clause
Definition: pathnodes.h:2552
Index tleSortGroupRef
Definition: parsenodes.h:1442
Expr * refassgnexpr
Definition: primnodes.h:673
List * refupperindexpr
Definition: primnodes.h:663
Expr * refexpr
Definition: primnodes.h:671
List * reflowerindexpr
Definition: primnodes.h:669
Expr * expr
Definition: primnodes.h:2162
AttrNumber resno
Definition: primnodes.h:2164
bool trig_update_after_row
Definition: reltrigger.h:62
bool trig_insert_after_row
Definition: reltrigger.h:57
bool trig_delete_after_row
Definition: reltrigger.h:67
Definition: primnodes.h:248
AttrNumber varattno
Definition: primnodes.h:260
int varno
Definition: primnodes.h:255
Index varlevelsup
Definition: primnodes.h:280
PlannerInfo * root
Definition: deparse.c:101
List ** params_list
Definition: deparse.c:107
RelOptInfo * foreignrel
Definition: deparse.c:102
StringInfo buf
Definition: deparse.c:106
RelOptInfo * scanrel
Definition: deparse.c:103
RelOptInfo * foreignrel
Definition: deparse.c:71
Relids relids
Definition: deparse.c:72
PlannerInfo * root
Definition: deparse.c:70
FDWCollateState state
Definition: deparse.c:93
char data[NAMEDATALEN]
Definition: c.h:742
Definition: regguts.h:323
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
#define TableOidAttributeNumber
Definition: sysattr.h:26
#define SelfItemPointerAttributeNumber
Definition: sysattr.h:21
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:266
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:218
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
TargetEntry * get_sortgroupref_tle(Index sortref, List *targetList)
Definition: tlist.c:345
List * add_to_flat_tlist(List *tlist, List *exprs)
Definition: tlist.c:132
#define FirstNormalObjectId
Definition: transam.h:197
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:346
#define TYPECACHE_GT_OPR
Definition: typcache.h:139
#define TYPECACHE_LT_OPR
Definition: typcache.h:138
List * pull_var_clause(Node *node, int flags)
Definition: var.c:607
void pull_varattnos(Node *node, Index varno, Bitmapset **varattnos)
Definition: var.c:291