1 /*-------------------------------------------------------------------------
2 *
3 * deparse.c
4 * Query deparser for postgres_fdw
5 *
6 * This file includes functions that examine query WHERE clauses to see
7 * whether they're safe to send to the remote server for execution, as
8 * well as functions to construct the query text to be sent. The latter
9 * functionality is annoyingly duplicative of ruleutils.c, but there are
10 * enough special considerations that it seems best to keep this separate.
11 * One saving grace is that we only need deparse logic for node types that
12 * we consider safe to send.
13 *
14 * We assume that the remote session's search_path is exactly "pg_catalog",
15 * and thus we need schema-qualify all and only names outside pg_catalog.
16 *
17 * We do not consider that it is ever safe to send COLLATE expressions to
18 * the remote server: it might not have the same collation names we do.
19 * (Later we might consider it safe to send COLLATE "C", but even that would
20 * fail on old remote servers.) An expression is considered safe to send
21 * only if all operator/function input collations used in it are traceable to
22 * Var(s) of the foreign table. That implies that if the remote server gets
23 * a different answer than we do, the foreign table's columns are not marked
24 * with collations that match the remote table's columns, which we can
25 * consider to be user error.
26 *
27 * Portions Copyright (c) 2012-2018, PostgreSQL Global Development Group
28 *
29 * IDENTIFICATION
30 * contrib/postgres_fdw/deparse.c
31 *
32 *-------------------------------------------------------------------------
33 */
34 #include "postgres.h"
35
36 #include "postgres_fdw.h"
37
38 #include "access/heapam.h"
39 #include "access/htup_details.h"
40 #include "access/sysattr.h"
41 #include "catalog/pg_aggregate.h"
42 #include "catalog/pg_collation.h"
43 #include "catalog/pg_namespace.h"
44 #include "catalog/pg_operator.h"
45 #include "catalog/pg_proc.h"
46 #include "catalog/pg_type.h"
47 #include "commands/defrem.h"
48 #include "nodes/makefuncs.h"
49 #include "nodes/nodeFuncs.h"
50 #include "nodes/plannodes.h"
51 #include "optimizer/clauses.h"
52 #include "optimizer/prep.h"
53 #include "optimizer/tlist.h"
54 #include "optimizer/var.h"
55 #include "parser/parsetree.h"
56 #include "utils/builtins.h"
57 #include "utils/lsyscache.h"
58 #include "utils/rel.h"
59 #include "utils/syscache.h"
60 #include "utils/typcache.h"
61
62
63 /*
64 * Global context for foreign_expr_walker's search of an expression tree.
65 */
66 typedef struct foreign_glob_cxt
67 {
68 PlannerInfo *root; /* global planner state */
69 RelOptInfo *foreignrel; /* the foreign relation we are planning for */
70 Relids relids; /* relids of base relations in the underlying
71 * scan */
72 } foreign_glob_cxt;
73
74 /*
75 * Local (per-tree-level) context for foreign_expr_walker's search.
76 * This is concerned with identifying collations used in the expression.
77 */
78 typedef enum
79 {
80 FDW_COLLATE_NONE, /* expression is of a noncollatable type, or
81 * it has default collation that is not
82 * traceable to a foreign Var */
83 FDW_COLLATE_SAFE, /* collation derives from a foreign Var */
84 FDW_COLLATE_UNSAFE /* collation is non-default and derives from
85 * something other than a foreign Var */
86 } FDWCollateState;
87
88 typedef struct foreign_loc_cxt
89 {
90 Oid collation; /* OID of current collation, if any */
91 FDWCollateState state; /* state of current collation choice */
92 } foreign_loc_cxt;
93
94 /*
95 * Context for deparseExpr
96 */
97 typedef struct deparse_expr_cxt
98 {
99 PlannerInfo *root; /* global planner state */
100 RelOptInfo *foreignrel; /* the foreign relation we are planning for */
101 RelOptInfo *scanrel; /* the underlying scan relation. Same as
102 * foreignrel, when that represents a join or
103 * a base relation. */
104 StringInfo buf; /* output buffer to append to */
105 List **params_list; /* exprs that will become remote Params */
106 } deparse_expr_cxt;
107
108 #define REL_ALIAS_PREFIX "r"
109 /* Handy macro to add relation name qualification */
110 #define ADD_REL_QUALIFIER(buf, varno) \
111 appendStringInfo((buf), "%s%d.", REL_ALIAS_PREFIX, (varno))
112 #define SUBQUERY_REL_ALIAS_PREFIX "s"
113 #define SUBQUERY_COL_ALIAS_PREFIX "c"
114
115 /*
116 * Functions to determine whether an expression can be evaluated safely on
117 * remote server.
118 */
119 static bool foreign_expr_walker(Node *node,
120 foreign_glob_cxt *glob_cxt,
121 foreign_loc_cxt *outer_cxt);
122 static char *deparse_type_name(Oid type_oid, int32 typemod);
123
124 /*
125 * Functions to construct string representation of a node tree.
126 */
127 static void deparseTargetList(StringInfo buf,
128 RangeTblEntry *rte,
129 Index rtindex,
130 Relation rel,
131 bool is_returning,
132 Bitmapset *attrs_used,
133 bool qualify_col,
134 List **retrieved_attrs);
135 static void deparseExplicitTargetList(List *tlist,
136 bool is_returning,
137 List **retrieved_attrs,
138 deparse_expr_cxt *context);
139 static void deparseSubqueryTargetList(deparse_expr_cxt *context);
140 static void deparseReturningList(StringInfo buf, RangeTblEntry *rte,
141 Index rtindex, Relation rel,
142 bool trig_after_row,
143 List *returningList,
144 List **retrieved_attrs);
145 static void deparseColumnRef(StringInfo buf, int varno, int varattno,
146 RangeTblEntry *rte, bool qualify_col);
147 static void deparseRelation(StringInfo buf, Relation rel);
148 static void deparseExpr(Expr *expr, deparse_expr_cxt *context);
149 static void deparseVar(Var *node, deparse_expr_cxt *context);
150 static void deparseConst(Const *node, deparse_expr_cxt *context, int showtype);
151 static void deparseParam(Param *node, deparse_expr_cxt *context);
152 static void deparseArrayRef(ArrayRef *node, deparse_expr_cxt *context);
153 static void deparseFuncExpr(FuncExpr *node, deparse_expr_cxt *context);
154 static void deparseOpExpr(OpExpr *node, deparse_expr_cxt *context);
155 static void deparseOperatorName(StringInfo buf, Form_pg_operator opform);
156 static void deparseDistinctExpr(DistinctExpr *node, deparse_expr_cxt *context);
157 static void deparseScalarArrayOpExpr(ScalarArrayOpExpr *node,
158 deparse_expr_cxt *context);
159 static void deparseRelabelType(RelabelType *node, deparse_expr_cxt *context);
160 static void deparseBoolExpr(BoolExpr *node, deparse_expr_cxt *context);
161 static void deparseNullTest(NullTest *node, deparse_expr_cxt *context);
162 static void deparseArrayExpr(ArrayExpr *node, deparse_expr_cxt *context);
163 static void printRemoteParam(int paramindex, Oid paramtype, int32 paramtypmod,
164 deparse_expr_cxt *context);
165 static void printRemotePlaceholder(Oid paramtype, int32 paramtypmod,
166 deparse_expr_cxt *context);
167 static void deparseSelectSql(List *tlist, bool is_subquery, List **retrieved_attrs,
168 deparse_expr_cxt *context);
169 static void deparseLockingClause(deparse_expr_cxt *context);
170 static void appendOrderByClause(List *pathkeys, deparse_expr_cxt *context);
171 static void appendConditions(List *exprs, deparse_expr_cxt *context);
172 static void deparseFromExprForRel(StringInfo buf, PlannerInfo *root,
173 RelOptInfo *foreignrel, bool use_alias,
174 Index ignore_rel, List **ignore_conds,
175 List **params_list);
176 static void deparseFromExpr(List *quals, deparse_expr_cxt *context);
177 static void deparseRangeTblRef(StringInfo buf, PlannerInfo *root,
178 RelOptInfo *foreignrel, bool make_subquery,
179 Index ignore_rel, List **ignore_conds, List **params_list);
180 static void deparseAggref(Aggref *node, deparse_expr_cxt *context);
181 static void appendGroupByClause(List *tlist, deparse_expr_cxt *context);
182 static void appendAggOrderBy(List *orderList, List *targetList,
183 deparse_expr_cxt *context);
184 static void appendFunctionName(Oid funcid, deparse_expr_cxt *context);
185 static Node *deparseSortGroupClause(Index ref, List *tlist, bool force_colno,
186 deparse_expr_cxt *context);
187
188 /*
189 * Helper functions
190 */
191 static bool is_subquery_var(Var *node, RelOptInfo *foreignrel,
192 int *relno, int *colno);
193 static void get_relation_column_alias_ids(Var *node, RelOptInfo *foreignrel,
194 int *relno, int *colno);
195
196
197 /*
198 * Examine each qual clause in input_conds, and classify them into two groups,
199 * which are returned as two lists:
200 * - remote_conds contains expressions that can be evaluated remotely
201 * - local_conds contains expressions that can't be evaluated remotely
202 */
203 void
classifyConditions(PlannerInfo * root,RelOptInfo * baserel,List * input_conds,List ** remote_conds,List ** local_conds)204 classifyConditions(PlannerInfo *root,
205 RelOptInfo *baserel,
206 List *input_conds,
207 List **remote_conds,
208 List **local_conds)
209 {
210 ListCell *lc;
211
212 *remote_conds = NIL;
213 *local_conds = NIL;
214
215 foreach(lc, input_conds)
216 {
217 RestrictInfo *ri = lfirst_node(RestrictInfo, lc);
218
219 if (is_foreign_expr(root, baserel, ri->clause))
220 *remote_conds = lappend(*remote_conds, ri);
221 else
222 *local_conds = lappend(*local_conds, ri);
223 }
224 }
225
226 /*
227 * Returns true if given expr is safe to evaluate on the foreign server.
228 */
229 bool
is_foreign_expr(PlannerInfo * root,RelOptInfo * baserel,Expr * expr)230 is_foreign_expr(PlannerInfo *root,
231 RelOptInfo *baserel,
232 Expr *expr)
233 {
234 foreign_glob_cxt glob_cxt;
235 foreign_loc_cxt loc_cxt;
236 PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) (baserel->fdw_private);
237
238 /*
239 * Check that the expression consists of nodes that are safe to execute
240 * remotely.
241 */
242 glob_cxt.root = root;
243 glob_cxt.foreignrel = baserel;
244
245 /*
246 * For an upper relation, use relids from its underneath scan relation,
247 * because the upperrel's own relids currently aren't set to anything
248 * meaningful by the core code. For other relation, use their own relids.
249 */
250 if (IS_UPPER_REL(baserel))
251 glob_cxt.relids = fpinfo->outerrel->relids;
252 else
253 glob_cxt.relids = baserel->relids;
254 loc_cxt.collation = InvalidOid;
255 loc_cxt.state = FDW_COLLATE_NONE;
256 if (!foreign_expr_walker((Node *) expr, &glob_cxt, &loc_cxt))
257 return false;
258
259 /*
260 * If the expression has a valid collation that does not arise from a
261 * foreign var, the expression can not be sent over.
262 */
263 if (loc_cxt.state == FDW_COLLATE_UNSAFE)
264 return false;
265
266 /*
267 * An expression which includes any mutable functions can't be sent over
268 * because its result is not stable. For example, sending now() remote
269 * side could cause confusion from clock offsets. Future versions might
270 * be able to make this choice with more granularity. (We check this last
271 * because it requires a lot of expensive catalog lookups.)
272 */
273 if (contain_mutable_functions((Node *) expr))
274 return false;
275
276 /* OK to evaluate on the remote server */
277 return true;
278 }
279
280 /*
281 * Check if expression is safe to execute remotely, and return true if so.
282 *
283 * In addition, *outer_cxt is updated with collation information.
284 *
285 * We must check that the expression contains only node types we can deparse,
286 * that all types/functions/operators are safe to send (they are "shippable"),
287 * and that all collations used in the expression derive from Vars of the
288 * foreign table. Because of the latter, the logic is pretty close to
289 * assign_collations_walker() in parse_collate.c, though we can assume here
290 * that the given expression is valid. Note function mutability is not
291 * currently considered here.
292 */
293 static bool
foreign_expr_walker(Node * node,foreign_glob_cxt * glob_cxt,foreign_loc_cxt * outer_cxt)294 foreign_expr_walker(Node *node,
295 foreign_glob_cxt *glob_cxt,
296 foreign_loc_cxt *outer_cxt)
297 {
298 bool check_type = true;
299 PgFdwRelationInfo *fpinfo;
300 foreign_loc_cxt inner_cxt;
301 Oid collation;
302 FDWCollateState state;
303
304 /* Need do nothing for empty subexpressions */
305 if (node == NULL)
306 return true;
307
308 /* May need server info from baserel's fdw_private struct */
309 fpinfo = (PgFdwRelationInfo *) (glob_cxt->foreignrel->fdw_private);
310
311 /* Set up inner_cxt for possible recursion to child nodes */
312 inner_cxt.collation = InvalidOid;
313 inner_cxt.state = FDW_COLLATE_NONE;
314
315 switch (nodeTag(node))
316 {
317 case T_Var:
318 {
319 Var *var = (Var *) node;
320
321 /*
322 * If the Var is from the foreign table, we consider its
323 * collation (if any) safe to use. If it is from another
324 * table, we treat its collation the same way as we would a
325 * Param's collation, ie it's not safe for it to have a
326 * non-default collation.
327 */
328 if (bms_is_member(var->varno, glob_cxt->relids) &&
329 var->varlevelsup == 0)
330 {
331 /* Var belongs to foreign table */
332
333 /*
334 * System columns other than ctid and oid should not be
335 * sent to the remote, since we don't make any effort to
336 * ensure that local and remote values match (tableoid, in
337 * particular, almost certainly doesn't match).
338 */
339 if (var->varattno < 0 &&
340 var->varattno != SelfItemPointerAttributeNumber &&
341 var->varattno != ObjectIdAttributeNumber)
342 return false;
343
344 /* Else check the collation */
345 collation = var->varcollid;
346 state = OidIsValid(collation) ? FDW_COLLATE_SAFE : FDW_COLLATE_NONE;
347 }
348 else
349 {
350 /* Var belongs to some other table */
351 collation = var->varcollid;
352 if (collation == InvalidOid ||
353 collation == DEFAULT_COLLATION_OID)
354 {
355 /*
356 * It's noncollatable, or it's safe to combine with a
357 * collatable foreign Var, so set state to NONE.
358 */
359 state = FDW_COLLATE_NONE;
360 }
361 else
362 {
363 /*
364 * Do not fail right away, since the Var might appear
365 * in a collation-insensitive context.
366 */
367 state = FDW_COLLATE_UNSAFE;
368 }
369 }
370 }
371 break;
372 case T_Const:
373 {
374 Const *c = (Const *) node;
375
376 /*
377 * If the constant has nondefault collation, either it's of a
378 * non-builtin type, or it reflects folding of a CollateExpr.
379 * It's unsafe to send to the remote unless it's used in a
380 * non-collation-sensitive context.
381 */
382 collation = c->constcollid;
383 if (collation == InvalidOid ||
384 collation == DEFAULT_COLLATION_OID)
385 state = FDW_COLLATE_NONE;
386 else
387 state = FDW_COLLATE_UNSAFE;
388 }
389 break;
390 case T_Param:
391 {
392 Param *p = (Param *) node;
393
394 /*
395 * If it's a MULTIEXPR Param, punt. We can't tell from here
396 * whether the referenced sublink/subplan contains any remote
397 * Vars; if it does, handling that is too complicated to
398 * consider supporting at present. Fortunately, MULTIEXPR
399 * Params are not reduced to plain PARAM_EXEC until the end of
400 * planning, so we can easily detect this case. (Normal
401 * PARAM_EXEC Params are safe to ship because their values
402 * come from somewhere else in the plan tree; but a MULTIEXPR
403 * references a sub-select elsewhere in the same targetlist,
404 * so we'd be on the hook to evaluate it somehow if we wanted
405 * to handle such cases as direct foreign updates.)
406 */
407 if (p->paramkind == PARAM_MULTIEXPR)
408 return false;
409
410 /*
411 * Collation rule is same as for Consts and non-foreign Vars.
412 */
413 collation = p->paramcollid;
414 if (collation == InvalidOid ||
415 collation == DEFAULT_COLLATION_OID)
416 state = FDW_COLLATE_NONE;
417 else
418 state = FDW_COLLATE_UNSAFE;
419 }
420 break;
421 case T_ArrayRef:
422 {
423 ArrayRef *ar = (ArrayRef *) node;
424
425 /* Assignment should not be in restrictions. */
426 if (ar->refassgnexpr != NULL)
427 return false;
428
429 /*
430 * Recurse to remaining subexpressions. Since the array
431 * subscripts must yield (noncollatable) integers, they won't
432 * affect the inner_cxt state.
433 */
434 if (!foreign_expr_walker((Node *) ar->refupperindexpr,
435 glob_cxt, &inner_cxt))
436 return false;
437 if (!foreign_expr_walker((Node *) ar->reflowerindexpr,
438 glob_cxt, &inner_cxt))
439 return false;
440 if (!foreign_expr_walker((Node *) ar->refexpr,
441 glob_cxt, &inner_cxt))
442 return false;
443
444 /*
445 * Array subscripting should yield same collation as input,
446 * but for safety use same logic as for function nodes.
447 */
448 collation = ar->refcollid;
449 if (collation == InvalidOid)
450 state = FDW_COLLATE_NONE;
451 else if (inner_cxt.state == FDW_COLLATE_SAFE &&
452 collation == inner_cxt.collation)
453 state = FDW_COLLATE_SAFE;
454 else if (collation == DEFAULT_COLLATION_OID)
455 state = FDW_COLLATE_NONE;
456 else
457 state = FDW_COLLATE_UNSAFE;
458 }
459 break;
460 case T_FuncExpr:
461 {
462 FuncExpr *fe = (FuncExpr *) node;
463
464 /*
465 * If function used by the expression is not shippable, it
466 * can't be sent to remote because it might have incompatible
467 * semantics on remote side.
468 */
469 if (!is_shippable(fe->funcid, ProcedureRelationId, fpinfo))
470 return false;
471
472 /*
473 * Recurse to input subexpressions.
474 */
475 if (!foreign_expr_walker((Node *) fe->args,
476 glob_cxt, &inner_cxt))
477 return false;
478
479 /*
480 * If function's input collation is not derived from a foreign
481 * Var, it can't be sent to remote.
482 */
483 if (fe->inputcollid == InvalidOid)
484 /* OK, inputs are all noncollatable */ ;
485 else if (inner_cxt.state != FDW_COLLATE_SAFE ||
486 fe->inputcollid != inner_cxt.collation)
487 return false;
488
489 /*
490 * Detect whether node is introducing a collation not derived
491 * from a foreign Var. (If so, we just mark it unsafe for now
492 * rather than immediately returning false, since the parent
493 * node might not care.)
494 */
495 collation = fe->funccollid;
496 if (collation == InvalidOid)
497 state = FDW_COLLATE_NONE;
498 else if (inner_cxt.state == FDW_COLLATE_SAFE &&
499 collation == inner_cxt.collation)
500 state = FDW_COLLATE_SAFE;
501 else if (collation == DEFAULT_COLLATION_OID)
502 state = FDW_COLLATE_NONE;
503 else
504 state = FDW_COLLATE_UNSAFE;
505 }
506 break;
507 case T_OpExpr:
508 case T_DistinctExpr: /* struct-equivalent to OpExpr */
509 {
510 OpExpr *oe = (OpExpr *) node;
511
512 /*
513 * Similarly, only shippable operators can be sent to remote.
514 * (If the operator is shippable, we assume its underlying
515 * function is too.)
516 */
517 if (!is_shippable(oe->opno, OperatorRelationId, fpinfo))
518 return false;
519
520 /*
521 * Recurse to input subexpressions.
522 */
523 if (!foreign_expr_walker((Node *) oe->args,
524 glob_cxt, &inner_cxt))
525 return false;
526
527 /*
528 * If operator's input collation is not derived from a foreign
529 * Var, it can't be sent to remote.
530 */
531 if (oe->inputcollid == InvalidOid)
532 /* OK, inputs are all noncollatable */ ;
533 else if (inner_cxt.state != FDW_COLLATE_SAFE ||
534 oe->inputcollid != inner_cxt.collation)
535 return false;
536
537 /* Result-collation handling is same as for functions */
538 collation = oe->opcollid;
539 if (collation == InvalidOid)
540 state = FDW_COLLATE_NONE;
541 else if (inner_cxt.state == FDW_COLLATE_SAFE &&
542 collation == inner_cxt.collation)
543 state = FDW_COLLATE_SAFE;
544 else if (collation == DEFAULT_COLLATION_OID)
545 state = FDW_COLLATE_NONE;
546 else
547 state = FDW_COLLATE_UNSAFE;
548 }
549 break;
550 case T_ScalarArrayOpExpr:
551 {
552 ScalarArrayOpExpr *oe = (ScalarArrayOpExpr *) node;
553
554 /*
555 * Again, only shippable operators can be sent to remote.
556 */
557 if (!is_shippable(oe->opno, OperatorRelationId, fpinfo))
558 return false;
559
560 /*
561 * Recurse to input subexpressions.
562 */
563 if (!foreign_expr_walker((Node *) oe->args,
564 glob_cxt, &inner_cxt))
565 return false;
566
567 /*
568 * If operator's input collation is not derived from a foreign
569 * Var, it can't be sent to remote.
570 */
571 if (oe->inputcollid == InvalidOid)
572 /* OK, inputs are all noncollatable */ ;
573 else if (inner_cxt.state != FDW_COLLATE_SAFE ||
574 oe->inputcollid != inner_cxt.collation)
575 return false;
576
577 /* Output is always boolean and so noncollatable. */
578 collation = InvalidOid;
579 state = FDW_COLLATE_NONE;
580 }
581 break;
582 case T_RelabelType:
583 {
584 RelabelType *r = (RelabelType *) node;
585
586 /*
587 * Recurse to input subexpression.
588 */
589 if (!foreign_expr_walker((Node *) r->arg,
590 glob_cxt, &inner_cxt))
591 return false;
592
593 /*
594 * RelabelType must not introduce a collation not derived from
595 * an input foreign Var (same logic as for a real function).
596 */
597 collation = r->resultcollid;
598 if (collation == InvalidOid)
599 state = FDW_COLLATE_NONE;
600 else if (inner_cxt.state == FDW_COLLATE_SAFE &&
601 collation == inner_cxt.collation)
602 state = FDW_COLLATE_SAFE;
603 else if (collation == DEFAULT_COLLATION_OID)
604 state = FDW_COLLATE_NONE;
605 else
606 state = FDW_COLLATE_UNSAFE;
607 }
608 break;
609 case T_BoolExpr:
610 {
611 BoolExpr *b = (BoolExpr *) node;
612
613 /*
614 * Recurse to input subexpressions.
615 */
616 if (!foreign_expr_walker((Node *) b->args,
617 glob_cxt, &inner_cxt))
618 return false;
619
620 /* Output is always boolean and so noncollatable. */
621 collation = InvalidOid;
622 state = FDW_COLLATE_NONE;
623 }
624 break;
625 case T_NullTest:
626 {
627 NullTest *nt = (NullTest *) node;
628
629 /*
630 * Recurse to input subexpressions.
631 */
632 if (!foreign_expr_walker((Node *) nt->arg,
633 glob_cxt, &inner_cxt))
634 return false;
635
636 /* Output is always boolean and so noncollatable. */
637 collation = InvalidOid;
638 state = FDW_COLLATE_NONE;
639 }
640 break;
641 case T_ArrayExpr:
642 {
643 ArrayExpr *a = (ArrayExpr *) node;
644
645 /*
646 * Recurse to input subexpressions.
647 */
648 if (!foreign_expr_walker((Node *) a->elements,
649 glob_cxt, &inner_cxt))
650 return false;
651
652 /*
653 * ArrayExpr must not introduce a collation not derived from
654 * an input foreign Var (same logic as for a function).
655 */
656 collation = a->array_collid;
657 if (collation == InvalidOid)
658 state = FDW_COLLATE_NONE;
659 else if (inner_cxt.state == FDW_COLLATE_SAFE &&
660 collation == inner_cxt.collation)
661 state = FDW_COLLATE_SAFE;
662 else if (collation == DEFAULT_COLLATION_OID)
663 state = FDW_COLLATE_NONE;
664 else
665 state = FDW_COLLATE_UNSAFE;
666 }
667 break;
668 case T_List:
669 {
670 List *l = (List *) node;
671 ListCell *lc;
672
673 /*
674 * Recurse to component subexpressions.
675 */
676 foreach(lc, l)
677 {
678 if (!foreign_expr_walker((Node *) lfirst(lc),
679 glob_cxt, &inner_cxt))
680 return false;
681 }
682
683 /*
684 * When processing a list, collation state just bubbles up
685 * from the list elements.
686 */
687 collation = inner_cxt.collation;
688 state = inner_cxt.state;
689
690 /* Don't apply exprType() to the list. */
691 check_type = false;
692 }
693 break;
694 case T_Aggref:
695 {
696 Aggref *agg = (Aggref *) node;
697 ListCell *lc;
698
699 /* Not safe to pushdown when not in grouping context */
700 if (!IS_UPPER_REL(glob_cxt->foreignrel))
701 return false;
702
703 /* Only non-split aggregates are pushable. */
704 if (agg->aggsplit != AGGSPLIT_SIMPLE)
705 return false;
706
707 /* As usual, it must be shippable. */
708 if (!is_shippable(agg->aggfnoid, ProcedureRelationId, fpinfo))
709 return false;
710
711 /*
712 * Recurse to input args. aggdirectargs, aggorder and
713 * aggdistinct are all present in args, so no need to check
714 * their shippability explicitly.
715 */
716 foreach(lc, agg->args)
717 {
718 Node *n = (Node *) lfirst(lc);
719
720 /* If TargetEntry, extract the expression from it */
721 if (IsA(n, TargetEntry))
722 {
723 TargetEntry *tle = (TargetEntry *) n;
724
725 n = (Node *) tle->expr;
726 }
727
728 if (!foreign_expr_walker(n, glob_cxt, &inner_cxt))
729 return false;
730 }
731
732 /*
733 * For aggorder elements, check whether the sort operator, if
734 * specified, is shippable or not.
735 */
736 if (agg->aggorder)
737 {
738 ListCell *lc;
739
740 foreach(lc, agg->aggorder)
741 {
742 SortGroupClause *srt = (SortGroupClause *) lfirst(lc);
743 Oid sortcoltype;
744 TypeCacheEntry *typentry;
745 TargetEntry *tle;
746
747 tle = get_sortgroupref_tle(srt->tleSortGroupRef,
748 agg->args);
749 sortcoltype = exprType((Node *) tle->expr);
750 typentry = lookup_type_cache(sortcoltype,
751 TYPECACHE_LT_OPR | TYPECACHE_GT_OPR);
752 /* Check shippability of non-default sort operator. */
753 if (srt->sortop != typentry->lt_opr &&
754 srt->sortop != typentry->gt_opr &&
755 !is_shippable(srt->sortop, OperatorRelationId,
756 fpinfo))
757 return false;
758 }
759 }
760
761 /* Check aggregate filter */
762 if (!foreign_expr_walker((Node *) agg->aggfilter,
763 glob_cxt, &inner_cxt))
764 return false;
765
766 /*
767 * If aggregate's input collation is not derived from a
768 * foreign Var, it can't be sent to remote.
769 */
770 if (agg->inputcollid == InvalidOid)
771 /* OK, inputs are all noncollatable */ ;
772 else if (inner_cxt.state != FDW_COLLATE_SAFE ||
773 agg->inputcollid != inner_cxt.collation)
774 return false;
775
776 /*
777 * Detect whether node is introducing a collation not derived
778 * from a foreign Var. (If so, we just mark it unsafe for now
779 * rather than immediately returning false, since the parent
780 * node might not care.)
781 */
782 collation = agg->aggcollid;
783 if (collation == InvalidOid)
784 state = FDW_COLLATE_NONE;
785 else if (inner_cxt.state == FDW_COLLATE_SAFE &&
786 collation == inner_cxt.collation)
787 state = FDW_COLLATE_SAFE;
788 else if (collation == DEFAULT_COLLATION_OID)
789 state = FDW_COLLATE_NONE;
790 else
791 state = FDW_COLLATE_UNSAFE;
792 }
793 break;
794 default:
795
796 /*
797 * If it's anything else, assume it's unsafe. This list can be
798 * expanded later, but don't forget to add deparse support below.
799 */
800 return false;
801 }
802
803 /*
804 * If result type of given expression is not shippable, it can't be sent
805 * to remote because it might have incompatible semantics on remote side.
806 */
807 if (check_type && !is_shippable(exprType(node), TypeRelationId, fpinfo))
808 return false;
809
810 /*
811 * Now, merge my collation information into my parent's state.
812 */
813 if (state > outer_cxt->state)
814 {
815 /* Override previous parent state */
816 outer_cxt->collation = collation;
817 outer_cxt->state = state;
818 }
819 else if (state == outer_cxt->state)
820 {
821 /* Merge, or detect error if there's a collation conflict */
822 switch (state)
823 {
824 case FDW_COLLATE_NONE:
825 /* Nothing + nothing is still nothing */
826 break;
827 case FDW_COLLATE_SAFE:
828 if (collation != outer_cxt->collation)
829 {
830 /*
831 * Non-default collation always beats default.
832 */
833 if (outer_cxt->collation == DEFAULT_COLLATION_OID)
834 {
835 /* Override previous parent state */
836 outer_cxt->collation = collation;
837 }
838 else if (collation != DEFAULT_COLLATION_OID)
839 {
840 /*
841 * Conflict; show state as indeterminate. We don't
842 * want to "return false" right away, since parent
843 * node might not care about collation.
844 */
845 outer_cxt->state = FDW_COLLATE_UNSAFE;
846 }
847 }
848 break;
849 case FDW_COLLATE_UNSAFE:
850 /* We're still conflicted ... */
851 break;
852 }
853 }
854
855 /* It looks OK */
856 return true;
857 }
858
859 /*
860 * Returns true if given expr is something we'd have to send the value of
861 * to the foreign server.
862 *
863 * This should return true when the expression is a shippable node that
864 * deparseExpr would add to context->params_list. Note that we don't care
865 * if the expression *contains* such a node, only whether one appears at top
866 * level. We need this to detect cases where setrefs.c would recognize a
867 * false match between an fdw_exprs item (which came from the params_list)
868 * and an entry in fdw_scan_tlist (which we're considering putting the given
869 * expression into).
870 */
871 bool
is_foreign_param(PlannerInfo * root,RelOptInfo * baserel,Expr * expr)872 is_foreign_param(PlannerInfo *root,
873 RelOptInfo *baserel,
874 Expr *expr)
875 {
876 if (expr == NULL)
877 return false;
878
879 switch (nodeTag(expr))
880 {
881 case T_Var:
882 {
883 /* It would have to be sent unless it's a foreign Var */
884 Var *var = (Var *) expr;
885 PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) (baserel->fdw_private);
886 Relids relids;
887
888 if (IS_UPPER_REL(baserel))
889 relids = fpinfo->outerrel->relids;
890 else
891 relids = baserel->relids;
892
893 if (bms_is_member(var->varno, relids) && var->varlevelsup == 0)
894 return false; /* foreign Var, so not a param */
895 else
896 return true; /* it'd have to be a param */
897 break;
898 }
899 case T_Param:
900 /* Params always have to be sent to the foreign server */
901 return true;
902 default:
903 break;
904 }
905 return false;
906 }
907
908 /*
909 * Convert type OID + typmod info into a type name we can ship to the remote
910 * server. Someplace else had better have verified that this type name is
911 * expected to be known on the remote end.
912 *
913 * This is almost just format_type_with_typemod(), except that if left to its
914 * own devices, that function will make schema-qualification decisions based
915 * on the local search_path, which is wrong. We must schema-qualify all
916 * type names that are not in pg_catalog. We assume here that built-in types
917 * are all in pg_catalog and need not be qualified; otherwise, qualify.
918 */
919 static char *
deparse_type_name(Oid type_oid,int32 typemod)920 deparse_type_name(Oid type_oid, int32 typemod)
921 {
922 bits16 flags = FORMAT_TYPE_TYPEMOD_GIVEN;
923
924 if (!is_builtin(type_oid))
925 flags |= FORMAT_TYPE_FORCE_QUALIFY;
926
927 return format_type_extended(type_oid, typemod, flags);
928 }
929
930 /*
931 * Build the targetlist for given relation to be deparsed as SELECT clause.
932 *
933 * The output targetlist contains the columns that need to be fetched from the
934 * foreign server for the given relation. If foreignrel is an upper relation,
935 * then the output targetlist can also contain expressions to be evaluated on
936 * foreign server.
937 */
938 List *
build_tlist_to_deparse(RelOptInfo * foreignrel)939 build_tlist_to_deparse(RelOptInfo *foreignrel)
940 {
941 List *tlist = NIL;
942 PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
943 ListCell *lc;
944
945 /*
946 * For an upper relation, we have already built the target list while
947 * checking shippability, so just return that.
948 */
949 if (IS_UPPER_REL(foreignrel))
950 return fpinfo->grouped_tlist;
951
952 /*
953 * We require columns specified in foreignrel->reltarget->exprs and those
954 * required for evaluating the local conditions.
955 */
956 tlist = add_to_flat_tlist(tlist,
957 pull_var_clause((Node *) foreignrel->reltarget->exprs,
958 PVC_RECURSE_PLACEHOLDERS));
959 foreach(lc, fpinfo->local_conds)
960 {
961 RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
962
963 tlist = add_to_flat_tlist(tlist,
964 pull_var_clause((Node *) rinfo->clause,
965 PVC_RECURSE_PLACEHOLDERS));
966 }
967
968 return tlist;
969 }
970
971 /*
972 * Deparse SELECT statement for given relation into buf.
973 *
974 * tlist contains the list of desired columns to be fetched from foreign server.
975 * For a base relation fpinfo->attrs_used is used to construct SELECT clause,
976 * hence the tlist is ignored for a base relation.
977 *
978 * remote_conds is the list of conditions to be deparsed into the WHERE clause
979 * (or, in the case of upper relations, into the HAVING clause).
980 *
981 * If params_list is not NULL, it receives a list of Params and other-relation
982 * Vars used in the clauses; these values must be transmitted to the remote
983 * server as parameter values.
984 *
985 * If params_list is NULL, we're generating the query for EXPLAIN purposes,
986 * so Params and other-relation Vars should be replaced by dummy values.
987 *
988 * pathkeys is the list of pathkeys to order the result by.
989 *
990 * is_subquery is the flag to indicate whether to deparse the specified
991 * relation as a subquery.
992 *
993 * List of columns selected is returned in retrieved_attrs.
994 */
995 void
deparseSelectStmtForRel(StringInfo buf,PlannerInfo * root,RelOptInfo * rel,List * tlist,List * remote_conds,List * pathkeys,bool is_subquery,List ** retrieved_attrs,List ** params_list)996 deparseSelectStmtForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *rel,
997 List *tlist, List *remote_conds, List *pathkeys,
998 bool is_subquery, List **retrieved_attrs,
999 List **params_list)
1000 {
1001 deparse_expr_cxt context;
1002 PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) rel->fdw_private;
1003 List *quals;
1004
1005 /*
1006 * We handle relations for foreign tables, joins between those and upper
1007 * relations.
1008 */
1009 Assert(IS_JOIN_REL(rel) || IS_SIMPLE_REL(rel) || IS_UPPER_REL(rel));
1010
1011 /* Fill portions of context common to upper, join and base relation */
1012 context.buf = buf;
1013 context.root = root;
1014 context.foreignrel = rel;
1015 context.scanrel = IS_UPPER_REL(rel) ? fpinfo->outerrel : rel;
1016 context.params_list = params_list;
1017
1018 /* Construct SELECT clause */
1019 deparseSelectSql(tlist, is_subquery, retrieved_attrs, &context);
1020
1021 /*
1022 * For upper relations, the WHERE clause is built from the remote
1023 * conditions of the underlying scan relation; otherwise, we can use the
1024 * supplied list of remote conditions directly.
1025 */
1026 if (IS_UPPER_REL(rel))
1027 {
1028 PgFdwRelationInfo *ofpinfo;
1029
1030 ofpinfo = (PgFdwRelationInfo *) fpinfo->outerrel->fdw_private;
1031 quals = ofpinfo->remote_conds;
1032 }
1033 else
1034 quals = remote_conds;
1035
1036 /* Construct FROM and WHERE clauses */
1037 deparseFromExpr(quals, &context);
1038
1039 if (IS_UPPER_REL(rel))
1040 {
1041 /* Append GROUP BY clause */
1042 appendGroupByClause(tlist, &context);
1043
1044 /* Append HAVING clause */
1045 if (remote_conds)
1046 {
1047 appendStringInfoString(buf, " HAVING ");
1048 appendConditions(remote_conds, &context);
1049 }
1050 }
1051
1052 /* Add ORDER BY clause if we found any useful pathkeys */
1053 if (pathkeys)
1054 appendOrderByClause(pathkeys, &context);
1055
1056 /* Add any necessary FOR UPDATE/SHARE. */
1057 deparseLockingClause(&context);
1058 }
1059
1060 /*
1061 * Construct a simple SELECT statement that retrieves desired columns
1062 * of the specified foreign table, and append it to "buf". The output
1063 * contains just "SELECT ... ".
1064 *
1065 * We also create an integer List of the columns being retrieved, which is
1066 * returned to *retrieved_attrs, unless we deparse the specified relation
1067 * as a subquery.
1068 *
1069 * tlist is the list of desired columns. is_subquery is the flag to
1070 * indicate whether to deparse the specified relation as a subquery.
1071 * Read prologue of deparseSelectStmtForRel() for details.
1072 */
1073 static void
deparseSelectSql(List * tlist,bool is_subquery,List ** retrieved_attrs,deparse_expr_cxt * context)1074 deparseSelectSql(List *tlist, bool is_subquery, List **retrieved_attrs,
1075 deparse_expr_cxt *context)
1076 {
1077 StringInfo buf = context->buf;
1078 RelOptInfo *foreignrel = context->foreignrel;
1079 PlannerInfo *root = context->root;
1080 PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
1081
1082 /*
1083 * Construct SELECT list
1084 */
1085 appendStringInfoString(buf, "SELECT ");
1086
1087 if (is_subquery)
1088 {
1089 /*
1090 * For a relation that is deparsed as a subquery, emit expressions
1091 * specified in the relation's reltarget. Note that since this is for
1092 * the subquery, no need to care about *retrieved_attrs.
1093 */
1094 deparseSubqueryTargetList(context);
1095 }
1096 else if (IS_JOIN_REL(foreignrel) || IS_UPPER_REL(foreignrel))
1097 {
1098 /*
1099 * For a join or upper relation the input tlist gives the list of
1100 * columns required to be fetched from the foreign server.
1101 */
1102 deparseExplicitTargetList(tlist, false, retrieved_attrs, context);
1103 }
1104 else
1105 {
1106 /*
1107 * For a base relation fpinfo->attrs_used gives the list of columns
1108 * required to be fetched from the foreign server.
1109 */
1110 RangeTblEntry *rte = planner_rt_fetch(foreignrel->relid, root);
1111
1112 /*
1113 * Core code already has some lock on each rel being planned, so we
1114 * can use NoLock here.
1115 */
1116 Relation rel = heap_open(rte->relid, NoLock);
1117
1118 deparseTargetList(buf, rte, foreignrel->relid, rel, false,
1119 fpinfo->attrs_used, false, retrieved_attrs);
1120 heap_close(rel, NoLock);
1121 }
1122 }
1123
1124 /*
1125 * Construct a FROM clause and, if needed, a WHERE clause, and append those to
1126 * "buf".
1127 *
1128 * quals is the list of clauses to be included in the WHERE clause.
1129 * (These may or may not include RestrictInfo decoration.)
1130 */
1131 static void
deparseFromExpr(List * quals,deparse_expr_cxt * context)1132 deparseFromExpr(List *quals, deparse_expr_cxt *context)
1133 {
1134 StringInfo buf = context->buf;
1135 RelOptInfo *scanrel = context->scanrel;
1136
1137 /* For upper relations, scanrel must be either a joinrel or a baserel */
1138 Assert(!IS_UPPER_REL(context->foreignrel) ||
1139 IS_JOIN_REL(scanrel) || IS_SIMPLE_REL(scanrel));
1140
1141 /* Construct FROM clause */
1142 appendStringInfoString(buf, " FROM ");
1143 deparseFromExprForRel(buf, context->root, scanrel,
1144 (bms_num_members(scanrel->relids) > 1),
1145 (Index) 0, NULL, context->params_list);
1146
1147 /* Construct WHERE clause */
1148 if (quals != NIL)
1149 {
1150 appendStringInfoString(buf, " WHERE ");
1151 appendConditions(quals, context);
1152 }
1153 }
1154
1155 /*
1156 * Emit a target list that retrieves the columns specified in attrs_used.
1157 * This is used for both SELECT and RETURNING targetlists; the is_returning
1158 * parameter is true only for a RETURNING targetlist.
1159 *
1160 * The tlist text is appended to buf, and we also create an integer List
1161 * of the columns being retrieved, which is returned to *retrieved_attrs.
1162 *
1163 * If qualify_col is true, add relation alias before the column name.
1164 */
1165 static void
deparseTargetList(StringInfo buf,RangeTblEntry * rte,Index rtindex,Relation rel,bool is_returning,Bitmapset * attrs_used,bool qualify_col,List ** retrieved_attrs)1166 deparseTargetList(StringInfo buf,
1167 RangeTblEntry *rte,
1168 Index rtindex,
1169 Relation rel,
1170 bool is_returning,
1171 Bitmapset *attrs_used,
1172 bool qualify_col,
1173 List **retrieved_attrs)
1174 {
1175 TupleDesc tupdesc = RelationGetDescr(rel);
1176 bool have_wholerow;
1177 bool first;
1178 int i;
1179
1180 *retrieved_attrs = NIL;
1181
1182 /* If there's a whole-row reference, we'll need all the columns. */
1183 have_wholerow = bms_is_member(0 - FirstLowInvalidHeapAttributeNumber,
1184 attrs_used);
1185
1186 first = true;
1187 for (i = 1; i <= tupdesc->natts; i++)
1188 {
1189 Form_pg_attribute attr = TupleDescAttr(tupdesc, i - 1);
1190
1191 /* Ignore dropped attributes. */
1192 if (attr->attisdropped)
1193 continue;
1194
1195 if (have_wholerow ||
1196 bms_is_member(i - FirstLowInvalidHeapAttributeNumber,
1197 attrs_used))
1198 {
1199 if (!first)
1200 appendStringInfoString(buf, ", ");
1201 else if (is_returning)
1202 appendStringInfoString(buf, " RETURNING ");
1203 first = false;
1204
1205 deparseColumnRef(buf, rtindex, i, rte, qualify_col);
1206
1207 *retrieved_attrs = lappend_int(*retrieved_attrs, i);
1208 }
1209 }
1210
1211 /*
1212 * Add ctid and oid if needed. We currently don't support retrieving any
1213 * other system columns.
1214 */
1215 if (bms_is_member(SelfItemPointerAttributeNumber - FirstLowInvalidHeapAttributeNumber,
1216 attrs_used))
1217 {
1218 if (!first)
1219 appendStringInfoString(buf, ", ");
1220 else if (is_returning)
1221 appendStringInfoString(buf, " RETURNING ");
1222 first = false;
1223
1224 if (qualify_col)
1225 ADD_REL_QUALIFIER(buf, rtindex);
1226 appendStringInfoString(buf, "ctid");
1227
1228 *retrieved_attrs = lappend_int(*retrieved_attrs,
1229 SelfItemPointerAttributeNumber);
1230 }
1231 if (bms_is_member(ObjectIdAttributeNumber - FirstLowInvalidHeapAttributeNumber,
1232 attrs_used))
1233 {
1234 if (!first)
1235 appendStringInfoString(buf, ", ");
1236 else if (is_returning)
1237 appendStringInfoString(buf, " RETURNING ");
1238 first = false;
1239
1240 if (qualify_col)
1241 ADD_REL_QUALIFIER(buf, rtindex);
1242 appendStringInfoString(buf, "oid");
1243
1244 *retrieved_attrs = lappend_int(*retrieved_attrs,
1245 ObjectIdAttributeNumber);
1246 }
1247
1248 /* Don't generate bad syntax if no undropped columns */
1249 if (first && !is_returning)
1250 appendStringInfoString(buf, "NULL");
1251 }
1252
1253 /*
1254 * Deparse the appropriate locking clause (FOR UPDATE or FOR SHARE) for a
1255 * given relation (context->scanrel).
1256 */
1257 static void
deparseLockingClause(deparse_expr_cxt * context)1258 deparseLockingClause(deparse_expr_cxt *context)
1259 {
1260 StringInfo buf = context->buf;
1261 PlannerInfo *root = context->root;
1262 RelOptInfo *rel = context->scanrel;
1263 PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) rel->fdw_private;
1264 int relid = -1;
1265
1266 while ((relid = bms_next_member(rel->relids, relid)) >= 0)
1267 {
1268 /*
1269 * Ignore relation if it appears in a lower subquery. Locking clause
1270 * for such a relation is included in the subquery if necessary.
1271 */
1272 if (bms_is_member(relid, fpinfo->lower_subquery_rels))
1273 continue;
1274
1275 /*
1276 * Add FOR UPDATE/SHARE if appropriate. We apply locking during the
1277 * initial row fetch, rather than later on as is done for local
1278 * tables. The extra roundtrips involved in trying to duplicate the
1279 * local semantics exactly don't seem worthwhile (see also comments
1280 * for RowMarkType).
1281 *
1282 * Note: because we actually run the query as a cursor, this assumes
1283 * that DECLARE CURSOR ... FOR UPDATE is supported, which it isn't
1284 * before 8.3.
1285 */
1286 if (relid == root->parse->resultRelation &&
1287 (root->parse->commandType == CMD_UPDATE ||
1288 root->parse->commandType == CMD_DELETE))
1289 {
1290 /* Relation is UPDATE/DELETE target, so use FOR UPDATE */
1291 appendStringInfoString(buf, " FOR UPDATE");
1292
1293 /* Add the relation alias if we are here for a join relation */
1294 if (IS_JOIN_REL(rel))
1295 appendStringInfo(buf, " OF %s%d", REL_ALIAS_PREFIX, relid);
1296 }
1297 else
1298 {
1299 PlanRowMark *rc = get_plan_rowmark(root->rowMarks, relid);
1300
1301 if (rc)
1302 {
1303 /*
1304 * Relation is specified as a FOR UPDATE/SHARE target, so
1305 * handle that. (But we could also see LCS_NONE, meaning this
1306 * isn't a target relation after all.)
1307 *
1308 * For now, just ignore any [NO] KEY specification, since (a)
1309 * it's not clear what that means for a remote table that we
1310 * don't have complete information about, and (b) it wouldn't
1311 * work anyway on older remote servers. Likewise, we don't
1312 * worry about NOWAIT.
1313 */
1314 switch (rc->strength)
1315 {
1316 case LCS_NONE:
1317 /* No locking needed */
1318 break;
1319 case LCS_FORKEYSHARE:
1320 case LCS_FORSHARE:
1321 appendStringInfoString(buf, " FOR SHARE");
1322 break;
1323 case LCS_FORNOKEYUPDATE:
1324 case LCS_FORUPDATE:
1325 appendStringInfoString(buf, " FOR UPDATE");
1326 break;
1327 }
1328
1329 /* Add the relation alias if we are here for a join relation */
1330 if (bms_num_members(rel->relids) > 1 &&
1331 rc->strength != LCS_NONE)
1332 appendStringInfo(buf, " OF %s%d", REL_ALIAS_PREFIX, relid);
1333 }
1334 }
1335 }
1336 }
1337
1338 /*
1339 * Deparse conditions from the provided list and append them to buf.
1340 *
1341 * The conditions in the list are assumed to be ANDed. This function is used to
1342 * deparse WHERE clauses, JOIN .. ON clauses and HAVING clauses.
1343 *
1344 * Depending on the caller, the list elements might be either RestrictInfos
1345 * or bare clauses.
1346 */
1347 static void
appendConditions(List * exprs,deparse_expr_cxt * context)1348 appendConditions(List *exprs, deparse_expr_cxt *context)
1349 {
1350 int nestlevel;
1351 ListCell *lc;
1352 bool is_first = true;
1353 StringInfo buf = context->buf;
1354
1355 /* Make sure any constants in the exprs are printed portably */
1356 nestlevel = set_transmission_modes();
1357
1358 foreach(lc, exprs)
1359 {
1360 Expr *expr = (Expr *) lfirst(lc);
1361
1362 /* Extract clause from RestrictInfo, if required */
1363 if (IsA(expr, RestrictInfo))
1364 expr = ((RestrictInfo *) expr)->clause;
1365
1366 /* Connect expressions with "AND" and parenthesize each condition. */
1367 if (!is_first)
1368 appendStringInfoString(buf, " AND ");
1369
1370 appendStringInfoChar(buf, '(');
1371 deparseExpr(expr, context);
1372 appendStringInfoChar(buf, ')');
1373
1374 is_first = false;
1375 }
1376
1377 reset_transmission_modes(nestlevel);
1378 }
1379
1380 /* Output join name for given join type */
1381 const char *
get_jointype_name(JoinType jointype)1382 get_jointype_name(JoinType jointype)
1383 {
1384 switch (jointype)
1385 {
1386 case JOIN_INNER:
1387 return "INNER";
1388
1389 case JOIN_LEFT:
1390 return "LEFT";
1391
1392 case JOIN_RIGHT:
1393 return "RIGHT";
1394
1395 case JOIN_FULL:
1396 return "FULL";
1397
1398 default:
1399 /* Shouldn't come here, but protect from buggy code. */
1400 elog(ERROR, "unsupported join type %d", jointype);
1401 }
1402
1403 /* Keep compiler happy */
1404 return NULL;
1405 }
1406
1407 /*
1408 * Deparse given targetlist and append it to context->buf.
1409 *
1410 * tlist is list of TargetEntry's which in turn contain Var nodes.
1411 *
1412 * retrieved_attrs is the list of continuously increasing integers starting
1413 * from 1. It has same number of entries as tlist.
1414 *
1415 * This is used for both SELECT and RETURNING targetlists; the is_returning
1416 * parameter is true only for a RETURNING targetlist.
1417 */
1418 static void
deparseExplicitTargetList(List * tlist,bool is_returning,List ** retrieved_attrs,deparse_expr_cxt * context)1419 deparseExplicitTargetList(List *tlist,
1420 bool is_returning,
1421 List **retrieved_attrs,
1422 deparse_expr_cxt *context)
1423 {
1424 ListCell *lc;
1425 StringInfo buf = context->buf;
1426 int i = 0;
1427
1428 *retrieved_attrs = NIL;
1429
1430 foreach(lc, tlist)
1431 {
1432 TargetEntry *tle = lfirst_node(TargetEntry, lc);
1433
1434 if (i > 0)
1435 appendStringInfoString(buf, ", ");
1436 else if (is_returning)
1437 appendStringInfoString(buf, " RETURNING ");
1438
1439 deparseExpr((Expr *) tle->expr, context);
1440
1441 *retrieved_attrs = lappend_int(*retrieved_attrs, i + 1);
1442 i++;
1443 }
1444
1445 if (i == 0 && !is_returning)
1446 appendStringInfoString(buf, "NULL");
1447 }
1448
1449 /*
1450 * Emit expressions specified in the given relation's reltarget.
1451 *
1452 * This is used for deparsing the given relation as a subquery.
1453 */
1454 static void
deparseSubqueryTargetList(deparse_expr_cxt * context)1455 deparseSubqueryTargetList(deparse_expr_cxt *context)
1456 {
1457 StringInfo buf = context->buf;
1458 RelOptInfo *foreignrel = context->foreignrel;
1459 bool first;
1460 ListCell *lc;
1461
1462 /* Should only be called in these cases. */
1463 Assert(IS_SIMPLE_REL(foreignrel) || IS_JOIN_REL(foreignrel));
1464
1465 first = true;
1466 foreach(lc, foreignrel->reltarget->exprs)
1467 {
1468 Node *node = (Node *) lfirst(lc);
1469
1470 if (!first)
1471 appendStringInfoString(buf, ", ");
1472 first = false;
1473
1474 deparseExpr((Expr *) node, context);
1475 }
1476
1477 /* Don't generate bad syntax if no expressions */
1478 if (first)
1479 appendStringInfoString(buf, "NULL");
1480 }
1481
1482 /*
1483 * Construct FROM clause for given relation
1484 *
1485 * The function constructs ... JOIN ... ON ... for join relation. For a base
1486 * relation it just returns schema-qualified tablename, with the appropriate
1487 * alias if so requested.
1488 *
1489 * 'ignore_rel' is either zero or the RT index of a target relation. In the
1490 * latter case the function constructs FROM clause of UPDATE or USING clause
1491 * of DELETE; it deparses the join relation as if the relation never contained
1492 * the target relation, and creates a List of conditions to be deparsed into
1493 * the top-level WHERE clause, which is returned to *ignore_conds.
1494 */
1495 static void
deparseFromExprForRel(StringInfo buf,PlannerInfo * root,RelOptInfo * foreignrel,bool use_alias,Index ignore_rel,List ** ignore_conds,List ** params_list)1496 deparseFromExprForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel,
1497 bool use_alias, Index ignore_rel, List **ignore_conds,
1498 List **params_list)
1499 {
1500 PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
1501
1502 if (IS_JOIN_REL(foreignrel))
1503 {
1504 StringInfoData join_sql_o;
1505 StringInfoData join_sql_i;
1506 RelOptInfo *outerrel = fpinfo->outerrel;
1507 RelOptInfo *innerrel = fpinfo->innerrel;
1508 bool outerrel_is_target = false;
1509 bool innerrel_is_target = false;
1510
1511 if (ignore_rel > 0 && bms_is_member(ignore_rel, foreignrel->relids))
1512 {
1513 /*
1514 * If this is an inner join, add joinclauses to *ignore_conds and
1515 * set it to empty so that those can be deparsed into the WHERE
1516 * clause. Note that since the target relation can never be
1517 * within the nullable side of an outer join, those could safely
1518 * be pulled up into the WHERE clause (see foreign_join_ok()).
1519 * Note also that since the target relation is only inner-joined
1520 * to any other relation in the query, all conditions in the join
1521 * tree mentioning the target relation could be deparsed into the
1522 * WHERE clause by doing this recursively.
1523 */
1524 if (fpinfo->jointype == JOIN_INNER)
1525 {
1526 *ignore_conds = list_concat(*ignore_conds,
1527 list_copy(fpinfo->joinclauses));
1528 fpinfo->joinclauses = NIL;
1529 }
1530
1531 /*
1532 * Check if either of the input relations is the target relation.
1533 */
1534 if (outerrel->relid == ignore_rel)
1535 outerrel_is_target = true;
1536 else if (innerrel->relid == ignore_rel)
1537 innerrel_is_target = true;
1538 }
1539
1540 /* Deparse outer relation if not the target relation. */
1541 if (!outerrel_is_target)
1542 {
1543 initStringInfo(&join_sql_o);
1544 deparseRangeTblRef(&join_sql_o, root, outerrel,
1545 fpinfo->make_outerrel_subquery,
1546 ignore_rel, ignore_conds, params_list);
1547
1548 /*
1549 * If inner relation is the target relation, skip deparsing it.
1550 * Note that since the join of the target relation with any other
1551 * relation in the query is an inner join and can never be within
1552 * the nullable side of an outer join, the join could be
1553 * interchanged with higher-level joins (cf. identity 1 on outer
1554 * join reordering shown in src/backend/optimizer/README), which
1555 * means it's safe to skip the target-relation deparsing here.
1556 */
1557 if (innerrel_is_target)
1558 {
1559 Assert(fpinfo->jointype == JOIN_INNER);
1560 Assert(fpinfo->joinclauses == NIL);
1561 appendStringInfo(buf, "%s", join_sql_o.data);
1562 return;
1563 }
1564 }
1565
1566 /* Deparse inner relation if not the target relation. */
1567 if (!innerrel_is_target)
1568 {
1569 initStringInfo(&join_sql_i);
1570 deparseRangeTblRef(&join_sql_i, root, innerrel,
1571 fpinfo->make_innerrel_subquery,
1572 ignore_rel, ignore_conds, params_list);
1573
1574 /*
1575 * If outer relation is the target relation, skip deparsing it.
1576 * See the above note about safety.
1577 */
1578 if (outerrel_is_target)
1579 {
1580 Assert(fpinfo->jointype == JOIN_INNER);
1581 Assert(fpinfo->joinclauses == NIL);
1582 appendStringInfo(buf, "%s", join_sql_i.data);
1583 return;
1584 }
1585 }
1586
1587 /* Neither of the relations is the target relation. */
1588 Assert(!outerrel_is_target && !innerrel_is_target);
1589
1590 /*
1591 * For a join relation FROM clause entry is deparsed as
1592 *
1593 * ((outer relation) <join type> (inner relation) ON (joinclauses))
1594 */
1595 appendStringInfo(buf, "(%s %s JOIN %s ON ", join_sql_o.data,
1596 get_jointype_name(fpinfo->jointype), join_sql_i.data);
1597
1598 /* Append join clause; (TRUE) if no join clause */
1599 if (fpinfo->joinclauses)
1600 {
1601 deparse_expr_cxt context;
1602
1603 context.buf = buf;
1604 context.foreignrel = foreignrel;
1605 context.scanrel = foreignrel;
1606 context.root = root;
1607 context.params_list = params_list;
1608
1609 appendStringInfoChar(buf, '(');
1610 appendConditions(fpinfo->joinclauses, &context);
1611 appendStringInfoChar(buf, ')');
1612 }
1613 else
1614 appendStringInfoString(buf, "(TRUE)");
1615
1616 /* End the FROM clause entry. */
1617 appendStringInfoChar(buf, ')');
1618 }
1619 else
1620 {
1621 RangeTblEntry *rte = planner_rt_fetch(foreignrel->relid, root);
1622
1623 /*
1624 * Core code already has some lock on each rel being planned, so we
1625 * can use NoLock here.
1626 */
1627 Relation rel = heap_open(rte->relid, NoLock);
1628
1629 deparseRelation(buf, rel);
1630
1631 /*
1632 * Add a unique alias to avoid any conflict in relation names due to
1633 * pulled up subqueries in the query being built for a pushed down
1634 * join.
1635 */
1636 if (use_alias)
1637 appendStringInfo(buf, " %s%d", REL_ALIAS_PREFIX, foreignrel->relid);
1638
1639 heap_close(rel, NoLock);
1640 }
1641 }
1642
1643 /*
1644 * Append FROM clause entry for the given relation into buf.
1645 */
1646 static void
deparseRangeTblRef(StringInfo buf,PlannerInfo * root,RelOptInfo * foreignrel,bool make_subquery,Index ignore_rel,List ** ignore_conds,List ** params_list)1647 deparseRangeTblRef(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel,
1648 bool make_subquery, Index ignore_rel, List **ignore_conds,
1649 List **params_list)
1650 {
1651 PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
1652
1653 /* Should only be called in these cases. */
1654 Assert(IS_SIMPLE_REL(foreignrel) || IS_JOIN_REL(foreignrel));
1655
1656 Assert(fpinfo->local_conds == NIL);
1657
1658 /* If make_subquery is true, deparse the relation as a subquery. */
1659 if (make_subquery)
1660 {
1661 List *retrieved_attrs;
1662 int ncols;
1663
1664 /*
1665 * The given relation shouldn't contain the target relation, because
1666 * this should only happen for input relations for a full join, and
1667 * such relations can never contain an UPDATE/DELETE target.
1668 */
1669 Assert(ignore_rel == 0 ||
1670 !bms_is_member(ignore_rel, foreignrel->relids));
1671
1672 /* Deparse the subquery representing the relation. */
1673 appendStringInfoChar(buf, '(');
1674 deparseSelectStmtForRel(buf, root, foreignrel, NIL,
1675 fpinfo->remote_conds, NIL, true,
1676 &retrieved_attrs, params_list);
1677 appendStringInfoChar(buf, ')');
1678
1679 /* Append the relation alias. */
1680 appendStringInfo(buf, " %s%d", SUBQUERY_REL_ALIAS_PREFIX,
1681 fpinfo->relation_index);
1682
1683 /*
1684 * Append the column aliases if needed. Note that the subquery emits
1685 * expressions specified in the relation's reltarget (see
1686 * deparseSubqueryTargetList).
1687 */
1688 ncols = list_length(foreignrel->reltarget->exprs);
1689 if (ncols > 0)
1690 {
1691 int i;
1692
1693 appendStringInfoChar(buf, '(');
1694 for (i = 1; i <= ncols; i++)
1695 {
1696 if (i > 1)
1697 appendStringInfoString(buf, ", ");
1698
1699 appendStringInfo(buf, "%s%d", SUBQUERY_COL_ALIAS_PREFIX, i);
1700 }
1701 appendStringInfoChar(buf, ')');
1702 }
1703 }
1704 else
1705 deparseFromExprForRel(buf, root, foreignrel, true, ignore_rel,
1706 ignore_conds, params_list);
1707 }
1708
1709 /*
1710 * deparse remote INSERT statement
1711 *
1712 * The statement text is appended to buf, and we also create an integer List
1713 * of the columns being retrieved by RETURNING (if any), which is returned
1714 * to *retrieved_attrs.
1715 */
1716 void
deparseInsertSql(StringInfo buf,RangeTblEntry * rte,Index rtindex,Relation rel,List * targetAttrs,bool doNothing,List * returningList,List ** retrieved_attrs)1717 deparseInsertSql(StringInfo buf, RangeTblEntry *rte,
1718 Index rtindex, Relation rel,
1719 List *targetAttrs, bool doNothing,
1720 List *returningList, List **retrieved_attrs)
1721 {
1722 AttrNumber pindex;
1723 bool first;
1724 ListCell *lc;
1725
1726 appendStringInfoString(buf, "INSERT INTO ");
1727 deparseRelation(buf, rel);
1728
1729 if (targetAttrs)
1730 {
1731 appendStringInfoChar(buf, '(');
1732
1733 first = true;
1734 foreach(lc, targetAttrs)
1735 {
1736 int attnum = lfirst_int(lc);
1737
1738 if (!first)
1739 appendStringInfoString(buf, ", ");
1740 first = false;
1741
1742 deparseColumnRef(buf, rtindex, attnum, rte, false);
1743 }
1744
1745 appendStringInfoString(buf, ") VALUES (");
1746
1747 pindex = 1;
1748 first = true;
1749 foreach(lc, targetAttrs)
1750 {
1751 if (!first)
1752 appendStringInfoString(buf, ", ");
1753 first = false;
1754
1755 appendStringInfo(buf, "$%d", pindex);
1756 pindex++;
1757 }
1758
1759 appendStringInfoChar(buf, ')');
1760 }
1761 else
1762 appendStringInfoString(buf, " DEFAULT VALUES");
1763
1764 if (doNothing)
1765 appendStringInfoString(buf, " ON CONFLICT DO NOTHING");
1766
1767 deparseReturningList(buf, rte, rtindex, rel,
1768 rel->trigdesc && rel->trigdesc->trig_insert_after_row,
1769 returningList, retrieved_attrs);
1770 }
1771
1772 /*
1773 * deparse remote UPDATE statement
1774 *
1775 * The statement text is appended to buf, and we also create an integer List
1776 * of the columns being retrieved by RETURNING (if any), which is returned
1777 * to *retrieved_attrs.
1778 */
1779 void
deparseUpdateSql(StringInfo buf,RangeTblEntry * rte,Index rtindex,Relation rel,List * targetAttrs,List * returningList,List ** retrieved_attrs)1780 deparseUpdateSql(StringInfo buf, RangeTblEntry *rte,
1781 Index rtindex, Relation rel,
1782 List *targetAttrs, List *returningList,
1783 List **retrieved_attrs)
1784 {
1785 AttrNumber pindex;
1786 bool first;
1787 ListCell *lc;
1788
1789 appendStringInfoString(buf, "UPDATE ");
1790 deparseRelation(buf, rel);
1791 appendStringInfoString(buf, " SET ");
1792
1793 pindex = 2; /* ctid is always the first param */
1794 first = true;
1795 foreach(lc, targetAttrs)
1796 {
1797 int attnum = lfirst_int(lc);
1798
1799 if (!first)
1800 appendStringInfoString(buf, ", ");
1801 first = false;
1802
1803 deparseColumnRef(buf, rtindex, attnum, rte, false);
1804 appendStringInfo(buf, " = $%d", pindex);
1805 pindex++;
1806 }
1807 appendStringInfoString(buf, " WHERE ctid = $1");
1808
1809 deparseReturningList(buf, rte, rtindex, rel,
1810 rel->trigdesc && rel->trigdesc->trig_update_after_row,
1811 returningList, retrieved_attrs);
1812 }
1813
1814 /*
1815 * deparse remote UPDATE statement
1816 *
1817 * 'buf' is the output buffer to append the statement to
1818 * 'rtindex' is the RT index of the associated target relation
1819 * 'rel' is the relation descriptor for the target relation
1820 * 'foreignrel' is the RelOptInfo for the target relation or the join relation
1821 * containing all base relations in the query
1822 * 'targetlist' is the tlist of the underlying foreign-scan plan node
1823 * 'targetAttrs' is the target columns of the UPDATE
1824 * 'remote_conds' is the qual clauses that must be evaluated remotely
1825 * '*params_list' is an output list of exprs that will become remote Params
1826 * 'returningList' is the RETURNING targetlist
1827 * '*retrieved_attrs' is an output list of integers of columns being retrieved
1828 * by RETURNING (if any)
1829 */
1830 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)1831 deparseDirectUpdateSql(StringInfo buf, PlannerInfo *root,
1832 Index rtindex, Relation rel,
1833 RelOptInfo *foreignrel,
1834 List *targetlist,
1835 List *targetAttrs,
1836 List *remote_conds,
1837 List **params_list,
1838 List *returningList,
1839 List **retrieved_attrs)
1840 {
1841 deparse_expr_cxt context;
1842 int nestlevel;
1843 bool first;
1844 ListCell *lc;
1845 RangeTblEntry *rte = planner_rt_fetch(rtindex, root);
1846
1847 /* Set up context struct for recursion */
1848 context.root = root;
1849 context.foreignrel = foreignrel;
1850 context.scanrel = foreignrel;
1851 context.buf = buf;
1852 context.params_list = params_list;
1853
1854 appendStringInfoString(buf, "UPDATE ");
1855 deparseRelation(buf, rel);
1856 if (foreignrel->reloptkind == RELOPT_JOINREL)
1857 appendStringInfo(buf, " %s%d", REL_ALIAS_PREFIX, rtindex);
1858 appendStringInfoString(buf, " SET ");
1859
1860 /* Make sure any constants in the exprs are printed portably */
1861 nestlevel = set_transmission_modes();
1862
1863 first = true;
1864 foreach(lc, targetAttrs)
1865 {
1866 int attnum = lfirst_int(lc);
1867 TargetEntry *tle = get_tle_by_resno(targetlist, attnum);
1868
1869 if (!tle)
1870 elog(ERROR, "attribute number %d not found in UPDATE targetlist",
1871 attnum);
1872
1873 if (!first)
1874 appendStringInfoString(buf, ", ");
1875 first = false;
1876
1877 deparseColumnRef(buf, rtindex, attnum, rte, false);
1878 appendStringInfoString(buf, " = ");
1879 deparseExpr((Expr *) tle->expr, &context);
1880 }
1881
1882 reset_transmission_modes(nestlevel);
1883
1884 if (foreignrel->reloptkind == RELOPT_JOINREL)
1885 {
1886 List *ignore_conds = NIL;
1887
1888 appendStringInfo(buf, " FROM ");
1889 deparseFromExprForRel(buf, root, foreignrel, true, rtindex,
1890 &ignore_conds, params_list);
1891 remote_conds = list_concat(remote_conds, ignore_conds);
1892 }
1893
1894 if (remote_conds)
1895 {
1896 appendStringInfoString(buf, " WHERE ");
1897 appendConditions(remote_conds, &context);
1898 }
1899
1900 if (foreignrel->reloptkind == RELOPT_JOINREL)
1901 deparseExplicitTargetList(returningList, true, retrieved_attrs,
1902 &context);
1903 else
1904 deparseReturningList(buf, rte, rtindex, rel, false,
1905 returningList, retrieved_attrs);
1906 }
1907
1908 /*
1909 * deparse remote DELETE statement
1910 *
1911 * The statement text is appended to buf, and we also create an integer List
1912 * of the columns being retrieved by RETURNING (if any), which is returned
1913 * to *retrieved_attrs.
1914 */
1915 void
deparseDeleteSql(StringInfo buf,RangeTblEntry * rte,Index rtindex,Relation rel,List * returningList,List ** retrieved_attrs)1916 deparseDeleteSql(StringInfo buf, RangeTblEntry *rte,
1917 Index rtindex, Relation rel,
1918 List *returningList,
1919 List **retrieved_attrs)
1920 {
1921 appendStringInfoString(buf, "DELETE FROM ");
1922 deparseRelation(buf, rel);
1923 appendStringInfoString(buf, " WHERE ctid = $1");
1924
1925 deparseReturningList(buf, rte, rtindex, rel,
1926 rel->trigdesc && rel->trigdesc->trig_delete_after_row,
1927 returningList, retrieved_attrs);
1928 }
1929
1930 /*
1931 * deparse remote DELETE statement
1932 *
1933 * 'buf' is the output buffer to append the statement to
1934 * 'rtindex' is the RT index of the associated target relation
1935 * 'rel' is the relation descriptor for the target relation
1936 * 'foreignrel' is the RelOptInfo for the target relation or the join relation
1937 * containing all base relations in the query
1938 * 'remote_conds' is the qual clauses that must be evaluated remotely
1939 * '*params_list' is an output list of exprs that will become remote Params
1940 * 'returningList' is the RETURNING targetlist
1941 * '*retrieved_attrs' is an output list of integers of columns being retrieved
1942 * by RETURNING (if any)
1943 */
1944 void
deparseDirectDeleteSql(StringInfo buf,PlannerInfo * root,Index rtindex,Relation rel,RelOptInfo * foreignrel,List * remote_conds,List ** params_list,List * returningList,List ** retrieved_attrs)1945 deparseDirectDeleteSql(StringInfo buf, PlannerInfo *root,
1946 Index rtindex, Relation rel,
1947 RelOptInfo *foreignrel,
1948 List *remote_conds,
1949 List **params_list,
1950 List *returningList,
1951 List **retrieved_attrs)
1952 {
1953 deparse_expr_cxt context;
1954
1955 /* Set up context struct for recursion */
1956 context.root = root;
1957 context.foreignrel = foreignrel;
1958 context.scanrel = foreignrel;
1959 context.buf = buf;
1960 context.params_list = params_list;
1961
1962 appendStringInfoString(buf, "DELETE FROM ");
1963 deparseRelation(buf, rel);
1964 if (foreignrel->reloptkind == RELOPT_JOINREL)
1965 appendStringInfo(buf, " %s%d", REL_ALIAS_PREFIX, rtindex);
1966
1967 if (foreignrel->reloptkind == RELOPT_JOINREL)
1968 {
1969 List *ignore_conds = NIL;
1970
1971 appendStringInfo(buf, " USING ");
1972 deparseFromExprForRel(buf, root, foreignrel, true, rtindex,
1973 &ignore_conds, params_list);
1974 remote_conds = list_concat(remote_conds, ignore_conds);
1975 }
1976
1977 if (remote_conds)
1978 {
1979 appendStringInfoString(buf, " WHERE ");
1980 appendConditions(remote_conds, &context);
1981 }
1982
1983 if (foreignrel->reloptkind == RELOPT_JOINREL)
1984 deparseExplicitTargetList(returningList, true, retrieved_attrs,
1985 &context);
1986 else
1987 deparseReturningList(buf, planner_rt_fetch(rtindex, root),
1988 rtindex, rel, false,
1989 returningList, retrieved_attrs);
1990 }
1991
1992 /*
1993 * Add a RETURNING clause, if needed, to an INSERT/UPDATE/DELETE.
1994 */
1995 static void
deparseReturningList(StringInfo buf,RangeTblEntry * rte,Index rtindex,Relation rel,bool trig_after_row,List * returningList,List ** retrieved_attrs)1996 deparseReturningList(StringInfo buf, RangeTblEntry *rte,
1997 Index rtindex, Relation rel,
1998 bool trig_after_row,
1999 List *returningList,
2000 List **retrieved_attrs)
2001 {
2002 Bitmapset *attrs_used = NULL;
2003
2004 if (trig_after_row)
2005 {
2006 /* whole-row reference acquires all non-system columns */
2007 attrs_used =
2008 bms_make_singleton(0 - FirstLowInvalidHeapAttributeNumber);
2009 }
2010
2011 if (returningList != NIL)
2012 {
2013 /*
2014 * We need the attrs, non-system and system, mentioned in the local
2015 * query's RETURNING list.
2016 */
2017 pull_varattnos((Node *) returningList, rtindex,
2018 &attrs_used);
2019 }
2020
2021 if (attrs_used != NULL)
2022 deparseTargetList(buf, rte, rtindex, rel, true, attrs_used, false,
2023 retrieved_attrs);
2024 else
2025 *retrieved_attrs = NIL;
2026 }
2027
2028 /*
2029 * Construct SELECT statement to acquire size in blocks of given relation.
2030 *
2031 * Note: we use local definition of block size, not remote definition.
2032 * This is perhaps debatable.
2033 *
2034 * Note: pg_relation_size() exists in 8.1 and later.
2035 */
2036 void
deparseAnalyzeSizeSql(StringInfo buf,Relation rel)2037 deparseAnalyzeSizeSql(StringInfo buf, Relation rel)
2038 {
2039 StringInfoData relname;
2040
2041 /* We'll need the remote relation name as a literal. */
2042 initStringInfo(&relname);
2043 deparseRelation(&relname, rel);
2044
2045 appendStringInfoString(buf, "SELECT pg_catalog.pg_relation_size(");
2046 deparseStringLiteral(buf, relname.data);
2047 appendStringInfo(buf, "::pg_catalog.regclass) / %d", BLCKSZ);
2048 }
2049
2050 /*
2051 * Construct SELECT statement to acquire sample rows of given relation.
2052 *
2053 * SELECT command is appended to buf, and list of columns retrieved
2054 * is returned to *retrieved_attrs.
2055 */
2056 void
deparseAnalyzeSql(StringInfo buf,Relation rel,List ** retrieved_attrs)2057 deparseAnalyzeSql(StringInfo buf, Relation rel, List **retrieved_attrs)
2058 {
2059 Oid relid = RelationGetRelid(rel);
2060 TupleDesc tupdesc = RelationGetDescr(rel);
2061 int i;
2062 char *colname;
2063 List *options;
2064 ListCell *lc;
2065 bool first = true;
2066
2067 *retrieved_attrs = NIL;
2068
2069 appendStringInfoString(buf, "SELECT ");
2070 for (i = 0; i < tupdesc->natts; i++)
2071 {
2072 /* Ignore dropped columns. */
2073 if (TupleDescAttr(tupdesc, i)->attisdropped)
2074 continue;
2075
2076 if (!first)
2077 appendStringInfoString(buf, ", ");
2078 first = false;
2079
2080 /* Use attribute name or column_name option. */
2081 colname = NameStr(TupleDescAttr(tupdesc, i)->attname);
2082 options = GetForeignColumnOptions(relid, i + 1);
2083
2084 foreach(lc, options)
2085 {
2086 DefElem *def = (DefElem *) lfirst(lc);
2087
2088 if (strcmp(def->defname, "column_name") == 0)
2089 {
2090 colname = defGetString(def);
2091 break;
2092 }
2093 }
2094
2095 appendStringInfoString(buf, quote_identifier(colname));
2096
2097 *retrieved_attrs = lappend_int(*retrieved_attrs, i + 1);
2098 }
2099
2100 /* Don't generate bad syntax for zero-column relation. */
2101 if (first)
2102 appendStringInfoString(buf, "NULL");
2103
2104 /*
2105 * Construct FROM clause
2106 */
2107 appendStringInfoString(buf, " FROM ");
2108 deparseRelation(buf, rel);
2109 }
2110
2111 /*
2112 * Construct name to use for given column, and emit it into buf.
2113 * If it has a column_name FDW option, use that instead of attribute name.
2114 *
2115 * If qualify_col is true, qualify column name with the alias of relation.
2116 */
2117 static void
deparseColumnRef(StringInfo buf,int varno,int varattno,RangeTblEntry * rte,bool qualify_col)2118 deparseColumnRef(StringInfo buf, int varno, int varattno, RangeTblEntry *rte,
2119 bool qualify_col)
2120 {
2121 /* We support fetching the remote side's CTID and OID. */
2122 if (varattno == SelfItemPointerAttributeNumber)
2123 {
2124 if (qualify_col)
2125 ADD_REL_QUALIFIER(buf, varno);
2126 appendStringInfoString(buf, "ctid");
2127 }
2128 else if (varattno == ObjectIdAttributeNumber)
2129 {
2130 if (qualify_col)
2131 ADD_REL_QUALIFIER(buf, varno);
2132 appendStringInfoString(buf, "oid");
2133 }
2134 else if (varattno < 0)
2135 {
2136 /*
2137 * All other system attributes are fetched as 0, except for table OID,
2138 * which is fetched as the local table OID. However, we must be
2139 * careful; the table could be beneath an outer join, in which case it
2140 * must go to NULL whenever the rest of the row does.
2141 */
2142 Oid fetchval = 0;
2143
2144 if (varattno == TableOidAttributeNumber)
2145 fetchval = rte->relid;
2146
2147 if (qualify_col)
2148 {
2149 appendStringInfoString(buf, "CASE WHEN (");
2150 ADD_REL_QUALIFIER(buf, varno);
2151 appendStringInfo(buf, "*)::text IS NOT NULL THEN %u END", fetchval);
2152 }
2153 else
2154 appendStringInfo(buf, "%u", fetchval);
2155 }
2156 else if (varattno == 0)
2157 {
2158 /* Whole row reference */
2159 Relation rel;
2160 Bitmapset *attrs_used;
2161
2162 /* Required only to be passed down to deparseTargetList(). */
2163 List *retrieved_attrs;
2164
2165 /*
2166 * The lock on the relation will be held by upper callers, so it's
2167 * fine to open it with no lock here.
2168 */
2169 rel = heap_open(rte->relid, NoLock);
2170
2171 /*
2172 * The local name of the foreign table can not be recognized by the
2173 * foreign server and the table it references on foreign server might
2174 * have different column ordering or different columns than those
2175 * declared locally. Hence we have to deparse whole-row reference as
2176 * ROW(columns referenced locally). Construct this by deparsing a
2177 * "whole row" attribute.
2178 */
2179 attrs_used = bms_add_member(NULL,
2180 0 - FirstLowInvalidHeapAttributeNumber);
2181
2182 /*
2183 * In case the whole-row reference is under an outer join then it has
2184 * to go NULL whenever the rest of the row goes NULL. Deparsing a join
2185 * query would always involve multiple relations, thus qualify_col
2186 * would be true.
2187 */
2188 if (qualify_col)
2189 {
2190 appendStringInfoString(buf, "CASE WHEN (");
2191 ADD_REL_QUALIFIER(buf, varno);
2192 appendStringInfoString(buf, "*)::text IS NOT NULL THEN ");
2193 }
2194
2195 appendStringInfoString(buf, "ROW(");
2196 deparseTargetList(buf, rte, varno, rel, false, attrs_used, qualify_col,
2197 &retrieved_attrs);
2198 appendStringInfoChar(buf, ')');
2199
2200 /* Complete the CASE WHEN statement started above. */
2201 if (qualify_col)
2202 appendStringInfoString(buf, " END");
2203
2204 heap_close(rel, NoLock);
2205 bms_free(attrs_used);
2206 }
2207 else
2208 {
2209 char *colname = NULL;
2210 List *options;
2211 ListCell *lc;
2212
2213 /* varno must not be any of OUTER_VAR, INNER_VAR and INDEX_VAR. */
2214 Assert(!IS_SPECIAL_VARNO(varno));
2215
2216 /*
2217 * If it's a column of a foreign table, and it has the column_name FDW
2218 * option, use that value.
2219 */
2220 options = GetForeignColumnOptions(rte->relid, varattno);
2221 foreach(lc, options)
2222 {
2223 DefElem *def = (DefElem *) lfirst(lc);
2224
2225 if (strcmp(def->defname, "column_name") == 0)
2226 {
2227 colname = defGetString(def);
2228 break;
2229 }
2230 }
2231
2232 /*
2233 * If it's a column of a regular table or it doesn't have column_name
2234 * FDW option, use attribute name.
2235 */
2236 if (colname == NULL)
2237 colname = get_attname(rte->relid, varattno, false);
2238
2239 if (qualify_col)
2240 ADD_REL_QUALIFIER(buf, varno);
2241
2242 appendStringInfoString(buf, quote_identifier(colname));
2243 }
2244 }
2245
2246 /*
2247 * Append remote name of specified foreign table to buf.
2248 * Use value of table_name FDW option (if any) instead of relation's name.
2249 * Similarly, schema_name FDW option overrides schema name.
2250 */
2251 static void
deparseRelation(StringInfo buf,Relation rel)2252 deparseRelation(StringInfo buf, Relation rel)
2253 {
2254 ForeignTable *table;
2255 const char *nspname = NULL;
2256 const char *relname = NULL;
2257 ListCell *lc;
2258
2259 /* obtain additional catalog information. */
2260 table = GetForeignTable(RelationGetRelid(rel));
2261
2262 /*
2263 * Use value of FDW options if any, instead of the name of object itself.
2264 */
2265 foreach(lc, table->options)
2266 {
2267 DefElem *def = (DefElem *) lfirst(lc);
2268
2269 if (strcmp(def->defname, "schema_name") == 0)
2270 nspname = defGetString(def);
2271 else if (strcmp(def->defname, "table_name") == 0)
2272 relname = defGetString(def);
2273 }
2274
2275 /*
2276 * Note: we could skip printing the schema name if it's pg_catalog, but
2277 * that doesn't seem worth the trouble.
2278 */
2279 if (nspname == NULL)
2280 nspname = get_namespace_name(RelationGetNamespace(rel));
2281 if (relname == NULL)
2282 relname = RelationGetRelationName(rel);
2283
2284 appendStringInfo(buf, "%s.%s",
2285 quote_identifier(nspname), quote_identifier(relname));
2286 }
2287
2288 /*
2289 * Append a SQL string literal representing "val" to buf.
2290 */
2291 void
deparseStringLiteral(StringInfo buf,const char * val)2292 deparseStringLiteral(StringInfo buf, const char *val)
2293 {
2294 const char *valptr;
2295
2296 /*
2297 * Rather than making assumptions about the remote server's value of
2298 * standard_conforming_strings, always use E'foo' syntax if there are any
2299 * backslashes. This will fail on remote servers before 8.1, but those
2300 * are long out of support.
2301 */
2302 if (strchr(val, '\\') != NULL)
2303 appendStringInfoChar(buf, ESCAPE_STRING_SYNTAX);
2304 appendStringInfoChar(buf, '\'');
2305 for (valptr = val; *valptr; valptr++)
2306 {
2307 char ch = *valptr;
2308
2309 if (SQL_STR_DOUBLE(ch, true))
2310 appendStringInfoChar(buf, ch);
2311 appendStringInfoChar(buf, ch);
2312 }
2313 appendStringInfoChar(buf, '\'');
2314 }
2315
2316 /*
2317 * Deparse given expression into context->buf.
2318 *
2319 * This function must support all the same node types that foreign_expr_walker
2320 * accepts.
2321 *
2322 * Note: unlike ruleutils.c, we just use a simple hard-wired parenthesization
2323 * scheme: anything more complex than a Var, Const, function call or cast
2324 * should be self-parenthesized.
2325 */
2326 static void
deparseExpr(Expr * node,deparse_expr_cxt * context)2327 deparseExpr(Expr *node, deparse_expr_cxt *context)
2328 {
2329 if (node == NULL)
2330 return;
2331
2332 switch (nodeTag(node))
2333 {
2334 case T_Var:
2335 deparseVar((Var *) node, context);
2336 break;
2337 case T_Const:
2338 deparseConst((Const *) node, context, 0);
2339 break;
2340 case T_Param:
2341 deparseParam((Param *) node, context);
2342 break;
2343 case T_ArrayRef:
2344 deparseArrayRef((ArrayRef *) node, context);
2345 break;
2346 case T_FuncExpr:
2347 deparseFuncExpr((FuncExpr *) node, context);
2348 break;
2349 case T_OpExpr:
2350 deparseOpExpr((OpExpr *) node, context);
2351 break;
2352 case T_DistinctExpr:
2353 deparseDistinctExpr((DistinctExpr *) node, context);
2354 break;
2355 case T_ScalarArrayOpExpr:
2356 deparseScalarArrayOpExpr((ScalarArrayOpExpr *) node, context);
2357 break;
2358 case T_RelabelType:
2359 deparseRelabelType((RelabelType *) node, context);
2360 break;
2361 case T_BoolExpr:
2362 deparseBoolExpr((BoolExpr *) node, context);
2363 break;
2364 case T_NullTest:
2365 deparseNullTest((NullTest *) node, context);
2366 break;
2367 case T_ArrayExpr:
2368 deparseArrayExpr((ArrayExpr *) node, context);
2369 break;
2370 case T_Aggref:
2371 deparseAggref((Aggref *) node, context);
2372 break;
2373 default:
2374 elog(ERROR, "unsupported expression type for deparse: %d",
2375 (int) nodeTag(node));
2376 break;
2377 }
2378 }
2379
2380 /*
2381 * Deparse given Var node into context->buf.
2382 *
2383 * If the Var belongs to the foreign relation, just print its remote name.
2384 * Otherwise, it's effectively a Param (and will in fact be a Param at
2385 * run time). Handle it the same way we handle plain Params --- see
2386 * deparseParam for comments.
2387 */
2388 static void
deparseVar(Var * node,deparse_expr_cxt * context)2389 deparseVar(Var *node, deparse_expr_cxt *context)
2390 {
2391 Relids relids = context->scanrel->relids;
2392 int relno;
2393 int colno;
2394
2395 /* Qualify columns when multiple relations are involved. */
2396 bool qualify_col = (bms_num_members(relids) > 1);
2397
2398 /*
2399 * If the Var belongs to the foreign relation that is deparsed as a
2400 * subquery, use the relation and column alias to the Var provided by the
2401 * subquery, instead of the remote name.
2402 */
2403 if (is_subquery_var(node, context->scanrel, &relno, &colno))
2404 {
2405 appendStringInfo(context->buf, "%s%d.%s%d",
2406 SUBQUERY_REL_ALIAS_PREFIX, relno,
2407 SUBQUERY_COL_ALIAS_PREFIX, colno);
2408 return;
2409 }
2410
2411 if (bms_is_member(node->varno, relids) && node->varlevelsup == 0)
2412 deparseColumnRef(context->buf, node->varno, node->varattno,
2413 planner_rt_fetch(node->varno, context->root),
2414 qualify_col);
2415 else
2416 {
2417 /* Treat like a Param */
2418 if (context->params_list)
2419 {
2420 int pindex = 0;
2421 ListCell *lc;
2422
2423 /* find its index in params_list */
2424 foreach(lc, *context->params_list)
2425 {
2426 pindex++;
2427 if (equal(node, (Node *) lfirst(lc)))
2428 break;
2429 }
2430 if (lc == NULL)
2431 {
2432 /* not in list, so add it */
2433 pindex++;
2434 *context->params_list = lappend(*context->params_list, node);
2435 }
2436
2437 printRemoteParam(pindex, node->vartype, node->vartypmod, context);
2438 }
2439 else
2440 {
2441 printRemotePlaceholder(node->vartype, node->vartypmod, context);
2442 }
2443 }
2444 }
2445
2446 /*
2447 * Deparse given constant value into context->buf.
2448 *
2449 * This function has to be kept in sync with ruleutils.c's get_const_expr.
2450 * As for that function, showtype can be -1 to never show "::typename" decoration,
2451 * or +1 to always show it, or 0 to show it only if the constant wouldn't be assumed
2452 * to be the right type by default.
2453 */
2454 static void
deparseConst(Const * node,deparse_expr_cxt * context,int showtype)2455 deparseConst(Const *node, deparse_expr_cxt *context, int showtype)
2456 {
2457 StringInfo buf = context->buf;
2458 Oid typoutput;
2459 bool typIsVarlena;
2460 char *extval;
2461 bool isfloat = false;
2462 bool needlabel;
2463
2464 if (node->constisnull)
2465 {
2466 appendStringInfoString(buf, "NULL");
2467 if (showtype >= 0)
2468 appendStringInfo(buf, "::%s",
2469 deparse_type_name(node->consttype,
2470 node->consttypmod));
2471 return;
2472 }
2473
2474 getTypeOutputInfo(node->consttype,
2475 &typoutput, &typIsVarlena);
2476 extval = OidOutputFunctionCall(typoutput, node->constvalue);
2477
2478 switch (node->consttype)
2479 {
2480 case INT2OID:
2481 case INT4OID:
2482 case INT8OID:
2483 case OIDOID:
2484 case FLOAT4OID:
2485 case FLOAT8OID:
2486 case NUMERICOID:
2487 {
2488 /*
2489 * No need to quote unless it's a special value such as 'NaN'.
2490 * See comments in get_const_expr().
2491 */
2492 if (strspn(extval, "0123456789+-eE.") == strlen(extval))
2493 {
2494 if (extval[0] == '+' || extval[0] == '-')
2495 appendStringInfo(buf, "(%s)", extval);
2496 else
2497 appendStringInfoString(buf, extval);
2498 if (strcspn(extval, "eE.") != strlen(extval))
2499 isfloat = true; /* it looks like a float */
2500 }
2501 else
2502 appendStringInfo(buf, "'%s'", extval);
2503 }
2504 break;
2505 case BITOID:
2506 case VARBITOID:
2507 appendStringInfo(buf, "B'%s'", extval);
2508 break;
2509 case BOOLOID:
2510 if (strcmp(extval, "t") == 0)
2511 appendStringInfoString(buf, "true");
2512 else
2513 appendStringInfoString(buf, "false");
2514 break;
2515 default:
2516 deparseStringLiteral(buf, extval);
2517 break;
2518 }
2519
2520 pfree(extval);
2521
2522 if (showtype < 0)
2523 return;
2524
2525 /*
2526 * For showtype == 0, append ::typename unless the constant will be
2527 * implicitly typed as the right type when it is read in.
2528 *
2529 * XXX this code has to be kept in sync with the behavior of the parser,
2530 * especially make_const.
2531 */
2532 switch (node->consttype)
2533 {
2534 case BOOLOID:
2535 case INT4OID:
2536 case UNKNOWNOID:
2537 needlabel = false;
2538 break;
2539 case NUMERICOID:
2540 needlabel = !isfloat || (node->consttypmod >= 0);
2541 break;
2542 default:
2543 needlabel = true;
2544 break;
2545 }
2546 if (needlabel || showtype > 0)
2547 appendStringInfo(buf, "::%s",
2548 deparse_type_name(node->consttype,
2549 node->consttypmod));
2550 }
2551
2552 /*
2553 * Deparse given Param node.
2554 *
2555 * If we're generating the query "for real", add the Param to
2556 * context->params_list if it's not already present, and then use its index
2557 * in that list as the remote parameter number. During EXPLAIN, there's
2558 * no need to identify a parameter number.
2559 */
2560 static void
deparseParam(Param * node,deparse_expr_cxt * context)2561 deparseParam(Param *node, deparse_expr_cxt *context)
2562 {
2563 if (context->params_list)
2564 {
2565 int pindex = 0;
2566 ListCell *lc;
2567
2568 /* find its index in params_list */
2569 foreach(lc, *context->params_list)
2570 {
2571 pindex++;
2572 if (equal(node, (Node *) lfirst(lc)))
2573 break;
2574 }
2575 if (lc == NULL)
2576 {
2577 /* not in list, so add it */
2578 pindex++;
2579 *context->params_list = lappend(*context->params_list, node);
2580 }
2581
2582 printRemoteParam(pindex, node->paramtype, node->paramtypmod, context);
2583 }
2584 else
2585 {
2586 printRemotePlaceholder(node->paramtype, node->paramtypmod, context);
2587 }
2588 }
2589
2590 /*
2591 * Deparse an array subscript expression.
2592 */
2593 static void
deparseArrayRef(ArrayRef * node,deparse_expr_cxt * context)2594 deparseArrayRef(ArrayRef *node, deparse_expr_cxt *context)
2595 {
2596 StringInfo buf = context->buf;
2597 ListCell *lowlist_item;
2598 ListCell *uplist_item;
2599
2600 /* Always parenthesize the expression. */
2601 appendStringInfoChar(buf, '(');
2602
2603 /*
2604 * Deparse referenced array expression first. If that expression includes
2605 * a cast, we have to parenthesize to prevent the array subscript from
2606 * being taken as typename decoration. We can avoid that in the typical
2607 * case of subscripting a Var, but otherwise do it.
2608 */
2609 if (IsA(node->refexpr, Var))
2610 deparseExpr(node->refexpr, context);
2611 else
2612 {
2613 appendStringInfoChar(buf, '(');
2614 deparseExpr(node->refexpr, context);
2615 appendStringInfoChar(buf, ')');
2616 }
2617
2618 /* Deparse subscript expressions. */
2619 lowlist_item = list_head(node->reflowerindexpr); /* could be NULL */
2620 foreach(uplist_item, node->refupperindexpr)
2621 {
2622 appendStringInfoChar(buf, '[');
2623 if (lowlist_item)
2624 {
2625 deparseExpr(lfirst(lowlist_item), context);
2626 appendStringInfoChar(buf, ':');
2627 lowlist_item = lnext(lowlist_item);
2628 }
2629 deparseExpr(lfirst(uplist_item), context);
2630 appendStringInfoChar(buf, ']');
2631 }
2632
2633 appendStringInfoChar(buf, ')');
2634 }
2635
2636 /*
2637 * Deparse a function call.
2638 */
2639 static void
deparseFuncExpr(FuncExpr * node,deparse_expr_cxt * context)2640 deparseFuncExpr(FuncExpr *node, deparse_expr_cxt *context)
2641 {
2642 StringInfo buf = context->buf;
2643 bool use_variadic;
2644 bool first;
2645 ListCell *arg;
2646
2647 /*
2648 * If the function call came from an implicit coercion, then just show the
2649 * first argument.
2650 */
2651 if (node->funcformat == COERCE_IMPLICIT_CAST)
2652 {
2653 deparseExpr((Expr *) linitial(node->args), context);
2654 return;
2655 }
2656
2657 /*
2658 * If the function call came from a cast, then show the first argument
2659 * plus an explicit cast operation.
2660 */
2661 if (node->funcformat == COERCE_EXPLICIT_CAST)
2662 {
2663 Oid rettype = node->funcresulttype;
2664 int32 coercedTypmod;
2665
2666 /* Get the typmod if this is a length-coercion function */
2667 (void) exprIsLengthCoercion((Node *) node, &coercedTypmod);
2668
2669 deparseExpr((Expr *) linitial(node->args), context);
2670 appendStringInfo(buf, "::%s",
2671 deparse_type_name(rettype, coercedTypmod));
2672 return;
2673 }
2674
2675 /* Check if need to print VARIADIC (cf. ruleutils.c) */
2676 use_variadic = node->funcvariadic;
2677
2678 /*
2679 * Normal function: display as proname(args).
2680 */
2681 appendFunctionName(node->funcid, context);
2682 appendStringInfoChar(buf, '(');
2683
2684 /* ... and all the arguments */
2685 first = true;
2686 foreach(arg, node->args)
2687 {
2688 if (!first)
2689 appendStringInfoString(buf, ", ");
2690 if (use_variadic && lnext(arg) == NULL)
2691 appendStringInfoString(buf, "VARIADIC ");
2692 deparseExpr((Expr *) lfirst(arg), context);
2693 first = false;
2694 }
2695 appendStringInfoChar(buf, ')');
2696 }
2697
2698 /*
2699 * Deparse given operator expression. To avoid problems around
2700 * priority of operations, we always parenthesize the arguments.
2701 */
2702 static void
deparseOpExpr(OpExpr * node,deparse_expr_cxt * context)2703 deparseOpExpr(OpExpr *node, deparse_expr_cxt *context)
2704 {
2705 StringInfo buf = context->buf;
2706 HeapTuple tuple;
2707 Form_pg_operator form;
2708 char oprkind;
2709 ListCell *arg;
2710
2711 /* Retrieve information about the operator from system catalog. */
2712 tuple = SearchSysCache1(OPEROID, ObjectIdGetDatum(node->opno));
2713 if (!HeapTupleIsValid(tuple))
2714 elog(ERROR, "cache lookup failed for operator %u", node->opno);
2715 form = (Form_pg_operator) GETSTRUCT(tuple);
2716 oprkind = form->oprkind;
2717
2718 /* Sanity check. */
2719 Assert((oprkind == 'r' && list_length(node->args) == 1) ||
2720 (oprkind == 'l' && list_length(node->args) == 1) ||
2721 (oprkind == 'b' && list_length(node->args) == 2));
2722
2723 /* Always parenthesize the expression. */
2724 appendStringInfoChar(buf, '(');
2725
2726 /* Deparse left operand. */
2727 if (oprkind == 'r' || oprkind == 'b')
2728 {
2729 arg = list_head(node->args);
2730 deparseExpr(lfirst(arg), context);
2731 appendStringInfoChar(buf, ' ');
2732 }
2733
2734 /* Deparse operator name. */
2735 deparseOperatorName(buf, form);
2736
2737 /* Deparse right operand. */
2738 if (oprkind == 'l' || oprkind == 'b')
2739 {
2740 arg = list_tail(node->args);
2741 appendStringInfoChar(buf, ' ');
2742 deparseExpr(lfirst(arg), context);
2743 }
2744
2745 appendStringInfoChar(buf, ')');
2746
2747 ReleaseSysCache(tuple);
2748 }
2749
2750 /*
2751 * Print the name of an operator.
2752 */
2753 static void
deparseOperatorName(StringInfo buf,Form_pg_operator opform)2754 deparseOperatorName(StringInfo buf, Form_pg_operator opform)
2755 {
2756 char *opname;
2757
2758 /* opname is not a SQL identifier, so we should not quote it. */
2759 opname = NameStr(opform->oprname);
2760
2761 /* Print schema name only if it's not pg_catalog */
2762 if (opform->oprnamespace != PG_CATALOG_NAMESPACE)
2763 {
2764 const char *opnspname;
2765
2766 opnspname = get_namespace_name(opform->oprnamespace);
2767 /* Print fully qualified operator name. */
2768 appendStringInfo(buf, "OPERATOR(%s.%s)",
2769 quote_identifier(opnspname), opname);
2770 }
2771 else
2772 {
2773 /* Just print operator name. */
2774 appendStringInfoString(buf, opname);
2775 }
2776 }
2777
2778 /*
2779 * Deparse IS DISTINCT FROM.
2780 */
2781 static void
deparseDistinctExpr(DistinctExpr * node,deparse_expr_cxt * context)2782 deparseDistinctExpr(DistinctExpr *node, deparse_expr_cxt *context)
2783 {
2784 StringInfo buf = context->buf;
2785
2786 Assert(list_length(node->args) == 2);
2787
2788 appendStringInfoChar(buf, '(');
2789 deparseExpr(linitial(node->args), context);
2790 appendStringInfoString(buf, " IS DISTINCT FROM ");
2791 deparseExpr(lsecond(node->args), context);
2792 appendStringInfoChar(buf, ')');
2793 }
2794
2795 /*
2796 * Deparse given ScalarArrayOpExpr expression. To avoid problems
2797 * around priority of operations, we always parenthesize the arguments.
2798 */
2799 static void
deparseScalarArrayOpExpr(ScalarArrayOpExpr * node,deparse_expr_cxt * context)2800 deparseScalarArrayOpExpr(ScalarArrayOpExpr *node, deparse_expr_cxt *context)
2801 {
2802 StringInfo buf = context->buf;
2803 HeapTuple tuple;
2804 Form_pg_operator form;
2805 Expr *arg1;
2806 Expr *arg2;
2807
2808 /* Retrieve information about the operator from system catalog. */
2809 tuple = SearchSysCache1(OPEROID, ObjectIdGetDatum(node->opno));
2810 if (!HeapTupleIsValid(tuple))
2811 elog(ERROR, "cache lookup failed for operator %u", node->opno);
2812 form = (Form_pg_operator) GETSTRUCT(tuple);
2813
2814 /* Sanity check. */
2815 Assert(list_length(node->args) == 2);
2816
2817 /* Always parenthesize the expression. */
2818 appendStringInfoChar(buf, '(');
2819
2820 /* Deparse left operand. */
2821 arg1 = linitial(node->args);
2822 deparseExpr(arg1, context);
2823 appendStringInfoChar(buf, ' ');
2824
2825 /* Deparse operator name plus decoration. */
2826 deparseOperatorName(buf, form);
2827 appendStringInfo(buf, " %s (", node->useOr ? "ANY" : "ALL");
2828
2829 /* Deparse right operand. */
2830 arg2 = lsecond(node->args);
2831 deparseExpr(arg2, context);
2832
2833 appendStringInfoChar(buf, ')');
2834
2835 /* Always parenthesize the expression. */
2836 appendStringInfoChar(buf, ')');
2837
2838 ReleaseSysCache(tuple);
2839 }
2840
2841 /*
2842 * Deparse a RelabelType (binary-compatible cast) node.
2843 */
2844 static void
deparseRelabelType(RelabelType * node,deparse_expr_cxt * context)2845 deparseRelabelType(RelabelType *node, deparse_expr_cxt *context)
2846 {
2847 deparseExpr(node->arg, context);
2848 if (node->relabelformat != COERCE_IMPLICIT_CAST)
2849 appendStringInfo(context->buf, "::%s",
2850 deparse_type_name(node->resulttype,
2851 node->resulttypmod));
2852 }
2853
2854 /*
2855 * Deparse a BoolExpr node.
2856 */
2857 static void
deparseBoolExpr(BoolExpr * node,deparse_expr_cxt * context)2858 deparseBoolExpr(BoolExpr *node, deparse_expr_cxt *context)
2859 {
2860 StringInfo buf = context->buf;
2861 const char *op = NULL; /* keep compiler quiet */
2862 bool first;
2863 ListCell *lc;
2864
2865 switch (node->boolop)
2866 {
2867 case AND_EXPR:
2868 op = "AND";
2869 break;
2870 case OR_EXPR:
2871 op = "OR";
2872 break;
2873 case NOT_EXPR:
2874 appendStringInfoString(buf, "(NOT ");
2875 deparseExpr(linitial(node->args), context);
2876 appendStringInfoChar(buf, ')');
2877 return;
2878 }
2879
2880 appendStringInfoChar(buf, '(');
2881 first = true;
2882 foreach(lc, node->args)
2883 {
2884 if (!first)
2885 appendStringInfo(buf, " %s ", op);
2886 deparseExpr((Expr *) lfirst(lc), context);
2887 first = false;
2888 }
2889 appendStringInfoChar(buf, ')');
2890 }
2891
2892 /*
2893 * Deparse IS [NOT] NULL expression.
2894 */
2895 static void
deparseNullTest(NullTest * node,deparse_expr_cxt * context)2896 deparseNullTest(NullTest *node, deparse_expr_cxt *context)
2897 {
2898 StringInfo buf = context->buf;
2899
2900 appendStringInfoChar(buf, '(');
2901 deparseExpr(node->arg, context);
2902
2903 /*
2904 * For scalar inputs, we prefer to print as IS [NOT] NULL, which is
2905 * shorter and traditional. If it's a rowtype input but we're applying a
2906 * scalar test, must print IS [NOT] DISTINCT FROM NULL to be semantically
2907 * correct.
2908 */
2909 if (node->argisrow || !type_is_rowtype(exprType((Node *) node->arg)))
2910 {
2911 if (node->nulltesttype == IS_NULL)
2912 appendStringInfoString(buf, " IS NULL)");
2913 else
2914 appendStringInfoString(buf, " IS NOT NULL)");
2915 }
2916 else
2917 {
2918 if (node->nulltesttype == IS_NULL)
2919 appendStringInfoString(buf, " IS NOT DISTINCT FROM NULL)");
2920 else
2921 appendStringInfoString(buf, " IS DISTINCT FROM NULL)");
2922 }
2923 }
2924
2925 /*
2926 * Deparse ARRAY[...] construct.
2927 */
2928 static void
deparseArrayExpr(ArrayExpr * node,deparse_expr_cxt * context)2929 deparseArrayExpr(ArrayExpr *node, deparse_expr_cxt *context)
2930 {
2931 StringInfo buf = context->buf;
2932 bool first = true;
2933 ListCell *lc;
2934
2935 appendStringInfoString(buf, "ARRAY[");
2936 foreach(lc, node->elements)
2937 {
2938 if (!first)
2939 appendStringInfoString(buf, ", ");
2940 deparseExpr(lfirst(lc), context);
2941 first = false;
2942 }
2943 appendStringInfoChar(buf, ']');
2944
2945 /* If the array is empty, we need an explicit cast to the array type. */
2946 if (node->elements == NIL)
2947 appendStringInfo(buf, "::%s",
2948 deparse_type_name(node->array_typeid, -1));
2949 }
2950
2951 /*
2952 * Deparse an Aggref node.
2953 */
2954 static void
deparseAggref(Aggref * node,deparse_expr_cxt * context)2955 deparseAggref(Aggref *node, deparse_expr_cxt *context)
2956 {
2957 StringInfo buf = context->buf;
2958 bool use_variadic;
2959
2960 /* Only basic, non-split aggregation accepted. */
2961 Assert(node->aggsplit == AGGSPLIT_SIMPLE);
2962
2963 /* Check if need to print VARIADIC (cf. ruleutils.c) */
2964 use_variadic = node->aggvariadic;
2965
2966 /* Find aggregate name from aggfnoid which is a pg_proc entry */
2967 appendFunctionName(node->aggfnoid, context);
2968 appendStringInfoChar(buf, '(');
2969
2970 /* Add DISTINCT */
2971 appendStringInfoString(buf, (node->aggdistinct != NIL) ? "DISTINCT " : "");
2972
2973 if (AGGKIND_IS_ORDERED_SET(node->aggkind))
2974 {
2975 /* Add WITHIN GROUP (ORDER BY ..) */
2976 ListCell *arg;
2977 bool first = true;
2978
2979 Assert(!node->aggvariadic);
2980 Assert(node->aggorder != NIL);
2981
2982 foreach(arg, node->aggdirectargs)
2983 {
2984 if (!first)
2985 appendStringInfoString(buf, ", ");
2986 first = false;
2987
2988 deparseExpr((Expr *) lfirst(arg), context);
2989 }
2990
2991 appendStringInfoString(buf, ") WITHIN GROUP (ORDER BY ");
2992 appendAggOrderBy(node->aggorder, node->args, context);
2993 }
2994 else
2995 {
2996 /* aggstar can be set only in zero-argument aggregates */
2997 if (node->aggstar)
2998 appendStringInfoChar(buf, '*');
2999 else
3000 {
3001 ListCell *arg;
3002 bool first = true;
3003
3004 /* Add all the arguments */
3005 foreach(arg, node->args)
3006 {
3007 TargetEntry *tle = (TargetEntry *) lfirst(arg);
3008 Node *n = (Node *) tle->expr;
3009
3010 if (tle->resjunk)
3011 continue;
3012
3013 if (!first)
3014 appendStringInfoString(buf, ", ");
3015 first = false;
3016
3017 /* Add VARIADIC */
3018 if (use_variadic && lnext(arg) == NULL)
3019 appendStringInfoString(buf, "VARIADIC ");
3020
3021 deparseExpr((Expr *) n, context);
3022 }
3023 }
3024
3025 /* Add ORDER BY */
3026 if (node->aggorder != NIL)
3027 {
3028 appendStringInfoString(buf, " ORDER BY ");
3029 appendAggOrderBy(node->aggorder, node->args, context);
3030 }
3031 }
3032
3033 /* Add FILTER (WHERE ..) */
3034 if (node->aggfilter != NULL)
3035 {
3036 appendStringInfoString(buf, ") FILTER (WHERE ");
3037 deparseExpr((Expr *) node->aggfilter, context);
3038 }
3039
3040 appendStringInfoChar(buf, ')');
3041 }
3042
3043 /*
3044 * Append ORDER BY within aggregate function.
3045 */
3046 static void
appendAggOrderBy(List * orderList,List * targetList,deparse_expr_cxt * context)3047 appendAggOrderBy(List *orderList, List *targetList, deparse_expr_cxt *context)
3048 {
3049 StringInfo buf = context->buf;
3050 ListCell *lc;
3051 bool first = true;
3052
3053 foreach(lc, orderList)
3054 {
3055 SortGroupClause *srt = (SortGroupClause *) lfirst(lc);
3056 Node *sortexpr;
3057 Oid sortcoltype;
3058 TypeCacheEntry *typentry;
3059
3060 if (!first)
3061 appendStringInfoString(buf, ", ");
3062 first = false;
3063
3064 sortexpr = deparseSortGroupClause(srt->tleSortGroupRef, targetList,
3065 false, context);
3066 sortcoltype = exprType(sortexpr);
3067 /* See whether operator is default < or > for datatype */
3068 typentry = lookup_type_cache(sortcoltype,
3069 TYPECACHE_LT_OPR | TYPECACHE_GT_OPR);
3070 if (srt->sortop == typentry->lt_opr)
3071 appendStringInfoString(buf, " ASC");
3072 else if (srt->sortop == typentry->gt_opr)
3073 appendStringInfoString(buf, " DESC");
3074 else
3075 {
3076 HeapTuple opertup;
3077 Form_pg_operator operform;
3078
3079 appendStringInfoString(buf, " USING ");
3080
3081 /* Append operator name. */
3082 opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(srt->sortop));
3083 if (!HeapTupleIsValid(opertup))
3084 elog(ERROR, "cache lookup failed for operator %u", srt->sortop);
3085 operform = (Form_pg_operator) GETSTRUCT(opertup);
3086 deparseOperatorName(buf, operform);
3087 ReleaseSysCache(opertup);
3088 }
3089
3090 if (srt->nulls_first)
3091 appendStringInfoString(buf, " NULLS FIRST");
3092 else
3093 appendStringInfoString(buf, " NULLS LAST");
3094 }
3095 }
3096
3097 /*
3098 * Print the representation of a parameter to be sent to the remote side.
3099 *
3100 * Note: we always label the Param's type explicitly rather than relying on
3101 * transmitting a numeric type OID in PQexecParams(). This allows us to
3102 * avoid assuming that types have the same OIDs on the remote side as they
3103 * do locally --- they need only have the same names.
3104 */
3105 static void
printRemoteParam(int paramindex,Oid paramtype,int32 paramtypmod,deparse_expr_cxt * context)3106 printRemoteParam(int paramindex, Oid paramtype, int32 paramtypmod,
3107 deparse_expr_cxt *context)
3108 {
3109 StringInfo buf = context->buf;
3110 char *ptypename = deparse_type_name(paramtype, paramtypmod);
3111
3112 appendStringInfo(buf, "$%d::%s", paramindex, ptypename);
3113 }
3114
3115 /*
3116 * Print the representation of a placeholder for a parameter that will be
3117 * sent to the remote side at execution time.
3118 *
3119 * This is used when we're just trying to EXPLAIN the remote query.
3120 * We don't have the actual value of the runtime parameter yet, and we don't
3121 * want the remote planner to generate a plan that depends on such a value
3122 * anyway. Thus, we can't do something simple like "$1::paramtype".
3123 * Instead, we emit "((SELECT null::paramtype)::paramtype)".
3124 * In all extant versions of Postgres, the planner will see that as an unknown
3125 * constant value, which is what we want. This might need adjustment if we
3126 * ever make the planner flatten scalar subqueries. Note: the reason for the
3127 * apparently useless outer cast is to ensure that the representation as a
3128 * whole will be parsed as an a_expr and not a select_with_parens; the latter
3129 * would do the wrong thing in the context "x = ANY(...)".
3130 */
3131 static void
printRemotePlaceholder(Oid paramtype,int32 paramtypmod,deparse_expr_cxt * context)3132 printRemotePlaceholder(Oid paramtype, int32 paramtypmod,
3133 deparse_expr_cxt *context)
3134 {
3135 StringInfo buf = context->buf;
3136 char *ptypename = deparse_type_name(paramtype, paramtypmod);
3137
3138 appendStringInfo(buf, "((SELECT null::%s)::%s)", ptypename, ptypename);
3139 }
3140
3141 /*
3142 * Deparse GROUP BY clause.
3143 */
3144 static void
appendGroupByClause(List * tlist,deparse_expr_cxt * context)3145 appendGroupByClause(List *tlist, deparse_expr_cxt *context)
3146 {
3147 StringInfo buf = context->buf;
3148 Query *query = context->root->parse;
3149 ListCell *lc;
3150 bool first = true;
3151
3152 /* Nothing to be done, if there's no GROUP BY clause in the query. */
3153 if (!query->groupClause)
3154 return;
3155
3156 appendStringInfoString(buf, " GROUP BY ");
3157
3158 /*
3159 * Queries with grouping sets are not pushed down, so we don't expect
3160 * grouping sets here.
3161 */
3162 Assert(!query->groupingSets);
3163
3164 foreach(lc, query->groupClause)
3165 {
3166 SortGroupClause *grp = (SortGroupClause *) lfirst(lc);
3167
3168 if (!first)
3169 appendStringInfoString(buf, ", ");
3170 first = false;
3171
3172 deparseSortGroupClause(grp->tleSortGroupRef, tlist, true, context);
3173 }
3174 }
3175
3176 /*
3177 * Deparse ORDER BY clause according to the given pathkeys for given base
3178 * relation. From given pathkeys expressions belonging entirely to the given
3179 * base relation are obtained and deparsed.
3180 */
3181 static void
appendOrderByClause(List * pathkeys,deparse_expr_cxt * context)3182 appendOrderByClause(List *pathkeys, deparse_expr_cxt *context)
3183 {
3184 ListCell *lcell;
3185 int nestlevel;
3186 char *delim = " ";
3187 RelOptInfo *baserel = context->scanrel;
3188 StringInfo buf = context->buf;
3189
3190 /* Make sure any constants in the exprs are printed portably */
3191 nestlevel = set_transmission_modes();
3192
3193 appendStringInfoString(buf, " ORDER BY");
3194 foreach(lcell, pathkeys)
3195 {
3196 PathKey *pathkey = lfirst(lcell);
3197 Expr *em_expr;
3198
3199 em_expr = find_em_expr_for_rel(pathkey->pk_eclass, baserel);
3200 Assert(em_expr != NULL);
3201
3202 appendStringInfoString(buf, delim);
3203 deparseExpr(em_expr, context);
3204 if (pathkey->pk_strategy == BTLessStrategyNumber)
3205 appendStringInfoString(buf, " ASC");
3206 else
3207 appendStringInfoString(buf, " DESC");
3208
3209 if (pathkey->pk_nulls_first)
3210 appendStringInfoString(buf, " NULLS FIRST");
3211 else
3212 appendStringInfoString(buf, " NULLS LAST");
3213
3214 delim = ", ";
3215 }
3216 reset_transmission_modes(nestlevel);
3217 }
3218
3219 /*
3220 * appendFunctionName
3221 * Deparses function name from given function oid.
3222 */
3223 static void
appendFunctionName(Oid funcid,deparse_expr_cxt * context)3224 appendFunctionName(Oid funcid, deparse_expr_cxt *context)
3225 {
3226 StringInfo buf = context->buf;
3227 HeapTuple proctup;
3228 Form_pg_proc procform;
3229 const char *proname;
3230
3231 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
3232 if (!HeapTupleIsValid(proctup))
3233 elog(ERROR, "cache lookup failed for function %u", funcid);
3234 procform = (Form_pg_proc) GETSTRUCT(proctup);
3235
3236 /* Print schema name only if it's not pg_catalog */
3237 if (procform->pronamespace != PG_CATALOG_NAMESPACE)
3238 {
3239 const char *schemaname;
3240
3241 schemaname = get_namespace_name(procform->pronamespace);
3242 appendStringInfo(buf, "%s.", quote_identifier(schemaname));
3243 }
3244
3245 /* Always print the function name */
3246 proname = NameStr(procform->proname);
3247 appendStringInfoString(buf, quote_identifier(proname));
3248
3249 ReleaseSysCache(proctup);
3250 }
3251
3252 /*
3253 * Appends a sort or group clause.
3254 *
3255 * Like get_rule_sortgroupclause(), returns the expression tree, so caller
3256 * need not find it again.
3257 */
3258 static Node *
deparseSortGroupClause(Index ref,List * tlist,bool force_colno,deparse_expr_cxt * context)3259 deparseSortGroupClause(Index ref, List *tlist, bool force_colno,
3260 deparse_expr_cxt *context)
3261 {
3262 StringInfo buf = context->buf;
3263 TargetEntry *tle;
3264 Expr *expr;
3265
3266 tle = get_sortgroupref_tle(ref, tlist);
3267 expr = tle->expr;
3268
3269 if (force_colno)
3270 {
3271 /* Use column-number form when requested by caller. */
3272 Assert(!tle->resjunk);
3273 appendStringInfo(buf, "%d", tle->resno);
3274 }
3275 else if (expr && IsA(expr, Const))
3276 {
3277 /*
3278 * Force a typecast here so that we don't emit something like "GROUP
3279 * BY 2", which will be misconstrued as a column position rather than
3280 * a constant.
3281 */
3282 deparseConst((Const *) expr, context, 1);
3283 }
3284 else if (!expr || IsA(expr, Var))
3285 deparseExpr(expr, context);
3286 else
3287 {
3288 /* Always parenthesize the expression. */
3289 appendStringInfoChar(buf, '(');
3290 deparseExpr(expr, context);
3291 appendStringInfoChar(buf, ')');
3292 }
3293
3294 return (Node *) expr;
3295 }
3296
3297
3298 /*
3299 * Returns true if given Var is deparsed as a subquery output column, in
3300 * which case, *relno and *colno are set to the IDs for the relation and
3301 * column alias to the Var provided by the subquery.
3302 */
3303 static bool
is_subquery_var(Var * node,RelOptInfo * foreignrel,int * relno,int * colno)3304 is_subquery_var(Var *node, RelOptInfo *foreignrel, int *relno, int *colno)
3305 {
3306 PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
3307 RelOptInfo *outerrel = fpinfo->outerrel;
3308 RelOptInfo *innerrel = fpinfo->innerrel;
3309
3310 /* Should only be called in these cases. */
3311 Assert(IS_SIMPLE_REL(foreignrel) || IS_JOIN_REL(foreignrel));
3312
3313 /*
3314 * If the given relation isn't a join relation, it doesn't have any lower
3315 * subqueries, so the Var isn't a subquery output column.
3316 */
3317 if (!IS_JOIN_REL(foreignrel))
3318 return false;
3319
3320 /*
3321 * If the Var doesn't belong to any lower subqueries, it isn't a subquery
3322 * output column.
3323 */
3324 if (!bms_is_member(node->varno, fpinfo->lower_subquery_rels))
3325 return false;
3326
3327 if (bms_is_member(node->varno, outerrel->relids))
3328 {
3329 /*
3330 * If outer relation is deparsed as a subquery, the Var is an output
3331 * column of the subquery; get the IDs for the relation/column alias.
3332 */
3333 if (fpinfo->make_outerrel_subquery)
3334 {
3335 get_relation_column_alias_ids(node, outerrel, relno, colno);
3336 return true;
3337 }
3338
3339 /* Otherwise, recurse into the outer relation. */
3340 return is_subquery_var(node, outerrel, relno, colno);
3341 }
3342 else
3343 {
3344 Assert(bms_is_member(node->varno, innerrel->relids));
3345
3346 /*
3347 * If inner relation is deparsed as a subquery, the Var is an output
3348 * column of the subquery; get the IDs for the relation/column alias.
3349 */
3350 if (fpinfo->make_innerrel_subquery)
3351 {
3352 get_relation_column_alias_ids(node, innerrel, relno, colno);
3353 return true;
3354 }
3355
3356 /* Otherwise, recurse into the inner relation. */
3357 return is_subquery_var(node, innerrel, relno, colno);
3358 }
3359 }
3360
3361 /*
3362 * Get the IDs for the relation and column alias to given Var belonging to
3363 * given relation, which are returned into *relno and *colno.
3364 */
3365 static void
get_relation_column_alias_ids(Var * node,RelOptInfo * foreignrel,int * relno,int * colno)3366 get_relation_column_alias_ids(Var *node, RelOptInfo *foreignrel,
3367 int *relno, int *colno)
3368 {
3369 PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
3370 int i;
3371 ListCell *lc;
3372
3373 /* Get the relation alias ID */
3374 *relno = fpinfo->relation_index;
3375
3376 /* Get the column alias ID */
3377 i = 1;
3378 foreach(lc, foreignrel->reltarget->exprs)
3379 {
3380 if (equal(lfirst(lc), (Node *) node))
3381 {
3382 *colno = i;
3383 return;
3384 }
3385 i++;
3386 }
3387
3388 /* Shouldn't get here */
3389 elog(ERROR, "unexpected expression in subquery output");
3390 }
3391