1 /*-------------------------------------------------------------------------
4 * Query deparser for postgres_fdw
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.
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.
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.
27 * Portions Copyright (c) 2012-2023, PostgreSQL Global Development Group
30 * contrib/postgres_fdw/deparse.c
32 *-------------------------------------------------------------------------
36 #include "access/htup_details.h"
37 #include "access/sysattr.h"
38 #include "access/table.h"
39 #include "catalog/pg_aggregate.h"
40 #include "catalog/pg_authid.h"
41 #include "catalog/pg_collation.h"
42 #include "catalog/pg_namespace.h"
43 #include "catalog/pg_operator.h"
44 #include "catalog/pg_opfamily.h"
45 #include "catalog/pg_proc.h"
46 #include "catalog/pg_ts_config.h"
47 #include "catalog/pg_ts_dict.h"
48 #include "catalog/pg_type.h"
49 #include "commands/defrem.h"
50 #include "nodes/makefuncs.h"
51 #include "nodes/nodeFuncs.h"
52 #include "nodes/plannodes.h"
53 #include "optimizer/optimizer.h"
54 #include "optimizer/prep.h"
55 #include "optimizer/tlist.h"
56 #include "parser/parsetree.h"
57 #include "postgres_fdw.h"
58 #include "utils/builtins.h"
59 #include "utils/lsyscache.h"
60 #include "utils/rel.h"
61 #include "utils/syscache.h"
62 #include "utils/typcache.h"
63 #include "commands/tablecmds.h"
66 * Global context for foreign_expr_walker's search of an expression tree.
68 typedef struct foreign_glob_cxt
70 PlannerInfo
*root
; /* global planner state */
71 RelOptInfo
*foreignrel
; /* the foreign relation we are planning for */
72 Relids relids
; /* relids of base relations in the underlying
77 * Local (per-tree-level) context for foreign_expr_walker's search.
78 * This is concerned with identifying collations used in the expression.
82 FDW_COLLATE_NONE
, /* expression is of a noncollatable type, or
83 * it has default collation that is not
84 * traceable to a foreign Var */
85 FDW_COLLATE_SAFE
, /* collation derives from a foreign Var */
86 FDW_COLLATE_UNSAFE
/* collation is non-default and derives from
87 * something other than a foreign Var */
90 typedef struct foreign_loc_cxt
92 Oid collation
; /* OID of current collation, if any */
93 FDWCollateState state
; /* state of current collation choice */
97 * Context for deparseExpr
99 typedef struct deparse_expr_cxt
101 PlannerInfo
*root
; /* global planner state */
102 RelOptInfo
*foreignrel
; /* the foreign relation we are planning for */
103 RelOptInfo
*scanrel
; /* the underlying scan relation. Same as
104 * foreignrel, when that represents a join or
105 * a base relation. */
106 StringInfo buf
; /* output buffer to append to */
107 List
**params_list
; /* exprs that will become remote Params */
110 #define REL_ALIAS_PREFIX "r"
111 /* Handy macro to add relation name qualification */
112 #define ADD_REL_QUALIFIER(buf, varno) \
113 appendStringInfo((buf), "%s%d.", REL_ALIAS_PREFIX, (varno))
114 #define SUBQUERY_REL_ALIAS_PREFIX "s"
115 #define SUBQUERY_COL_ALIAS_PREFIX "c"
118 * Functions to determine whether an expression can be evaluated safely on
121 static bool foreign_expr_walker(Node
*node
,
122 foreign_glob_cxt
*glob_cxt
,
123 foreign_loc_cxt
*outer_cxt
,
124 foreign_loc_cxt
*case_arg_cxt
);
125 static char *deparse_type_name(Oid type_oid
, int32 typemod
);
128 * Functions to construct string representation of a node tree.
130 static void deparseTargetList(StringInfo buf
,
135 Bitmapset
*attrs_used
,
137 List
**retrieved_attrs
);
138 static void deparseExplicitTargetList(List
*tlist
,
140 List
**retrieved_attrs
,
141 deparse_expr_cxt
*context
);
142 static void deparseSubqueryTargetList(deparse_expr_cxt
*context
);
143 static void deparseReturningList(StringInfo buf
, RangeTblEntry
*rte
,
144 Index rtindex
, Relation rel
,
146 List
*withCheckOptionList
,
148 List
**retrieved_attrs
);
149 static void deparseColumnRef(StringInfo buf
, int varno
, int varattno
,
150 RangeTblEntry
*rte
, bool qualify_col
);
151 static void deparseRelation(StringInfo buf
, Relation rel
);
152 static void deparseExpr(Expr
*node
, deparse_expr_cxt
*context
);
153 static void deparseVar(Var
*node
, deparse_expr_cxt
*context
);
154 static void deparseConst(Const
*node
, deparse_expr_cxt
*context
, int showtype
);
155 static void deparseParam(Param
*node
, deparse_expr_cxt
*context
);
156 static void deparseSubscriptingRef(SubscriptingRef
*node
, deparse_expr_cxt
*context
);
157 static void deparseFuncExpr(FuncExpr
*node
, deparse_expr_cxt
*context
);
158 static void deparseOpExpr(OpExpr
*node
, deparse_expr_cxt
*context
);
159 static bool isPlainForeignVar(Expr
*node
, deparse_expr_cxt
*context
);
160 static void deparseOperatorName(StringInfo buf
, Form_pg_operator opform
);
161 static void deparseDistinctExpr(DistinctExpr
*node
, deparse_expr_cxt
*context
);
162 static void deparseScalarArrayOpExpr(ScalarArrayOpExpr
*node
,
163 deparse_expr_cxt
*context
);
164 static void deparseRelabelType(RelabelType
*node
, deparse_expr_cxt
*context
);
165 static void deparseBoolExpr(BoolExpr
*node
, deparse_expr_cxt
*context
);
166 static void deparseNullTest(NullTest
*node
, deparse_expr_cxt
*context
);
167 static void deparseCaseExpr(CaseExpr
*node
, deparse_expr_cxt
*context
);
168 static void deparseArrayExpr(ArrayExpr
*node
, deparse_expr_cxt
*context
);
169 static void printRemoteParam(int paramindex
, Oid paramtype
, int32 paramtypmod
,
170 deparse_expr_cxt
*context
);
171 static void printRemotePlaceholder(Oid paramtype
, int32 paramtypmod
,
172 deparse_expr_cxt
*context
);
173 static void deparseSelectSql(List
*tlist
, bool is_subquery
, List
**retrieved_attrs
,
174 deparse_expr_cxt
*context
);
175 static void deparseLockingClause(deparse_expr_cxt
*context
);
176 static void appendOrderByClause(List
*pathkeys
, bool has_final_sort
,
177 deparse_expr_cxt
*context
);
178 static void appendLimitClause(deparse_expr_cxt
*context
);
179 static void appendConditions(List
*exprs
, deparse_expr_cxt
*context
);
180 static void deparseFromExprForRel(StringInfo buf
, PlannerInfo
*root
,
181 RelOptInfo
*foreignrel
, bool use_alias
,
182 Index ignore_rel
, List
**ignore_conds
,
184 static void deparseFromExpr(List
*quals
, deparse_expr_cxt
*context
);
185 static void deparseRangeTblRef(StringInfo buf
, PlannerInfo
*root
,
186 RelOptInfo
*foreignrel
, bool make_subquery
,
187 Index ignore_rel
, List
**ignore_conds
, List
**params_list
);
188 static void deparseAggref(Aggref
*node
, deparse_expr_cxt
*context
);
189 static void appendGroupByClause(List
*tlist
, deparse_expr_cxt
*context
);
190 static void appendOrderBySuffix(Oid sortop
, Oid sortcoltype
, bool nulls_first
,
191 deparse_expr_cxt
*context
);
192 static void appendAggOrderBy(List
*orderList
, List
*targetList
,
193 deparse_expr_cxt
*context
);
194 static void appendFunctionName(Oid funcid
, deparse_expr_cxt
*context
);
195 static Node
*deparseSortGroupClause(Index ref
, List
*tlist
, bool force_colno
,
196 deparse_expr_cxt
*context
);
201 static bool is_subquery_var(Var
*node
, RelOptInfo
*foreignrel
,
202 int *relno
, int *colno
);
203 static void get_relation_column_alias_ids(Var
*node
, RelOptInfo
*foreignrel
,
204 int *relno
, int *colno
);
208 * Examine each qual clause in input_conds, and classify them into two groups,
209 * which are returned as two lists:
210 * - remote_conds contains expressions that can be evaluated remotely
211 * - local_conds contains expressions that can't be evaluated remotely
214 classifyConditions(PlannerInfo
*root
,
225 foreach(lc
, input_conds
)
227 RestrictInfo
*ri
= lfirst_node(RestrictInfo
, lc
);
229 if (is_foreign_expr(root
, baserel
, ri
->clause
))
230 *remote_conds
= lappend(*remote_conds
, ri
);
232 *local_conds
= lappend(*local_conds
, ri
);
237 * Returns true if given expr is safe to evaluate on the foreign server.
240 is_foreign_expr(PlannerInfo
*root
,
244 foreign_glob_cxt glob_cxt
;
245 foreign_loc_cxt loc_cxt
;
246 PgFdwRelationInfo
*fpinfo
= (PgFdwRelationInfo
*) (baserel
->fdw_private
);
249 * Check that the expression consists of nodes that are safe to execute
252 glob_cxt
.root
= root
;
253 glob_cxt
.foreignrel
= baserel
;
256 * For an upper relation, use relids from its underneath scan relation,
257 * because the upperrel's own relids currently aren't set to anything
258 * meaningful by the core code. For other relation, use their own relids.
260 if (IS_UPPER_REL(baserel
))
261 glob_cxt
.relids
= fpinfo
->outerrel
->relids
;
263 glob_cxt
.relids
= baserel
->relids
;
264 loc_cxt
.collation
= InvalidOid
;
265 loc_cxt
.state
= FDW_COLLATE_NONE
;
266 if (!foreign_expr_walker((Node
*) expr
, &glob_cxt
, &loc_cxt
, NULL
))
270 * If the expression has a valid collation that does not arise from a
271 * foreign var, the expression can not be sent over.
273 if (loc_cxt
.state
== FDW_COLLATE_UNSAFE
)
277 * An expression which includes any mutable functions can't be sent over
278 * because its result is not stable. For example, sending now() remote
279 * side could cause confusion from clock offsets. Future versions might
280 * be able to make this choice with more granularity. (We check this last
281 * because it requires a lot of expensive catalog lookups.)
283 if (contain_mutable_functions((Node
*) expr
))
286 /* OK to evaluate on the remote server */
291 * Check if expression is safe to execute remotely, and return true if so.
293 * In addition, *outer_cxt is updated with collation information.
295 * case_arg_cxt is NULL if this subexpression is not inside a CASE-with-arg.
296 * Otherwise, it points to the collation info derived from the arg expression,
297 * which must be consulted by any CaseTestExpr.
299 * We must check that the expression contains only node types we can deparse,
300 * that all types/functions/operators are safe to send (they are "shippable"),
301 * and that all collations used in the expression derive from Vars of the
302 * foreign table. Because of the latter, the logic is pretty close to
303 * assign_collations_walker() in parse_collate.c, though we can assume here
304 * that the given expression is valid. Note function mutability is not
305 * currently considered here.
308 foreign_expr_walker(Node
*node
,
309 foreign_glob_cxt
*glob_cxt
,
310 foreign_loc_cxt
*outer_cxt
,
311 foreign_loc_cxt
*case_arg_cxt
)
313 bool check_type
= true;
314 PgFdwRelationInfo
*fpinfo
;
315 foreign_loc_cxt inner_cxt
;
317 FDWCollateState state
;
319 /* Need do nothing for empty subexpressions */
323 /* May need server info from baserel's fdw_private struct */
324 fpinfo
= (PgFdwRelationInfo
*) (glob_cxt
->foreignrel
->fdw_private
);
326 /* Set up inner_cxt for possible recursion to child nodes */
327 inner_cxt
.collation
= InvalidOid
;
328 inner_cxt
.state
= FDW_COLLATE_NONE
;
330 switch (nodeTag(node
))
334 Var
*var
= (Var
*) node
;
337 * If the Var is from the foreign table, we consider its
338 * collation (if any) safe to use. If it is from another
339 * table, we treat its collation the same way as we would a
340 * Param's collation, ie it's not safe for it to have a
341 * non-default collation.
343 if (bms_is_member(var
->varno
, glob_cxt
->relids
) &&
344 var
->varlevelsup
== 0)
346 /* Var belongs to foreign table */
349 * System columns other than ctid should not be sent to
350 * the remote, since we don't make any effort to ensure
351 * that local and remote values match (tableoid, in
352 * particular, almost certainly doesn't match).
354 if (var
->varattno
< 0 &&
355 var
->varattno
!= SelfItemPointerAttributeNumber
)
358 /* Else check the collation */
359 collation
= var
->varcollid
;
360 state
= OidIsValid(collation
) ? FDW_COLLATE_SAFE
: FDW_COLLATE_NONE
;
364 /* Var belongs to some other table */
365 collation
= var
->varcollid
;
366 if (collation
== InvalidOid
||
367 collation
== DEFAULT_COLLATION_OID
)
370 * It's noncollatable, or it's safe to combine with a
371 * collatable foreign Var, so set state to NONE.
373 state
= FDW_COLLATE_NONE
;
378 * Do not fail right away, since the Var might appear
379 * in a collation-insensitive context.
381 state
= FDW_COLLATE_UNSAFE
;
388 Const
*c
= (Const
*) node
;
391 * Constants of regproc and related types can't be shipped
392 * unless the referenced object is shippable. But NULL's ok.
393 * (See also the related code in dependency.c.)
397 switch (c
->consttype
)
400 case REGPROCEDUREOID
:
401 if (!is_shippable(DatumGetObjectId(c
->constvalue
),
402 ProcedureRelationId
, fpinfo
))
407 if (!is_shippable(DatumGetObjectId(c
->constvalue
),
408 OperatorRelationId
, fpinfo
))
412 if (!is_shippable(DatumGetObjectId(c
->constvalue
),
413 RelationRelationId
, fpinfo
))
417 if (!is_shippable(DatumGetObjectId(c
->constvalue
),
418 TypeRelationId
, fpinfo
))
421 case REGCOLLATIONOID
:
422 if (!is_shippable(DatumGetObjectId(c
->constvalue
),
423 CollationRelationId
, fpinfo
))
429 * For text search objects only, we weaken the
430 * normal shippability criterion to allow all OIDs
431 * below FirstNormalObjectId. Without this, none
432 * of the initdb-installed TS configurations would
433 * be shippable, which would be quite annoying.
435 if (DatumGetObjectId(c
->constvalue
) >= FirstNormalObjectId
&&
436 !is_shippable(DatumGetObjectId(c
->constvalue
),
437 TSConfigRelationId
, fpinfo
))
440 case REGDICTIONARYOID
:
441 if (DatumGetObjectId(c
->constvalue
) >= FirstNormalObjectId
&&
442 !is_shippable(DatumGetObjectId(c
->constvalue
),
443 TSDictionaryRelationId
, fpinfo
))
446 case REGNAMESPACEOID
:
447 if (!is_shippable(DatumGetObjectId(c
->constvalue
),
448 NamespaceRelationId
, fpinfo
))
452 if (!is_shippable(DatumGetObjectId(c
->constvalue
),
453 AuthIdRelationId
, fpinfo
))
460 * If the constant has nondefault collation, either it's of a
461 * non-builtin type, or it reflects folding of a CollateExpr.
462 * It's unsafe to send to the remote unless it's used in a
463 * non-collation-sensitive context.
465 collation
= c
->constcollid
;
466 if (collation
== InvalidOid
||
467 collation
== DEFAULT_COLLATION_OID
)
468 state
= FDW_COLLATE_NONE
;
470 state
= FDW_COLLATE_UNSAFE
;
475 Param
*p
= (Param
*) node
;
478 * If it's a MULTIEXPR Param, punt. We can't tell from here
479 * whether the referenced sublink/subplan contains any remote
480 * Vars; if it does, handling that is too complicated to
481 * consider supporting at present. Fortunately, MULTIEXPR
482 * Params are not reduced to plain PARAM_EXEC until the end of
483 * planning, so we can easily detect this case. (Normal
484 * PARAM_EXEC Params are safe to ship because their values
485 * come from somewhere else in the plan tree; but a MULTIEXPR
486 * references a sub-select elsewhere in the same targetlist,
487 * so we'd be on the hook to evaluate it somehow if we wanted
488 * to handle such cases as direct foreign updates.)
490 if (p
->paramkind
== PARAM_MULTIEXPR
)
494 * Collation rule is same as for Consts and non-foreign Vars.
496 collation
= p
->paramcollid
;
497 if (collation
== InvalidOid
||
498 collation
== DEFAULT_COLLATION_OID
)
499 state
= FDW_COLLATE_NONE
;
501 state
= FDW_COLLATE_UNSAFE
;
504 case T_SubscriptingRef
:
506 SubscriptingRef
*sr
= (SubscriptingRef
*) node
;
508 /* Assignment should not be in restrictions. */
509 if (sr
->refassgnexpr
!= NULL
)
513 * Recurse into the remaining subexpressions. The container
514 * subscripts will not affect collation of the SubscriptingRef
515 * result, so do those first and reset inner_cxt afterwards.
517 if (!foreign_expr_walker((Node
*) sr
->refupperindexpr
,
518 glob_cxt
, &inner_cxt
, case_arg_cxt
))
520 inner_cxt
.collation
= InvalidOid
;
521 inner_cxt
.state
= FDW_COLLATE_NONE
;
522 if (!foreign_expr_walker((Node
*) sr
->reflowerindexpr
,
523 glob_cxt
, &inner_cxt
, case_arg_cxt
))
525 inner_cxt
.collation
= InvalidOid
;
526 inner_cxt
.state
= FDW_COLLATE_NONE
;
527 if (!foreign_expr_walker((Node
*) sr
->refexpr
,
528 glob_cxt
, &inner_cxt
, case_arg_cxt
))
532 * Container subscripting typically yields same collation as
533 * refexpr's, but in case it doesn't, use same logic as for
536 collation
= sr
->refcollid
;
537 if (collation
== InvalidOid
)
538 state
= FDW_COLLATE_NONE
;
539 else if (inner_cxt
.state
== FDW_COLLATE_SAFE
&&
540 collation
== inner_cxt
.collation
)
541 state
= FDW_COLLATE_SAFE
;
542 else if (collation
== DEFAULT_COLLATION_OID
)
543 state
= FDW_COLLATE_NONE
;
545 state
= FDW_COLLATE_UNSAFE
;
550 FuncExpr
*fe
= (FuncExpr
*) node
;
553 * If function used by the expression is not shippable, it
554 * can't be sent to remote because it might have incompatible
555 * semantics on remote side.
557 if (!is_shippable(fe
->funcid
, ProcedureRelationId
, fpinfo
))
561 * Recurse to input subexpressions.
563 if (!foreign_expr_walker((Node
*) fe
->args
,
564 glob_cxt
, &inner_cxt
, case_arg_cxt
))
568 * If function's input collation is not derived from a foreign
569 * Var, it can't be sent to remote.
571 if (fe
->inputcollid
== InvalidOid
)
572 /* OK, inputs are all noncollatable */ ;
573 else if (inner_cxt
.state
!= FDW_COLLATE_SAFE
||
574 fe
->inputcollid
!= inner_cxt
.collation
)
578 * Detect whether node is introducing a collation not derived
579 * from a foreign Var. (If so, we just mark it unsafe for now
580 * rather than immediately returning false, since the parent
581 * node might not care.)
583 collation
= fe
->funccollid
;
584 if (collation
== InvalidOid
)
585 state
= FDW_COLLATE_NONE
;
586 else if (inner_cxt
.state
== FDW_COLLATE_SAFE
&&
587 collation
== inner_cxt
.collation
)
588 state
= FDW_COLLATE_SAFE
;
589 else if (collation
== DEFAULT_COLLATION_OID
)
590 state
= FDW_COLLATE_NONE
;
592 state
= FDW_COLLATE_UNSAFE
;
596 case T_DistinctExpr
: /* struct-equivalent to OpExpr */
598 OpExpr
*oe
= (OpExpr
*) node
;
601 * Similarly, only shippable operators can be sent to remote.
602 * (If the operator is shippable, we assume its underlying
605 if (!is_shippable(oe
->opno
, OperatorRelationId
, fpinfo
))
609 * Recurse to input subexpressions.
611 if (!foreign_expr_walker((Node
*) oe
->args
,
612 glob_cxt
, &inner_cxt
, case_arg_cxt
))
616 * If operator's input collation is not derived from a foreign
617 * Var, it can't be sent to remote.
619 if (oe
->inputcollid
== InvalidOid
)
620 /* OK, inputs are all noncollatable */ ;
621 else if (inner_cxt
.state
!= FDW_COLLATE_SAFE
||
622 oe
->inputcollid
!= inner_cxt
.collation
)
625 /* Result-collation handling is same as for functions */
626 collation
= oe
->opcollid
;
627 if (collation
== InvalidOid
)
628 state
= FDW_COLLATE_NONE
;
629 else if (inner_cxt
.state
== FDW_COLLATE_SAFE
&&
630 collation
== inner_cxt
.collation
)
631 state
= FDW_COLLATE_SAFE
;
632 else if (collation
== DEFAULT_COLLATION_OID
)
633 state
= FDW_COLLATE_NONE
;
635 state
= FDW_COLLATE_UNSAFE
;
638 case T_ScalarArrayOpExpr
:
640 ScalarArrayOpExpr
*oe
= (ScalarArrayOpExpr
*) node
;
643 * Again, only shippable operators can be sent to remote.
645 if (!is_shippable(oe
->opno
, OperatorRelationId
, fpinfo
))
649 * Recurse to input subexpressions.
651 if (!foreign_expr_walker((Node
*) oe
->args
,
652 glob_cxt
, &inner_cxt
, case_arg_cxt
))
656 * If operator's input collation is not derived from a foreign
657 * Var, it can't be sent to remote.
659 if (oe
->inputcollid
== InvalidOid
)
660 /* OK, inputs are all noncollatable */ ;
661 else if (inner_cxt
.state
!= FDW_COLLATE_SAFE
||
662 oe
->inputcollid
!= inner_cxt
.collation
)
665 /* Output is always boolean and so noncollatable. */
666 collation
= InvalidOid
;
667 state
= FDW_COLLATE_NONE
;
672 RelabelType
*r
= (RelabelType
*) node
;
675 * Recurse to input subexpression.
677 if (!foreign_expr_walker((Node
*) r
->arg
,
678 glob_cxt
, &inner_cxt
, case_arg_cxt
))
682 * RelabelType must not introduce a collation not derived from
683 * an input foreign Var (same logic as for a real function).
685 collation
= r
->resultcollid
;
686 if (collation
== InvalidOid
)
687 state
= FDW_COLLATE_NONE
;
688 else if (inner_cxt
.state
== FDW_COLLATE_SAFE
&&
689 collation
== inner_cxt
.collation
)
690 state
= FDW_COLLATE_SAFE
;
691 else if (collation
== DEFAULT_COLLATION_OID
)
692 state
= FDW_COLLATE_NONE
;
694 state
= FDW_COLLATE_UNSAFE
;
699 BoolExpr
*b
= (BoolExpr
*) node
;
702 * Recurse to input subexpressions.
704 if (!foreign_expr_walker((Node
*) b
->args
,
705 glob_cxt
, &inner_cxt
, case_arg_cxt
))
708 /* Output is always boolean and so noncollatable. */
709 collation
= InvalidOid
;
710 state
= FDW_COLLATE_NONE
;
715 NullTest
*nt
= (NullTest
*) node
;
718 * Recurse to input subexpressions.
720 if (!foreign_expr_walker((Node
*) nt
->arg
,
721 glob_cxt
, &inner_cxt
, case_arg_cxt
))
724 /* Output is always boolean and so noncollatable. */
725 collation
= InvalidOid
;
726 state
= FDW_COLLATE_NONE
;
731 CaseExpr
*ce
= (CaseExpr
*) node
;
732 foreign_loc_cxt arg_cxt
;
733 foreign_loc_cxt tmp_cxt
;
737 * Recurse to CASE's arg expression, if any. Its collation
738 * has to be saved aside for use while examining CaseTestExprs
739 * within the WHEN expressions.
741 arg_cxt
.collation
= InvalidOid
;
742 arg_cxt
.state
= FDW_COLLATE_NONE
;
745 if (!foreign_expr_walker((Node
*) ce
->arg
,
746 glob_cxt
, &arg_cxt
, case_arg_cxt
))
750 /* Examine the CaseWhen subexpressions. */
751 foreach(lc
, ce
->args
)
753 CaseWhen
*cw
= lfirst_node(CaseWhen
, lc
);
758 * In a CASE-with-arg, the parser should have produced
759 * WHEN clauses of the form "CaseTestExpr = RHS",
760 * possibly with an implicit coercion inserted above
761 * the CaseTestExpr. However in an expression that's
762 * been through the optimizer, the WHEN clause could
763 * be almost anything (since the equality operator
764 * could have been expanded into an inline function).
765 * In such cases forbid pushdown, because
766 * deparseCaseExpr can't handle it.
768 Node
*whenExpr
= (Node
*) cw
->expr
;
771 if (!IsA(whenExpr
, OpExpr
))
774 opArgs
= ((OpExpr
*) whenExpr
)->args
;
775 if (list_length(opArgs
) != 2 ||
776 !IsA(strip_implicit_coercions(linitial(opArgs
)),
782 * Recurse to WHEN expression, passing down the arg info.
783 * Its collation doesn't affect the result (really, it
784 * should be boolean and thus not have a collation).
786 tmp_cxt
.collation
= InvalidOid
;
787 tmp_cxt
.state
= FDW_COLLATE_NONE
;
788 if (!foreign_expr_walker((Node
*) cw
->expr
,
789 glob_cxt
, &tmp_cxt
, &arg_cxt
))
792 /* Recurse to THEN expression. */
793 if (!foreign_expr_walker((Node
*) cw
->result
,
794 glob_cxt
, &inner_cxt
, case_arg_cxt
))
798 /* Recurse to ELSE expression. */
799 if (!foreign_expr_walker((Node
*) ce
->defresult
,
800 glob_cxt
, &inner_cxt
, case_arg_cxt
))
804 * Detect whether node is introducing a collation not derived
805 * from a foreign Var. (If so, we just mark it unsafe for now
806 * rather than immediately returning false, since the parent
807 * node might not care.) This is the same as for function
808 * nodes, except that the input collation is derived from only
809 * the THEN and ELSE subexpressions.
811 collation
= ce
->casecollid
;
812 if (collation
== InvalidOid
)
813 state
= FDW_COLLATE_NONE
;
814 else if (inner_cxt
.state
== FDW_COLLATE_SAFE
&&
815 collation
== inner_cxt
.collation
)
816 state
= FDW_COLLATE_SAFE
;
817 else if (collation
== DEFAULT_COLLATION_OID
)
818 state
= FDW_COLLATE_NONE
;
820 state
= FDW_COLLATE_UNSAFE
;
825 CaseTestExpr
*c
= (CaseTestExpr
*) node
;
827 /* Punt if we seem not to be inside a CASE arg WHEN. */
832 * Otherwise, any nondefault collation attached to the
833 * CaseTestExpr node must be derived from foreign Var(s) in
836 collation
= c
->collation
;
837 if (collation
== InvalidOid
)
838 state
= FDW_COLLATE_NONE
;
839 else if (case_arg_cxt
->state
== FDW_COLLATE_SAFE
&&
840 collation
== case_arg_cxt
->collation
)
841 state
= FDW_COLLATE_SAFE
;
842 else if (collation
== DEFAULT_COLLATION_OID
)
843 state
= FDW_COLLATE_NONE
;
845 state
= FDW_COLLATE_UNSAFE
;
850 ArrayExpr
*a
= (ArrayExpr
*) node
;
853 * Recurse to input subexpressions.
855 if (!foreign_expr_walker((Node
*) a
->elements
,
856 glob_cxt
, &inner_cxt
, case_arg_cxt
))
860 * ArrayExpr must not introduce a collation not derived from
861 * an input foreign Var (same logic as for a function).
863 collation
= a
->array_collid
;
864 if (collation
== InvalidOid
)
865 state
= FDW_COLLATE_NONE
;
866 else if (inner_cxt
.state
== FDW_COLLATE_SAFE
&&
867 collation
== inner_cxt
.collation
)
868 state
= FDW_COLLATE_SAFE
;
869 else if (collation
== DEFAULT_COLLATION_OID
)
870 state
= FDW_COLLATE_NONE
;
872 state
= FDW_COLLATE_UNSAFE
;
877 List
*l
= (List
*) node
;
881 * Recurse to component subexpressions.
885 if (!foreign_expr_walker((Node
*) lfirst(lc
),
886 glob_cxt
, &inner_cxt
, case_arg_cxt
))
891 * When processing a list, collation state just bubbles up
892 * from the list elements.
894 collation
= inner_cxt
.collation
;
895 state
= inner_cxt
.state
;
897 /* Don't apply exprType() to the list. */
903 Aggref
*agg
= (Aggref
*) node
;
906 /* Not safe to pushdown when not in grouping context */
907 if (!IS_UPPER_REL(glob_cxt
->foreignrel
))
910 /* Only non-split aggregates are pushable. */
911 if (agg
->aggsplit
!= AGGSPLIT_SIMPLE
)
914 /* As usual, it must be shippable. */
915 if (!is_shippable(agg
->aggfnoid
, ProcedureRelationId
, fpinfo
))
919 * Recurse to input args. aggdirectargs, aggorder and
920 * aggdistinct are all present in args, so no need to check
921 * their shippability explicitly.
923 foreach(lc
, agg
->args
)
925 Node
*n
= (Node
*) lfirst(lc
);
927 /* If TargetEntry, extract the expression from it */
928 if (IsA(n
, TargetEntry
))
930 TargetEntry
*tle
= (TargetEntry
*) n
;
932 n
= (Node
*) tle
->expr
;
935 if (!foreign_expr_walker(n
,
936 glob_cxt
, &inner_cxt
, case_arg_cxt
))
941 * For aggorder elements, check whether the sort operator, if
942 * specified, is shippable or not.
946 foreach(lc
, agg
->aggorder
)
948 SortGroupClause
*srt
= (SortGroupClause
*) lfirst(lc
);
950 TypeCacheEntry
*typentry
;
953 tle
= get_sortgroupref_tle(srt
->tleSortGroupRef
,
955 sortcoltype
= exprType((Node
*) tle
->expr
);
956 typentry
= lookup_type_cache(sortcoltype
,
957 TYPECACHE_LT_OPR
| TYPECACHE_GT_OPR
);
958 /* Check shippability of non-default sort operator. */
959 if (srt
->sortop
!= typentry
->lt_opr
&&
960 srt
->sortop
!= typentry
->gt_opr
&&
961 !is_shippable(srt
->sortop
, OperatorRelationId
,
967 /* Check aggregate filter */
968 if (!foreign_expr_walker((Node
*) agg
->aggfilter
,
969 glob_cxt
, &inner_cxt
, case_arg_cxt
))
973 * If aggregate's input collation is not derived from a
974 * foreign Var, it can't be sent to remote.
976 if (agg
->inputcollid
== InvalidOid
)
977 /* OK, inputs are all noncollatable */ ;
978 else if (inner_cxt
.state
!= FDW_COLLATE_SAFE
||
979 agg
->inputcollid
!= inner_cxt
.collation
)
983 * Detect whether node is introducing a collation not derived
984 * from a foreign Var. (If so, we just mark it unsafe for now
985 * rather than immediately returning false, since the parent
986 * node might not care.)
988 collation
= agg
->aggcollid
;
989 if (collation
== InvalidOid
)
990 state
= FDW_COLLATE_NONE
;
991 else if (inner_cxt
.state
== FDW_COLLATE_SAFE
&&
992 collation
== inner_cxt
.collation
)
993 state
= FDW_COLLATE_SAFE
;
994 else if (collation
== DEFAULT_COLLATION_OID
)
995 state
= FDW_COLLATE_NONE
;
997 state
= FDW_COLLATE_UNSAFE
;
1003 * If it's anything else, assume it's unsafe. This list can be
1004 * expanded later, but don't forget to add deparse support below.
1010 * If result type of given expression is not shippable, it can't be sent
1011 * to remote because it might have incompatible semantics on remote side.
1013 if (check_type
&& !is_shippable(exprType(node
), TypeRelationId
, fpinfo
))
1017 * Now, merge my collation information into my parent's state.
1019 if (state
> outer_cxt
->state
)
1021 /* Override previous parent state */
1022 outer_cxt
->collation
= collation
;
1023 outer_cxt
->state
= state
;
1025 else if (state
== outer_cxt
->state
)
1027 /* Merge, or detect error if there's a collation conflict */
1030 case FDW_COLLATE_NONE
:
1031 /* Nothing + nothing is still nothing */
1033 case FDW_COLLATE_SAFE
:
1034 if (collation
!= outer_cxt
->collation
)
1037 * Non-default collation always beats default.
1039 if (outer_cxt
->collation
== DEFAULT_COLLATION_OID
)
1041 /* Override previous parent state */
1042 outer_cxt
->collation
= collation
;
1044 else if (collation
!= DEFAULT_COLLATION_OID
)
1047 * Conflict; show state as indeterminate. We don't
1048 * want to "return false" right away, since parent
1049 * node might not care about collation.
1051 outer_cxt
->state
= FDW_COLLATE_UNSAFE
;
1055 case FDW_COLLATE_UNSAFE
:
1056 /* We're still conflicted ... */
1066 * Returns true if given expr is something we'd have to send the value of
1067 * to the foreign server.
1069 * This should return true when the expression is a shippable node that
1070 * deparseExpr would add to context->params_list. Note that we don't care
1071 * if the expression *contains* such a node, only whether one appears at top
1072 * level. We need this to detect cases where setrefs.c would recognize a
1073 * false match between an fdw_exprs item (which came from the params_list)
1074 * and an entry in fdw_scan_tlist (which we're considering putting the given
1078 is_foreign_param(PlannerInfo
*root
,
1079 RelOptInfo
*baserel
,
1085 switch (nodeTag(expr
))
1089 /* It would have to be sent unless it's a foreign Var */
1090 Var
*var
= (Var
*) expr
;
1091 PgFdwRelationInfo
*fpinfo
= (PgFdwRelationInfo
*) (baserel
->fdw_private
);
1094 if (IS_UPPER_REL(baserel
))
1095 relids
= fpinfo
->outerrel
->relids
;
1097 relids
= baserel
->relids
;
1099 if (bms_is_member(var
->varno
, relids
) && var
->varlevelsup
== 0)
1100 return false; /* foreign Var, so not a param */
1102 return true; /* it'd have to be a param */
1106 /* Params always have to be sent to the foreign server */
1115 * Returns true if it's safe to push down the sort expression described by
1116 * 'pathkey' to the foreign server.
1119 is_foreign_pathkey(PlannerInfo
*root
,
1120 RelOptInfo
*baserel
,
1123 EquivalenceClass
*pathkey_ec
= pathkey
->pk_eclass
;
1124 PgFdwRelationInfo
*fpinfo
= (PgFdwRelationInfo
*) baserel
->fdw_private
;
1127 * is_foreign_expr would detect volatile expressions as well, but checking
1128 * ec_has_volatile here saves some cycles.
1130 if (pathkey_ec
->ec_has_volatile
)
1133 /* can't push down the sort if the pathkey's opfamily is not shippable */
1134 if (!is_shippable(pathkey
->pk_opfamily
, OperatorFamilyRelationId
, fpinfo
))
1137 /* can push if a suitable EC member exists */
1138 return (find_em_for_rel(root
, pathkey_ec
, baserel
) != NULL
);
1142 * Convert type OID + typmod info into a type name we can ship to the remote
1143 * server. Someplace else had better have verified that this type name is
1144 * expected to be known on the remote end.
1146 * This is almost just format_type_with_typemod(), except that if left to its
1147 * own devices, that function will make schema-qualification decisions based
1148 * on the local search_path, which is wrong. We must schema-qualify all
1149 * type names that are not in pg_catalog. We assume here that built-in types
1150 * are all in pg_catalog and need not be qualified; otherwise, qualify.
1153 deparse_type_name(Oid type_oid
, int32 typemod
)
1155 bits16 flags
= FORMAT_TYPE_TYPEMOD_GIVEN
;
1157 if (!is_builtin(type_oid
))
1158 flags
|= FORMAT_TYPE_FORCE_QUALIFY
;
1160 return format_type_extended(type_oid
, typemod
, flags
);
1164 * Build the targetlist for given relation to be deparsed as SELECT clause.
1166 * The output targetlist contains the columns that need to be fetched from the
1167 * foreign server for the given relation. If foreignrel is an upper relation,
1168 * then the output targetlist can also contain expressions to be evaluated on
1172 build_tlist_to_deparse(RelOptInfo
*foreignrel
)
1175 PgFdwRelationInfo
*fpinfo
= (PgFdwRelationInfo
*) foreignrel
->fdw_private
;
1179 * For an upper relation, we have already built the target list while
1180 * checking shippability, so just return that.
1182 if (IS_UPPER_REL(foreignrel
))
1183 return fpinfo
->grouped_tlist
;
1186 * We require columns specified in foreignrel->reltarget->exprs and those
1187 * required for evaluating the local conditions.
1189 tlist
= add_to_flat_tlist(tlist
,
1190 pull_var_clause((Node
*) foreignrel
->reltarget
->exprs
,
1191 PVC_RECURSE_PLACEHOLDERS
));
1192 foreach(lc
, fpinfo
->local_conds
)
1194 RestrictInfo
*rinfo
= lfirst_node(RestrictInfo
, lc
);
1196 tlist
= add_to_flat_tlist(tlist
,
1197 pull_var_clause((Node
*) rinfo
->clause
,
1198 PVC_RECURSE_PLACEHOLDERS
));
1205 * Deparse SELECT statement for given relation into buf.
1207 * tlist contains the list of desired columns to be fetched from foreign server.
1208 * For a base relation fpinfo->attrs_used is used to construct SELECT clause,
1209 * hence the tlist is ignored for a base relation.
1211 * remote_conds is the list of conditions to be deparsed into the WHERE clause
1212 * (or, in the case of upper relations, into the HAVING clause).
1214 * If params_list is not NULL, it receives a list of Params and other-relation
1215 * Vars used in the clauses; these values must be transmitted to the remote
1216 * server as parameter values.
1218 * If params_list is NULL, we're generating the query for EXPLAIN purposes,
1219 * so Params and other-relation Vars should be replaced by dummy values.
1221 * pathkeys is the list of pathkeys to order the result by.
1223 * is_subquery is the flag to indicate whether to deparse the specified
1224 * relation as a subquery.
1226 * List of columns selected is returned in retrieved_attrs.
1229 deparseSelectStmtForRel(StringInfo buf
, PlannerInfo
*root
, RelOptInfo
*rel
,
1230 List
*tlist
, List
*remote_conds
, List
*pathkeys
,
1231 bool has_final_sort
, bool has_limit
, bool is_subquery
,
1232 List
**retrieved_attrs
, List
**params_list
)
1234 deparse_expr_cxt context
;
1235 PgFdwRelationInfo
*fpinfo
= (PgFdwRelationInfo
*) rel
->fdw_private
;
1239 * We handle relations for foreign tables, joins between those and upper
1242 Assert(IS_JOIN_REL(rel
) || IS_SIMPLE_REL(rel
) || IS_UPPER_REL(rel
));
1244 /* Fill portions of context common to upper, join and base relation */
1246 context
.root
= root
;
1247 context
.foreignrel
= rel
;
1248 context
.scanrel
= IS_UPPER_REL(rel
) ? fpinfo
->outerrel
: rel
;
1249 context
.params_list
= params_list
;
1251 /* Construct SELECT clause */
1252 deparseSelectSql(tlist
, is_subquery
, retrieved_attrs
, &context
);
1255 * For upper relations, the WHERE clause is built from the remote
1256 * conditions of the underlying scan relation; otherwise, we can use the
1257 * supplied list of remote conditions directly.
1259 if (IS_UPPER_REL(rel
))
1261 PgFdwRelationInfo
*ofpinfo
;
1263 ofpinfo
= (PgFdwRelationInfo
*) fpinfo
->outerrel
->fdw_private
;
1264 quals
= ofpinfo
->remote_conds
;
1267 quals
= remote_conds
;
1269 /* Construct FROM and WHERE clauses */
1270 deparseFromExpr(quals
, &context
);
1272 if (IS_UPPER_REL(rel
))
1274 /* Append GROUP BY clause */
1275 appendGroupByClause(tlist
, &context
);
1277 /* Append HAVING clause */
1280 appendStringInfoString(buf
, " HAVING ");
1281 appendConditions(remote_conds
, &context
);
1285 /* Add ORDER BY clause if we found any useful pathkeys */
1287 appendOrderByClause(pathkeys
, has_final_sort
, &context
);
1289 /* Add LIMIT clause if necessary */
1291 appendLimitClause(&context
);
1293 /* Add any necessary FOR UPDATE/SHARE. */
1294 deparseLockingClause(&context
);
1298 * Construct a simple SELECT statement that retrieves desired columns
1299 * of the specified foreign table, and append it to "buf". The output
1300 * contains just "SELECT ... ".
1302 * We also create an integer List of the columns being retrieved, which is
1303 * returned to *retrieved_attrs, unless we deparse the specified relation
1306 * tlist is the list of desired columns. is_subquery is the flag to
1307 * indicate whether to deparse the specified relation as a subquery.
1308 * Read prologue of deparseSelectStmtForRel() for details.
1311 deparseSelectSql(List
*tlist
, bool is_subquery
, List
**retrieved_attrs
,
1312 deparse_expr_cxt
*context
)
1314 StringInfo buf
= context
->buf
;
1315 RelOptInfo
*foreignrel
= context
->foreignrel
;
1316 PlannerInfo
*root
= context
->root
;
1317 PgFdwRelationInfo
*fpinfo
= (PgFdwRelationInfo
*) foreignrel
->fdw_private
;
1320 * Construct SELECT list
1322 appendStringInfoString(buf
, "SELECT ");
1327 * For a relation that is deparsed as a subquery, emit expressions
1328 * specified in the relation's reltarget. Note that since this is for
1329 * the subquery, no need to care about *retrieved_attrs.
1331 deparseSubqueryTargetList(context
);
1333 else if (IS_JOIN_REL(foreignrel
) || IS_UPPER_REL(foreignrel
))
1336 * For a join or upper relation the input tlist gives the list of
1337 * columns required to be fetched from the foreign server.
1339 deparseExplicitTargetList(tlist
, false, retrieved_attrs
, context
);
1344 * For a base relation fpinfo->attrs_used gives the list of columns
1345 * required to be fetched from the foreign server.
1347 RangeTblEntry
*rte
= planner_rt_fetch(foreignrel
->relid
, root
);
1350 * Core code already has some lock on each rel being planned, so we
1351 * can use NoLock here.
1353 Relation rel
= table_open(rte
->relid
, NoLock
);
1355 deparseTargetList(buf
, rte
, foreignrel
->relid
, rel
, false,
1356 fpinfo
->attrs_used
, false, retrieved_attrs
);
1357 table_close(rel
, NoLock
);
1362 * Construct a FROM clause and, if needed, a WHERE clause, and append those to
1365 * quals is the list of clauses to be included in the WHERE clause.
1366 * (These may or may not include RestrictInfo decoration.)
1369 deparseFromExpr(List
*quals
, deparse_expr_cxt
*context
)
1371 StringInfo buf
= context
->buf
;
1372 RelOptInfo
*scanrel
= context
->scanrel
;
1374 /* For upper relations, scanrel must be either a joinrel or a baserel */
1375 Assert(!IS_UPPER_REL(context
->foreignrel
) ||
1376 IS_JOIN_REL(scanrel
) || IS_SIMPLE_REL(scanrel
));
1378 /* Construct FROM clause */
1379 appendStringInfoString(buf
, " FROM ");
1380 deparseFromExprForRel(buf
, context
->root
, scanrel
,
1381 (bms_membership(scanrel
->relids
) == BMS_MULTIPLE
),
1382 (Index
) 0, NULL
, context
->params_list
);
1384 /* Construct WHERE clause */
1387 appendStringInfoString(buf
, " WHERE ");
1388 appendConditions(quals
, context
);
1393 * Emit a target list that retrieves the columns specified in attrs_used.
1394 * This is used for both SELECT and RETURNING targetlists; the is_returning
1395 * parameter is true only for a RETURNING targetlist.
1397 * The tlist text is appended to buf, and we also create an integer List
1398 * of the columns being retrieved, which is returned to *retrieved_attrs.
1400 * If qualify_col is true, add relation alias before the column name.
1403 deparseTargetList(StringInfo buf
,
1408 Bitmapset
*attrs_used
,
1410 List
**retrieved_attrs
)
1412 TupleDesc tupdesc
= RelationGetDescr(rel
);
1417 *retrieved_attrs
= NIL
;
1419 /* If there's a whole-row reference, we'll need all the columns. */
1420 have_wholerow
= bms_is_member(0 - FirstLowInvalidHeapAttributeNumber
,
1424 for (i
= 1; i
<= tupdesc
->natts
; i
++)
1426 Form_pg_attribute attr
= TupleDescAttr(tupdesc
, i
- 1);
1428 /* Ignore dropped attributes. */
1429 if (attr
->attisdropped
)
1432 if (have_wholerow
||
1433 bms_is_member(i
- FirstLowInvalidHeapAttributeNumber
,
1437 appendStringInfoString(buf
, ", ");
1438 else if (is_returning
)
1439 appendStringInfoString(buf
, " RETURNING ");
1442 deparseColumnRef(buf
, rtindex
, i
, rte
, qualify_col
);
1444 *retrieved_attrs
= lappend_int(*retrieved_attrs
, i
);
1449 * Add ctid if needed. We currently don't support retrieving any other
1452 if (bms_is_member(SelfItemPointerAttributeNumber
- FirstLowInvalidHeapAttributeNumber
,
1456 appendStringInfoString(buf
, ", ");
1457 else if (is_returning
)
1458 appendStringInfoString(buf
, " RETURNING ");
1462 ADD_REL_QUALIFIER(buf
, rtindex
);
1463 appendStringInfoString(buf
, "ctid");
1465 *retrieved_attrs
= lappend_int(*retrieved_attrs
,
1466 SelfItemPointerAttributeNumber
);
1469 /* Don't generate bad syntax if no undropped columns */
1470 if (first
&& !is_returning
)
1471 appendStringInfoString(buf
, "NULL");
1475 * Deparse the appropriate locking clause (FOR UPDATE or FOR SHARE) for a
1476 * given relation (context->scanrel).
1479 deparseLockingClause(deparse_expr_cxt
*context
)
1481 StringInfo buf
= context
->buf
;
1482 PlannerInfo
*root
= context
->root
;
1483 RelOptInfo
*rel
= context
->scanrel
;
1484 PgFdwRelationInfo
*fpinfo
= (PgFdwRelationInfo
*) rel
->fdw_private
;
1487 while ((relid
= bms_next_member(rel
->relids
, relid
)) >= 0)
1490 * Ignore relation if it appears in a lower subquery. Locking clause
1491 * for such a relation is included in the subquery if necessary.
1493 if (bms_is_member(relid
, fpinfo
->lower_subquery_rels
))
1497 * Add FOR UPDATE/SHARE if appropriate. We apply locking during the
1498 * initial row fetch, rather than later on as is done for local
1499 * tables. The extra roundtrips involved in trying to duplicate the
1500 * local semantics exactly don't seem worthwhile (see also comments
1503 * Note: because we actually run the query as a cursor, this assumes
1504 * that DECLARE CURSOR ... FOR UPDATE is supported, which it isn't
1507 if (bms_is_member(relid
, root
->all_result_relids
) &&
1508 (root
->parse
->commandType
== CMD_UPDATE
||
1509 root
->parse
->commandType
== CMD_DELETE
))
1511 /* Relation is UPDATE/DELETE target, so use FOR UPDATE */
1512 appendStringInfoString(buf
, " FOR UPDATE");
1514 /* Add the relation alias if we are here for a join relation */
1515 if (IS_JOIN_REL(rel
))
1516 appendStringInfo(buf
, " OF %s%d", REL_ALIAS_PREFIX
, relid
);
1520 PlanRowMark
*rc
= get_plan_rowmark(root
->rowMarks
, relid
);
1525 * Relation is specified as a FOR UPDATE/SHARE target, so
1526 * handle that. (But we could also see LCS_NONE, meaning this
1527 * isn't a target relation after all.)
1529 * For now, just ignore any [NO] KEY specification, since (a)
1530 * it's not clear what that means for a remote table that we
1531 * don't have complete information about, and (b) it wouldn't
1532 * work anyway on older remote servers. Likewise, we don't
1533 * worry about NOWAIT.
1535 switch (rc
->strength
)
1538 /* No locking needed */
1540 case LCS_FORKEYSHARE
:
1542 appendStringInfoString(buf
, " FOR SHARE");
1544 case LCS_FORNOKEYUPDATE
:
1546 appendStringInfoString(buf
, " FOR UPDATE");
1550 /* Add the relation alias if we are here for a join relation */
1551 if (bms_membership(rel
->relids
) == BMS_MULTIPLE
&&
1552 rc
->strength
!= LCS_NONE
)
1553 appendStringInfo(buf
, " OF %s%d", REL_ALIAS_PREFIX
, relid
);
1560 * Deparse conditions from the provided list and append them to buf.
1562 * The conditions in the list are assumed to be ANDed. This function is used to
1563 * deparse WHERE clauses, JOIN .. ON clauses and HAVING clauses.
1565 * Depending on the caller, the list elements might be either RestrictInfos
1569 appendConditions(List
*exprs
, deparse_expr_cxt
*context
)
1573 bool is_first
= true;
1574 StringInfo buf
= context
->buf
;
1576 /* Make sure any constants in the exprs are printed portably */
1577 nestlevel
= set_transmission_modes();
1581 Expr
*expr
= (Expr
*) lfirst(lc
);
1583 /* Extract clause from RestrictInfo, if required */
1584 if (IsA(expr
, RestrictInfo
))
1585 expr
= ((RestrictInfo
*) expr
)->clause
;
1587 /* Connect expressions with "AND" and parenthesize each condition. */
1589 appendStringInfoString(buf
, " AND ");
1591 appendStringInfoChar(buf
, '(');
1592 deparseExpr(expr
, context
);
1593 appendStringInfoChar(buf
, ')');
1598 reset_transmission_modes(nestlevel
);
1601 /* Output join name for given join type */
1603 get_jointype_name(JoinType jointype
)
1620 /* Shouldn't come here, but protect from buggy code. */
1621 elog(ERROR
, "unsupported join type %d", jointype
);
1624 /* Keep compiler happy */
1629 * Deparse given targetlist and append it to context->buf.
1631 * tlist is list of TargetEntry's which in turn contain Var nodes.
1633 * retrieved_attrs is the list of continuously increasing integers starting
1634 * from 1. It has same number of entries as tlist.
1636 * This is used for both SELECT and RETURNING targetlists; the is_returning
1637 * parameter is true only for a RETURNING targetlist.
1640 deparseExplicitTargetList(List
*tlist
,
1642 List
**retrieved_attrs
,
1643 deparse_expr_cxt
*context
)
1646 StringInfo buf
= context
->buf
;
1649 *retrieved_attrs
= NIL
;
1653 TargetEntry
*tle
= lfirst_node(TargetEntry
, lc
);
1656 appendStringInfoString(buf
, ", ");
1657 else if (is_returning
)
1658 appendStringInfoString(buf
, " RETURNING ");
1660 deparseExpr((Expr
*) tle
->expr
, context
);
1662 *retrieved_attrs
= lappend_int(*retrieved_attrs
, i
+ 1);
1666 if (i
== 0 && !is_returning
)
1667 appendStringInfoString(buf
, "NULL");
1671 * Emit expressions specified in the given relation's reltarget.
1673 * This is used for deparsing the given relation as a subquery.
1676 deparseSubqueryTargetList(deparse_expr_cxt
*context
)
1678 StringInfo buf
= context
->buf
;
1679 RelOptInfo
*foreignrel
= context
->foreignrel
;
1683 /* Should only be called in these cases. */
1684 Assert(IS_SIMPLE_REL(foreignrel
) || IS_JOIN_REL(foreignrel
));
1687 foreach(lc
, foreignrel
->reltarget
->exprs
)
1689 Node
*node
= (Node
*) lfirst(lc
);
1692 appendStringInfoString(buf
, ", ");
1695 deparseExpr((Expr
*) node
, context
);
1698 /* Don't generate bad syntax if no expressions */
1700 appendStringInfoString(buf
, "NULL");
1704 * Construct FROM clause for given relation
1706 * The function constructs ... JOIN ... ON ... for join relation. For a base
1707 * relation it just returns schema-qualified tablename, with the appropriate
1708 * alias if so requested.
1710 * 'ignore_rel' is either zero or the RT index of a target relation. In the
1711 * latter case the function constructs FROM clause of UPDATE or USING clause
1712 * of DELETE; it deparses the join relation as if the relation never contained
1713 * the target relation, and creates a List of conditions to be deparsed into
1714 * the top-level WHERE clause, which is returned to *ignore_conds.
1717 deparseFromExprForRel(StringInfo buf
, PlannerInfo
*root
, RelOptInfo
*foreignrel
,
1718 bool use_alias
, Index ignore_rel
, List
**ignore_conds
,
1721 PgFdwRelationInfo
*fpinfo
= (PgFdwRelationInfo
*) foreignrel
->fdw_private
;
1723 if (IS_JOIN_REL(foreignrel
))
1725 StringInfoData join_sql_o
;
1726 StringInfoData join_sql_i
;
1727 RelOptInfo
*outerrel
= fpinfo
->outerrel
;
1728 RelOptInfo
*innerrel
= fpinfo
->innerrel
;
1729 bool outerrel_is_target
= false;
1730 bool innerrel_is_target
= false;
1732 if (ignore_rel
> 0 && bms_is_member(ignore_rel
, foreignrel
->relids
))
1735 * If this is an inner join, add joinclauses to *ignore_conds and
1736 * set it to empty so that those can be deparsed into the WHERE
1737 * clause. Note that since the target relation can never be
1738 * within the nullable side of an outer join, those could safely
1739 * be pulled up into the WHERE clause (see foreign_join_ok()).
1740 * Note also that since the target relation is only inner-joined
1741 * to any other relation in the query, all conditions in the join
1742 * tree mentioning the target relation could be deparsed into the
1743 * WHERE clause by doing this recursively.
1745 if (fpinfo
->jointype
== JOIN_INNER
)
1747 *ignore_conds
= list_concat(*ignore_conds
,
1748 fpinfo
->joinclauses
);
1749 fpinfo
->joinclauses
= NIL
;
1753 * Check if either of the input relations is the target relation.
1755 if (outerrel
->relid
== ignore_rel
)
1756 outerrel_is_target
= true;
1757 else if (innerrel
->relid
== ignore_rel
)
1758 innerrel_is_target
= true;
1761 /* Deparse outer relation if not the target relation. */
1762 if (!outerrel_is_target
)
1764 initStringInfo(&join_sql_o
);
1765 deparseRangeTblRef(&join_sql_o
, root
, outerrel
,
1766 fpinfo
->make_outerrel_subquery
,
1767 ignore_rel
, ignore_conds
, params_list
);
1770 * If inner relation is the target relation, skip deparsing it.
1771 * Note that since the join of the target relation with any other
1772 * relation in the query is an inner join and can never be within
1773 * the nullable side of an outer join, the join could be
1774 * interchanged with higher-level joins (cf. identity 1 on outer
1775 * join reordering shown in src/backend/optimizer/README), which
1776 * means it's safe to skip the target-relation deparsing here.
1778 if (innerrel_is_target
)
1780 Assert(fpinfo
->jointype
== JOIN_INNER
);
1781 Assert(fpinfo
->joinclauses
== NIL
);
1782 appendBinaryStringInfo(buf
, join_sql_o
.data
, join_sql_o
.len
);
1787 /* Deparse inner relation if not the target relation. */
1788 if (!innerrel_is_target
)
1790 initStringInfo(&join_sql_i
);
1791 deparseRangeTblRef(&join_sql_i
, root
, innerrel
,
1792 fpinfo
->make_innerrel_subquery
,
1793 ignore_rel
, ignore_conds
, params_list
);
1796 * If outer relation is the target relation, skip deparsing it.
1797 * See the above note about safety.
1799 if (outerrel_is_target
)
1801 Assert(fpinfo
->jointype
== JOIN_INNER
);
1802 Assert(fpinfo
->joinclauses
== NIL
);
1803 appendBinaryStringInfo(buf
, join_sql_i
.data
, join_sql_i
.len
);
1808 /* Neither of the relations is the target relation. */
1809 Assert(!outerrel_is_target
&& !innerrel_is_target
);
1812 * For a join relation FROM clause entry is deparsed as
1814 * ((outer relation) <join type> (inner relation) ON (joinclauses))
1816 appendStringInfo(buf
, "(%s %s JOIN %s ON ", join_sql_o
.data
,
1817 get_jointype_name(fpinfo
->jointype
), join_sql_i
.data
);
1819 /* Append join clause; (TRUE) if no join clause */
1820 if (fpinfo
->joinclauses
)
1822 deparse_expr_cxt context
;
1825 context
.foreignrel
= foreignrel
;
1826 context
.scanrel
= foreignrel
;
1827 context
.root
= root
;
1828 context
.params_list
= params_list
;
1830 appendStringInfoChar(buf
, '(');
1831 appendConditions(fpinfo
->joinclauses
, &context
);
1832 appendStringInfoChar(buf
, ')');
1835 appendStringInfoString(buf
, "(TRUE)");
1837 /* End the FROM clause entry. */
1838 appendStringInfoChar(buf
, ')');
1842 RangeTblEntry
*rte
= planner_rt_fetch(foreignrel
->relid
, root
);
1845 * Core code already has some lock on each rel being planned, so we
1846 * can use NoLock here.
1848 Relation rel
= table_open(rte
->relid
, NoLock
);
1850 deparseRelation(buf
, rel
);
1853 * Add a unique alias to avoid any conflict in relation names due to
1854 * pulled up subqueries in the query being built for a pushed down
1858 appendStringInfo(buf
, " %s%d", REL_ALIAS_PREFIX
, foreignrel
->relid
);
1860 table_close(rel
, NoLock
);
1865 * Append FROM clause entry for the given relation into buf.
1868 deparseRangeTblRef(StringInfo buf
, PlannerInfo
*root
, RelOptInfo
*foreignrel
,
1869 bool make_subquery
, Index ignore_rel
, List
**ignore_conds
,
1872 PgFdwRelationInfo
*fpinfo
= (PgFdwRelationInfo
*) foreignrel
->fdw_private
;
1874 /* Should only be called in these cases. */
1875 Assert(IS_SIMPLE_REL(foreignrel
) || IS_JOIN_REL(foreignrel
));
1877 Assert(fpinfo
->local_conds
== NIL
);
1879 /* If make_subquery is true, deparse the relation as a subquery. */
1882 List
*retrieved_attrs
;
1886 * The given relation shouldn't contain the target relation, because
1887 * this should only happen for input relations for a full join, and
1888 * such relations can never contain an UPDATE/DELETE target.
1890 Assert(ignore_rel
== 0 ||
1891 !bms_is_member(ignore_rel
, foreignrel
->relids
));
1893 /* Deparse the subquery representing the relation. */
1894 appendStringInfoChar(buf
, '(');
1895 deparseSelectStmtForRel(buf
, root
, foreignrel
, NIL
,
1896 fpinfo
->remote_conds
, NIL
,
1898 &retrieved_attrs
, params_list
);
1899 appendStringInfoChar(buf
, ')');
1901 /* Append the relation alias. */
1902 appendStringInfo(buf
, " %s%d", SUBQUERY_REL_ALIAS_PREFIX
,
1903 fpinfo
->relation_index
);
1906 * Append the column aliases if needed. Note that the subquery emits
1907 * expressions specified in the relation's reltarget (see
1908 * deparseSubqueryTargetList).
1910 ncols
= list_length(foreignrel
->reltarget
->exprs
);
1915 appendStringInfoChar(buf
, '(');
1916 for (i
= 1; i
<= ncols
; i
++)
1919 appendStringInfoString(buf
, ", ");
1921 appendStringInfo(buf
, "%s%d", SUBQUERY_COL_ALIAS_PREFIX
, i
);
1923 appendStringInfoChar(buf
, ')');
1927 deparseFromExprForRel(buf
, root
, foreignrel
, true, ignore_rel
,
1928 ignore_conds
, params_list
);
1932 * deparse remote INSERT statement
1934 * The statement text is appended to buf, and we also create an integer List
1935 * of the columns being retrieved by WITH CHECK OPTION or RETURNING (if any),
1936 * which is returned to *retrieved_attrs.
1938 * This also stores end position of the VALUES clause, so that we can rebuild
1939 * an INSERT for a batch of rows later.
1942 deparseInsertSql(StringInfo buf
, RangeTblEntry
*rte
,
1943 Index rtindex
, Relation rel
,
1944 List
*targetAttrs
, bool doNothing
,
1945 List
*withCheckOptionList
, List
*returningList
,
1946 List
**retrieved_attrs
, int *values_end_len
)
1948 TupleDesc tupdesc
= RelationGetDescr(rel
);
1953 appendStringInfoString(buf
, "INSERT INTO ");
1954 deparseRelation(buf
, rel
);
1958 appendStringInfoChar(buf
, '(');
1961 foreach(lc
, targetAttrs
)
1963 int attnum
= lfirst_int(lc
);
1966 appendStringInfoString(buf
, ", ");
1969 deparseColumnRef(buf
, rtindex
, attnum
, rte
, false);
1972 appendStringInfoString(buf
, ") VALUES (");
1976 foreach(lc
, targetAttrs
)
1978 int attnum
= lfirst_int(lc
);
1979 Form_pg_attribute attr
= TupleDescAttr(tupdesc
, attnum
- 1);
1982 appendStringInfoString(buf
, ", ");
1985 if (attr
->attgenerated
)
1986 appendStringInfoString(buf
, "DEFAULT");
1989 appendStringInfo(buf
, "$%d", pindex
);
1994 appendStringInfoChar(buf
, ')');
1997 appendStringInfoString(buf
, " DEFAULT VALUES");
1998 *values_end_len
= buf
->len
;
2001 appendStringInfoString(buf
, " ON CONFLICT DO NOTHING");
2003 deparseReturningList(buf
, rte
, rtindex
, rel
,
2004 rel
->trigdesc
&& rel
->trigdesc
->trig_insert_after_row
,
2005 withCheckOptionList
, returningList
, retrieved_attrs
);
2009 * rebuild remote INSERT statement
2011 * Provided a number of rows in a batch, builds INSERT statement with the
2012 * right number of parameters.
2015 rebuildInsertSql(StringInfo buf
, Relation rel
,
2016 char *orig_query
, List
*target_attrs
,
2017 int values_end_len
, int num_params
,
2020 TupleDesc tupdesc
= RelationGetDescr(rel
);
2026 /* Make sure the values_end_len is sensible */
2027 Assert((values_end_len
> 0) && (values_end_len
<= strlen(orig_query
)));
2029 /* Copy up to the end of the first record from the original query */
2030 appendBinaryStringInfo(buf
, orig_query
, values_end_len
);
2033 * Add records to VALUES clause (we already have parameters for the first
2034 * row, so start at the right offset).
2036 pindex
= num_params
+ 1;
2037 for (i
= 0; i
< num_rows
; i
++)
2039 appendStringInfoString(buf
, ", (");
2042 foreach(lc
, target_attrs
)
2044 int attnum
= lfirst_int(lc
);
2045 Form_pg_attribute attr
= TupleDescAttr(tupdesc
, attnum
- 1);
2048 appendStringInfoString(buf
, ", ");
2051 if (attr
->attgenerated
)
2052 appendStringInfoString(buf
, "DEFAULT");
2055 appendStringInfo(buf
, "$%d", pindex
);
2060 appendStringInfoChar(buf
, ')');
2063 /* Copy stuff after VALUES clause from the original query */
2064 appendStringInfoString(buf
, orig_query
+ values_end_len
);
2068 * deparse remote UPDATE statement
2070 * The statement text is appended to buf, and we also create an integer List
2071 * of the columns being retrieved by WITH CHECK OPTION or RETURNING (if any),
2072 * which is returned to *retrieved_attrs.
2075 deparseUpdateSql(StringInfo buf
, RangeTblEntry
*rte
,
2076 Index rtindex
, Relation rel
,
2078 List
*withCheckOptionList
, List
*returningList
,
2079 List
**retrieved_attrs
)
2081 TupleDesc tupdesc
= RelationGetDescr(rel
);
2086 appendStringInfoString(buf
, "UPDATE ");
2087 deparseRelation(buf
, rel
);
2088 appendStringInfoString(buf
, " SET ");
2090 pindex
= 2; /* ctid is always the first param */
2092 foreach(lc
, targetAttrs
)
2094 int attnum
= lfirst_int(lc
);
2095 Form_pg_attribute attr
= TupleDescAttr(tupdesc
, attnum
- 1);
2098 appendStringInfoString(buf
, ", ");
2101 deparseColumnRef(buf
, rtindex
, attnum
, rte
, false);
2102 if (attr
->attgenerated
)
2103 appendStringInfoString(buf
, " = DEFAULT");
2106 appendStringInfo(buf
, " = $%d", pindex
);
2110 appendStringInfoString(buf
, " WHERE ctid = $1");
2112 deparseReturningList(buf
, rte
, rtindex
, rel
,
2113 rel
->trigdesc
&& rel
->trigdesc
->trig_update_after_row
,
2114 withCheckOptionList
, returningList
, retrieved_attrs
);
2118 * deparse remote UPDATE statement
2120 * 'buf' is the output buffer to append the statement to
2121 * 'rtindex' is the RT index of the associated target relation
2122 * 'rel' is the relation descriptor for the target relation
2123 * 'foreignrel' is the RelOptInfo for the target relation or the join relation
2124 * containing all base relations in the query
2125 * 'targetlist' is the tlist of the underlying foreign-scan plan node
2126 * (note that this only contains new-value expressions and junk attrs)
2127 * 'targetAttrs' is the target columns of the UPDATE
2128 * 'remote_conds' is the qual clauses that must be evaluated remotely
2129 * '*params_list' is an output list of exprs that will become remote Params
2130 * 'returningList' is the RETURNING targetlist
2131 * '*retrieved_attrs' is an output list of integers of columns being retrieved
2132 * by RETURNING (if any)
2135 deparseDirectUpdateSql(StringInfo buf
, PlannerInfo
*root
,
2136 Index rtindex
, Relation rel
,
2137 RelOptInfo
*foreignrel
,
2142 List
*returningList
,
2143 List
**retrieved_attrs
)
2145 deparse_expr_cxt context
;
2148 RangeTblEntry
*rte
= planner_rt_fetch(rtindex
, root
);
2152 /* Set up context struct for recursion */
2153 context
.root
= root
;
2154 context
.foreignrel
= foreignrel
;
2155 context
.scanrel
= foreignrel
;
2157 context
.params_list
= params_list
;
2159 appendStringInfoString(buf
, "UPDATE ");
2160 deparseRelation(buf
, rel
);
2161 if (foreignrel
->reloptkind
== RELOPT_JOINREL
)
2162 appendStringInfo(buf
, " %s%d", REL_ALIAS_PREFIX
, rtindex
);
2163 appendStringInfoString(buf
, " SET ");
2165 /* Make sure any constants in the exprs are printed portably */
2166 nestlevel
= set_transmission_modes();
2169 forboth(lc
, targetlist
, lc2
, targetAttrs
)
2171 TargetEntry
*tle
= lfirst_node(TargetEntry
, lc
);
2172 int attnum
= lfirst_int(lc2
);
2174 /* update's new-value expressions shouldn't be resjunk */
2175 Assert(!tle
->resjunk
);
2178 appendStringInfoString(buf
, ", ");
2181 deparseColumnRef(buf
, rtindex
, attnum
, rte
, false);
2182 appendStringInfoString(buf
, " = ");
2183 deparseExpr((Expr
*) tle
->expr
, &context
);
2186 reset_transmission_modes(nestlevel
);
2188 if (foreignrel
->reloptkind
== RELOPT_JOINREL
)
2190 List
*ignore_conds
= NIL
;
2192 appendStringInfoString(buf
, " FROM ");
2193 deparseFromExprForRel(buf
, root
, foreignrel
, true, rtindex
,
2194 &ignore_conds
, params_list
);
2195 remote_conds
= list_concat(remote_conds
, ignore_conds
);
2200 appendStringInfoString(buf
, " WHERE ");
2201 appendConditions(remote_conds
, &context
);
2204 if (foreignrel
->reloptkind
== RELOPT_JOINREL
)
2205 deparseExplicitTargetList(returningList
, true, retrieved_attrs
,
2208 deparseReturningList(buf
, rte
, rtindex
, rel
, false,
2209 NIL
, returningList
, retrieved_attrs
);
2213 * deparse remote DELETE statement
2215 * The statement text is appended to buf, and we also create an integer List
2216 * of the columns being retrieved by RETURNING (if any), which is returned
2217 * to *retrieved_attrs.
2220 deparseDeleteSql(StringInfo buf
, RangeTblEntry
*rte
,
2221 Index rtindex
, Relation rel
,
2222 List
*returningList
,
2223 List
**retrieved_attrs
)
2225 appendStringInfoString(buf
, "DELETE FROM ");
2226 deparseRelation(buf
, rel
);
2227 appendStringInfoString(buf
, " WHERE ctid = $1");
2229 deparseReturningList(buf
, rte
, rtindex
, rel
,
2230 rel
->trigdesc
&& rel
->trigdesc
->trig_delete_after_row
,
2231 NIL
, returningList
, retrieved_attrs
);
2235 * deparse remote DELETE statement
2237 * 'buf' is the output buffer to append the statement to
2238 * 'rtindex' is the RT index of the associated target relation
2239 * 'rel' is the relation descriptor for the target relation
2240 * 'foreignrel' is the RelOptInfo for the target relation or the join relation
2241 * containing all base relations in the query
2242 * 'remote_conds' is the qual clauses that must be evaluated remotely
2243 * '*params_list' is an output list of exprs that will become remote Params
2244 * 'returningList' is the RETURNING targetlist
2245 * '*retrieved_attrs' is an output list of integers of columns being retrieved
2246 * by RETURNING (if any)
2249 deparseDirectDeleteSql(StringInfo buf
, PlannerInfo
*root
,
2250 Index rtindex
, Relation rel
,
2251 RelOptInfo
*foreignrel
,
2254 List
*returningList
,
2255 List
**retrieved_attrs
)
2257 deparse_expr_cxt context
;
2259 /* Set up context struct for recursion */
2260 context
.root
= root
;
2261 context
.foreignrel
= foreignrel
;
2262 context
.scanrel
= foreignrel
;
2264 context
.params_list
= params_list
;
2266 appendStringInfoString(buf
, "DELETE FROM ");
2267 deparseRelation(buf
, rel
);
2268 if (foreignrel
->reloptkind
== RELOPT_JOINREL
)
2269 appendStringInfo(buf
, " %s%d", REL_ALIAS_PREFIX
, rtindex
);
2271 if (foreignrel
->reloptkind
== RELOPT_JOINREL
)
2273 List
*ignore_conds
= NIL
;
2275 appendStringInfoString(buf
, " USING ");
2276 deparseFromExprForRel(buf
, root
, foreignrel
, true, rtindex
,
2277 &ignore_conds
, params_list
);
2278 remote_conds
= list_concat(remote_conds
, ignore_conds
);
2283 appendStringInfoString(buf
, " WHERE ");
2284 appendConditions(remote_conds
, &context
);
2287 if (foreignrel
->reloptkind
== RELOPT_JOINREL
)
2288 deparseExplicitTargetList(returningList
, true, retrieved_attrs
,
2291 deparseReturningList(buf
, planner_rt_fetch(rtindex
, root
),
2292 rtindex
, rel
, false,
2293 NIL
, returningList
, retrieved_attrs
);
2297 * Add a RETURNING clause, if needed, to an INSERT/UPDATE/DELETE.
2300 deparseReturningList(StringInfo buf
, RangeTblEntry
*rte
,
2301 Index rtindex
, Relation rel
,
2302 bool trig_after_row
,
2303 List
*withCheckOptionList
,
2304 List
*returningList
,
2305 List
**retrieved_attrs
)
2307 Bitmapset
*attrs_used
= NULL
;
2311 /* whole-row reference acquires all non-system columns */
2313 bms_make_singleton(0 - FirstLowInvalidHeapAttributeNumber
);
2316 if (withCheckOptionList
!= NIL
)
2319 * We need the attrs, non-system and system, mentioned in the local
2320 * query's WITH CHECK OPTION list.
2322 * Note: we do this to ensure that WCO constraints will be evaluated
2323 * on the data actually inserted/updated on the remote side, which
2324 * might differ from the data supplied by the core code, for example
2325 * as a result of remote triggers.
2327 pull_varattnos((Node
*) withCheckOptionList
, rtindex
,
2331 if (returningList
!= NIL
)
2334 * We need the attrs, non-system and system, mentioned in the local
2335 * query's RETURNING list.
2337 pull_varattnos((Node
*) returningList
, rtindex
,
2341 if (attrs_used
!= NULL
)
2342 deparseTargetList(buf
, rte
, rtindex
, rel
, true, attrs_used
, false,
2345 *retrieved_attrs
= NIL
;
2349 * Construct SELECT statement to acquire size in blocks of given relation.
2351 * Note: we use local definition of block size, not remote definition.
2352 * This is perhaps debatable.
2354 * Note: pg_relation_size() exists in 8.1 and later.
2357 deparseAnalyzeSizeSql(StringInfo buf
, Relation rel
)
2359 StringInfoData relname
;
2361 /* We'll need the remote relation name as a literal. */
2362 initStringInfo(&relname
);
2363 deparseRelation(&relname
, rel
);
2365 appendStringInfoString(buf
, "SELECT pg_catalog.pg_relation_size(");
2366 deparseStringLiteral(buf
, relname
.data
);
2367 appendStringInfo(buf
, "::pg_catalog.regclass) / %d", BLCKSZ
);
2371 * Construct SELECT statement to acquire the number of rows and the relkind of
2374 * Note: we just return the remote server's reltuples value, which might
2375 * be off a good deal, but it doesn't seem worth working harder. See
2376 * comments in postgresAcquireSampleRowsFunc.
2379 deparseAnalyzeInfoSql(StringInfo buf
, Relation rel
)
2381 StringInfoData relname
;
2383 /* We'll need the remote relation name as a literal. */
2384 initStringInfo(&relname
);
2385 deparseRelation(&relname
, rel
);
2387 appendStringInfoString(buf
, "SELECT reltuples, relkind FROM pg_catalog.pg_class WHERE oid = ");
2388 deparseStringLiteral(buf
, relname
.data
);
2389 appendStringInfoString(buf
, "::pg_catalog.regclass");
2393 * Construct SELECT statement to acquire sample rows of given relation.
2395 * SELECT command is appended to buf, and list of columns retrieved
2396 * is returned to *retrieved_attrs.
2398 * We only support sampling methods we can decide based on server version.
2399 * Allowing custom TSM modules (like tsm_system_rows) might be useful, but it
2400 * would require detecting which extensions are installed, to allow automatic
2401 * fall-back. Moreover, the methods may use different parameters like number
2402 * of rows (and not sampling rate). So we leave this for future improvements.
2404 * Using random() to sample rows on the remote server has the advantage that
2405 * this works on all PostgreSQL versions (unlike TABLESAMPLE), and that it
2406 * does the sampling on the remote side (without transferring everything and
2407 * then discarding most rows).
2409 * The disadvantage is that we still have to read all rows and evaluate the
2410 * random(), while TABLESAMPLE (at least with the "system" method) may skip.
2411 * It's not that different from the "bernoulli" method, though.
2413 * We could also do "ORDER BY random() LIMIT x", which would always pick
2414 * the expected number of rows, but it requires sorting so it may be much
2415 * more expensive (particularly on large tables, which is what the
2416 * remote sampling is meant to improve).
2419 deparseAnalyzeSql(StringInfo buf
, Relation rel
,
2420 PgFdwSamplingMethod sample_method
, double sample_frac
,
2421 List
**retrieved_attrs
)
2423 Oid relid
= RelationGetRelid(rel
);
2424 TupleDesc tupdesc
= RelationGetDescr(rel
);
2431 *retrieved_attrs
= NIL
;
2433 appendStringInfoString(buf
, "SELECT ");
2434 for (i
= 0; i
< tupdesc
->natts
; i
++)
2436 /* Ignore dropped columns. */
2437 if (TupleDescAttr(tupdesc
, i
)->attisdropped
)
2441 appendStringInfoString(buf
, ", ");
2444 /* Use attribute name or column_name option. */
2445 colname
= NameStr(TupleDescAttr(tupdesc
, i
)->attname
);
2446 options
= GetForeignColumnOptions(relid
, i
+ 1);
2448 foreach(lc
, options
)
2450 DefElem
*def
= (DefElem
*) lfirst(lc
);
2452 if (strcmp(def
->defname
, "column_name") == 0)
2454 colname
= defGetString(def
);
2459 appendStringInfoString(buf
, quote_identifier(colname
));
2461 *retrieved_attrs
= lappend_int(*retrieved_attrs
, i
+ 1);
2464 /* Don't generate bad syntax for zero-column relation. */
2466 appendStringInfoString(buf
, "NULL");
2469 * Construct FROM clause, and perhaps WHERE clause too, depending on the
2470 * selected sampling method.
2472 appendStringInfoString(buf
, " FROM ");
2473 deparseRelation(buf
, rel
);
2475 switch (sample_method
)
2477 case ANALYZE_SAMPLE_OFF
:
2478 /* nothing to do here */
2481 case ANALYZE_SAMPLE_RANDOM
:
2482 appendStringInfo(buf
, " WHERE pg_catalog.random() < %f", sample_frac
);
2485 case ANALYZE_SAMPLE_SYSTEM
:
2486 appendStringInfo(buf
, " TABLESAMPLE SYSTEM(%f)", (100.0 * sample_frac
));
2489 case ANALYZE_SAMPLE_BERNOULLI
:
2490 appendStringInfo(buf
, " TABLESAMPLE BERNOULLI(%f)", (100.0 * sample_frac
));
2493 case ANALYZE_SAMPLE_AUTO
:
2494 /* should have been resolved into actual method */
2495 elog(ERROR
, "unexpected sampling method");
2501 * Construct a simple "TRUNCATE rel" statement
2504 deparseTruncateSql(StringInfo buf
,
2506 DropBehavior behavior
,
2511 appendStringInfoString(buf
, "TRUNCATE ");
2515 Relation rel
= lfirst(cell
);
2517 if (cell
!= list_head(rels
))
2518 appendStringInfoString(buf
, ", ");
2520 deparseRelation(buf
, rel
);
2523 appendStringInfo(buf
, " %s IDENTITY",
2524 restart_seqs
? "RESTART" : "CONTINUE");
2526 if (behavior
== DROP_RESTRICT
)
2527 appendStringInfoString(buf
, " RESTRICT");
2528 else if (behavior
== DROP_CASCADE
)
2529 appendStringInfoString(buf
, " CASCADE");
2533 * Construct name to use for given column, and emit it into buf.
2534 * If it has a column_name FDW option, use that instead of attribute name.
2536 * If qualify_col is true, qualify column name with the alias of relation.
2539 deparseColumnRef(StringInfo buf
, int varno
, int varattno
, RangeTblEntry
*rte
,
2542 /* We support fetching the remote side's CTID and OID. */
2543 if (varattno
== SelfItemPointerAttributeNumber
)
2546 ADD_REL_QUALIFIER(buf
, varno
);
2547 appendStringInfoString(buf
, "ctid");
2549 else if (varattno
< 0)
2552 * All other system attributes are fetched as 0, except for table OID,
2553 * which is fetched as the local table OID. However, we must be
2554 * careful; the table could be beneath an outer join, in which case it
2555 * must go to NULL whenever the rest of the row does.
2559 if (varattno
== TableOidAttributeNumber
)
2560 fetchval
= rte
->relid
;
2564 appendStringInfoString(buf
, "CASE WHEN (");
2565 ADD_REL_QUALIFIER(buf
, varno
);
2566 appendStringInfo(buf
, "*)::text IS NOT NULL THEN %u END", fetchval
);
2569 appendStringInfo(buf
, "%u", fetchval
);
2571 else if (varattno
== 0)
2573 /* Whole row reference */
2575 Bitmapset
*attrs_used
;
2577 /* Required only to be passed down to deparseTargetList(). */
2578 List
*retrieved_attrs
;
2581 * The lock on the relation will be held by upper callers, so it's
2582 * fine to open it with no lock here.
2584 rel
= table_open(rte
->relid
, NoLock
);
2587 * The local name of the foreign table can not be recognized by the
2588 * foreign server and the table it references on foreign server might
2589 * have different column ordering or different columns than those
2590 * declared locally. Hence we have to deparse whole-row reference as
2591 * ROW(columns referenced locally). Construct this by deparsing a
2592 * "whole row" attribute.
2594 attrs_used
= bms_add_member(NULL
,
2595 0 - FirstLowInvalidHeapAttributeNumber
);
2598 * In case the whole-row reference is under an outer join then it has
2599 * to go NULL whenever the rest of the row goes NULL. Deparsing a join
2600 * query would always involve multiple relations, thus qualify_col
2605 appendStringInfoString(buf
, "CASE WHEN (");
2606 ADD_REL_QUALIFIER(buf
, varno
);
2607 appendStringInfoString(buf
, "*)::text IS NOT NULL THEN ");
2610 appendStringInfoString(buf
, "ROW(");
2611 deparseTargetList(buf
, rte
, varno
, rel
, false, attrs_used
, qualify_col
,
2613 appendStringInfoChar(buf
, ')');
2615 /* Complete the CASE WHEN statement started above. */
2617 appendStringInfoString(buf
, " END");
2619 table_close(rel
, NoLock
);
2620 bms_free(attrs_used
);
2624 char *colname
= NULL
;
2628 /* varno must not be any of OUTER_VAR, INNER_VAR and INDEX_VAR. */
2629 Assert(!IS_SPECIAL_VARNO(varno
));
2632 * If it's a column of a foreign table, and it has the column_name FDW
2633 * option, use that value.
2635 options
= GetForeignColumnOptions(rte
->relid
, varattno
);
2636 foreach(lc
, options
)
2638 DefElem
*def
= (DefElem
*) lfirst(lc
);
2640 if (strcmp(def
->defname
, "column_name") == 0)
2642 colname
= defGetString(def
);
2648 * If it's a column of a regular table or it doesn't have column_name
2649 * FDW option, use attribute name.
2651 if (colname
== NULL
)
2652 colname
= get_attname(rte
->relid
, varattno
, false);
2655 ADD_REL_QUALIFIER(buf
, varno
);
2657 appendStringInfoString(buf
, quote_identifier(colname
));
2662 * Append remote name of specified foreign table to buf.
2663 * Use value of table_name FDW option (if any) instead of relation's name.
2664 * Similarly, schema_name FDW option overrides schema name.
2667 deparseRelation(StringInfo buf
, Relation rel
)
2669 ForeignTable
*table
;
2670 const char *nspname
= NULL
;
2671 const char *relname
= NULL
;
2674 /* obtain additional catalog information. */
2675 table
= GetForeignTable(RelationGetRelid(rel
));
2678 * Use value of FDW options if any, instead of the name of object itself.
2680 foreach(lc
, table
->options
)
2682 DefElem
*def
= (DefElem
*) lfirst(lc
);
2684 if (strcmp(def
->defname
, "schema_name") == 0)
2685 nspname
= defGetString(def
);
2686 else if (strcmp(def
->defname
, "table_name") == 0)
2687 relname
= defGetString(def
);
2691 * Note: we could skip printing the schema name if it's pg_catalog, but
2692 * that doesn't seem worth the trouble.
2694 if (nspname
== NULL
)
2695 nspname
= get_namespace_name(RelationGetNamespace(rel
));
2696 if (relname
== NULL
)
2697 relname
= RelationGetRelationName(rel
);
2699 appendStringInfo(buf
, "%s.%s",
2700 quote_identifier(nspname
), quote_identifier(relname
));
2704 * Append a SQL string literal representing "val" to buf.
2707 deparseStringLiteral(StringInfo buf
, const char *val
)
2712 * Rather than making assumptions about the remote server's value of
2713 * standard_conforming_strings, always use E'foo' syntax if there are any
2714 * backslashes. This will fail on remote servers before 8.1, but those
2715 * are long out of support.
2717 if (strchr(val
, '\\') != NULL
)
2718 appendStringInfoChar(buf
, ESCAPE_STRING_SYNTAX
);
2719 appendStringInfoChar(buf
, '\'');
2720 for (valptr
= val
; *valptr
; valptr
++)
2724 if (SQL_STR_DOUBLE(ch
, true))
2725 appendStringInfoChar(buf
, ch
);
2726 appendStringInfoChar(buf
, ch
);
2728 appendStringInfoChar(buf
, '\'');
2732 * Deparse given expression into context->buf.
2734 * This function must support all the same node types that foreign_expr_walker
2737 * Note: unlike ruleutils.c, we just use a simple hard-wired parenthesization
2738 * scheme: anything more complex than a Var, Const, function call or cast
2739 * should be self-parenthesized.
2742 deparseExpr(Expr
*node
, deparse_expr_cxt
*context
)
2747 switch (nodeTag(node
))
2750 deparseVar((Var
*) node
, context
);
2753 deparseConst((Const
*) node
, context
, 0);
2756 deparseParam((Param
*) node
, context
);
2758 case T_SubscriptingRef
:
2759 deparseSubscriptingRef((SubscriptingRef
*) node
, context
);
2762 deparseFuncExpr((FuncExpr
*) node
, context
);
2765 deparseOpExpr((OpExpr
*) node
, context
);
2767 case T_DistinctExpr
:
2768 deparseDistinctExpr((DistinctExpr
*) node
, context
);
2770 case T_ScalarArrayOpExpr
:
2771 deparseScalarArrayOpExpr((ScalarArrayOpExpr
*) node
, context
);
2774 deparseRelabelType((RelabelType
*) node
, context
);
2777 deparseBoolExpr((BoolExpr
*) node
, context
);
2780 deparseNullTest((NullTest
*) node
, context
);
2783 deparseCaseExpr((CaseExpr
*) node
, context
);
2786 deparseArrayExpr((ArrayExpr
*) node
, context
);
2789 deparseAggref((Aggref
*) node
, context
);
2792 elog(ERROR
, "unsupported expression type for deparse: %d",
2793 (int) nodeTag(node
));
2799 * Deparse given Var node into context->buf.
2801 * If the Var belongs to the foreign relation, just print its remote name.
2802 * Otherwise, it's effectively a Param (and will in fact be a Param at
2803 * run time). Handle it the same way we handle plain Params --- see
2804 * deparseParam for comments.
2807 deparseVar(Var
*node
, deparse_expr_cxt
*context
)
2809 Relids relids
= context
->scanrel
->relids
;
2813 /* Qualify columns when multiple relations are involved. */
2814 bool qualify_col
= (bms_membership(relids
) == BMS_MULTIPLE
);
2817 * If the Var belongs to the foreign relation that is deparsed as a
2818 * subquery, use the relation and column alias to the Var provided by the
2819 * subquery, instead of the remote name.
2821 if (is_subquery_var(node
, context
->scanrel
, &relno
, &colno
))
2823 appendStringInfo(context
->buf
, "%s%d.%s%d",
2824 SUBQUERY_REL_ALIAS_PREFIX
, relno
,
2825 SUBQUERY_COL_ALIAS_PREFIX
, colno
);
2829 if (bms_is_member(node
->varno
, relids
) && node
->varlevelsup
== 0)
2830 deparseColumnRef(context
->buf
, node
->varno
, node
->varattno
,
2831 planner_rt_fetch(node
->varno
, context
->root
),
2835 /* Treat like a Param */
2836 if (context
->params_list
)
2841 /* find its index in params_list */
2842 foreach(lc
, *context
->params_list
)
2845 if (equal(node
, (Node
*) lfirst(lc
)))
2850 /* not in list, so add it */
2852 *context
->params_list
= lappend(*context
->params_list
, node
);
2855 printRemoteParam(pindex
, node
->vartype
, node
->vartypmod
, context
);
2859 printRemotePlaceholder(node
->vartype
, node
->vartypmod
, context
);
2865 * Deparse given constant value into context->buf.
2867 * This function has to be kept in sync with ruleutils.c's get_const_expr.
2869 * As in that function, showtype can be -1 to never show "::typename"
2870 * decoration, +1 to always show it, or 0 to show it only if the constant
2871 * wouldn't be assumed to be the right type by default.
2873 * In addition, this code allows showtype to be -2 to indicate that we should
2874 * not show "::typename" decoration if the constant is printed as an untyped
2875 * literal or NULL (while in other cases, behaving as for showtype == 0).
2878 deparseConst(Const
*node
, deparse_expr_cxt
*context
, int showtype
)
2880 StringInfo buf
= context
->buf
;
2884 bool isfloat
= false;
2885 bool isstring
= false;
2888 if (node
->constisnull
)
2890 appendStringInfoString(buf
, "NULL");
2892 appendStringInfo(buf
, "::%s",
2893 deparse_type_name(node
->consttype
,
2894 node
->consttypmod
));
2898 getTypeOutputInfo(node
->consttype
,
2899 &typoutput
, &typIsVarlena
);
2900 extval
= OidOutputFunctionCall(typoutput
, node
->constvalue
);
2902 switch (node
->consttype
)
2913 * No need to quote unless it's a special value such as 'NaN'.
2914 * See comments in get_const_expr().
2916 if (strspn(extval
, "0123456789+-eE.") == strlen(extval
))
2918 if (extval
[0] == '+' || extval
[0] == '-')
2919 appendStringInfo(buf
, "(%s)", extval
);
2921 appendStringInfoString(buf
, extval
);
2922 if (strcspn(extval
, "eE.") != strlen(extval
))
2923 isfloat
= true; /* it looks like a float */
2926 appendStringInfo(buf
, "'%s'", extval
);
2931 appendStringInfo(buf
, "B'%s'", extval
);
2934 if (strcmp(extval
, "t") == 0)
2935 appendStringInfoString(buf
, "true");
2937 appendStringInfoString(buf
, "false");
2940 deparseStringLiteral(buf
, extval
);
2948 return; /* never print type label */
2951 * For showtype == 0, append ::typename unless the constant will be
2952 * implicitly typed as the right type when it is read in.
2954 * XXX this code has to be kept in sync with the behavior of the parser,
2955 * especially make_const.
2957 switch (node
->consttype
)
2965 needlabel
= !isfloat
|| (node
->consttypmod
>= 0);
2970 /* label unless we printed it as an untyped string */
2971 needlabel
= !isstring
;
2977 if (needlabel
|| showtype
> 0)
2978 appendStringInfo(buf
, "::%s",
2979 deparse_type_name(node
->consttype
,
2980 node
->consttypmod
));
2984 * Deparse given Param node.
2986 * If we're generating the query "for real", add the Param to
2987 * context->params_list if it's not already present, and then use its index
2988 * in that list as the remote parameter number. During EXPLAIN, there's
2989 * no need to identify a parameter number.
2992 deparseParam(Param
*node
, deparse_expr_cxt
*context
)
2994 if (context
->params_list
)
2999 /* find its index in params_list */
3000 foreach(lc
, *context
->params_list
)
3003 if (equal(node
, (Node
*) lfirst(lc
)))
3008 /* not in list, so add it */
3010 *context
->params_list
= lappend(*context
->params_list
, node
);
3013 printRemoteParam(pindex
, node
->paramtype
, node
->paramtypmod
, context
);
3017 printRemotePlaceholder(node
->paramtype
, node
->paramtypmod
, context
);
3022 * Deparse a container subscript expression.
3025 deparseSubscriptingRef(SubscriptingRef
*node
, deparse_expr_cxt
*context
)
3027 StringInfo buf
= context
->buf
;
3028 ListCell
*lowlist_item
;
3029 ListCell
*uplist_item
;
3031 /* Always parenthesize the expression. */
3032 appendStringInfoChar(buf
, '(');
3035 * Deparse referenced array expression first. If that expression includes
3036 * a cast, we have to parenthesize to prevent the array subscript from
3037 * being taken as typename decoration. We can avoid that in the typical
3038 * case of subscripting a Var, but otherwise do it.
3040 if (IsA(node
->refexpr
, Var
))
3041 deparseExpr(node
->refexpr
, context
);
3044 appendStringInfoChar(buf
, '(');
3045 deparseExpr(node
->refexpr
, context
);
3046 appendStringInfoChar(buf
, ')');
3049 /* Deparse subscript expressions. */
3050 lowlist_item
= list_head(node
->reflowerindexpr
); /* could be NULL */
3051 foreach(uplist_item
, node
->refupperindexpr
)
3053 appendStringInfoChar(buf
, '[');
3056 deparseExpr(lfirst(lowlist_item
), context
);
3057 appendStringInfoChar(buf
, ':');
3058 lowlist_item
= lnext(node
->reflowerindexpr
, lowlist_item
);
3060 deparseExpr(lfirst(uplist_item
), context
);
3061 appendStringInfoChar(buf
, ']');
3064 appendStringInfoChar(buf
, ')');
3068 * Deparse a function call.
3071 deparseFuncExpr(FuncExpr
*node
, deparse_expr_cxt
*context
)
3073 StringInfo buf
= context
->buf
;
3079 * If the function call came from an implicit coercion, then just show the
3082 if (node
->funcformat
== COERCE_IMPLICIT_CAST
)
3084 deparseExpr((Expr
*) linitial(node
->args
), context
);
3089 * If the function call came from a cast, then show the first argument
3090 * plus an explicit cast operation.
3092 if (node
->funcformat
== COERCE_EXPLICIT_CAST
)
3094 Oid rettype
= node
->funcresulttype
;
3095 int32 coercedTypmod
;
3097 /* Get the typmod if this is a length-coercion function */
3098 (void) exprIsLengthCoercion((Node
*) node
, &coercedTypmod
);
3100 deparseExpr((Expr
*) linitial(node
->args
), context
);
3101 appendStringInfo(buf
, "::%s",
3102 deparse_type_name(rettype
, coercedTypmod
));
3106 /* Check if need to print VARIADIC (cf. ruleutils.c) */
3107 use_variadic
= node
->funcvariadic
;
3110 * Normal function: display as proname(args).
3112 appendFunctionName(node
->funcid
, context
);
3113 appendStringInfoChar(buf
, '(');
3115 /* ... and all the arguments */
3117 foreach(arg
, node
->args
)
3120 appendStringInfoString(buf
, ", ");
3121 if (use_variadic
&& lnext(node
->args
, arg
) == NULL
)
3122 appendStringInfoString(buf
, "VARIADIC ");
3123 deparseExpr((Expr
*) lfirst(arg
), context
);
3126 appendStringInfoChar(buf
, ')');
3130 * Deparse given operator expression. To avoid problems around
3131 * priority of operations, we always parenthesize the arguments.
3134 deparseOpExpr(OpExpr
*node
, deparse_expr_cxt
*context
)
3136 StringInfo buf
= context
->buf
;
3138 Form_pg_operator form
;
3140 bool canSuppressRightConstCast
= false;
3143 /* Retrieve information about the operator from system catalog. */
3144 tuple
= SearchSysCache1(OPEROID
, ObjectIdGetDatum(node
->opno
));
3145 if (!HeapTupleIsValid(tuple
))
3146 elog(ERROR
, "cache lookup failed for operator %u", node
->opno
);
3147 form
= (Form_pg_operator
) GETSTRUCT(tuple
);
3148 oprkind
= form
->oprkind
;
3151 Assert((oprkind
== 'l' && list_length(node
->args
) == 1) ||
3152 (oprkind
== 'b' && list_length(node
->args
) == 2));
3154 right
= llast(node
->args
);
3156 /* Always parenthesize the expression. */
3157 appendStringInfoChar(buf
, '(');
3159 /* Deparse left operand, if any. */
3162 Expr
*left
= linitial(node
->args
);
3163 Oid leftType
= exprType((Node
*) left
);
3164 Oid rightType
= exprType((Node
*) right
);
3165 bool canSuppressLeftConstCast
= false;
3168 * When considering a binary operator, if one operand is a Const that
3169 * can be printed as a bare string literal or NULL (i.e., it will look
3170 * like type UNKNOWN to the remote parser), the Const normally
3171 * receives an explicit cast to the operator's input type. However,
3172 * in Const-to-Var comparisons where both operands are of the same
3173 * type, we prefer to suppress the explicit cast, leaving the Const's
3174 * type resolution up to the remote parser. The remote's resolution
3175 * heuristic will assume that an unknown input type being compared to
3176 * a known input type is of that known type as well.
3178 * This hack allows some cases to succeed where a remote column is
3179 * declared with a different type in the local (foreign) table. By
3180 * emitting "foreigncol = 'foo'" not "foreigncol = 'foo'::text" or the
3181 * like, we allow the remote parser to pick an "=" operator that's
3182 * compatible with whatever type the remote column really is, such as
3185 * We allow cast suppression to happen only when the other operand is
3186 * a plain foreign Var. Although the remote's unknown-type heuristic
3187 * would apply to other cases just as well, we would be taking a
3188 * bigger risk that the inferred type is something unexpected. With
3189 * this restriction, if anything goes wrong it's the user's fault for
3190 * not declaring the local column with the same type as the remote
3193 if (leftType
== rightType
)
3195 if (IsA(left
, Const
))
3196 canSuppressLeftConstCast
= isPlainForeignVar(right
, context
);
3197 else if (IsA(right
, Const
))
3198 canSuppressRightConstCast
= isPlainForeignVar(left
, context
);
3201 if (canSuppressLeftConstCast
)
3202 deparseConst((Const
*) left
, context
, -2);
3204 deparseExpr(left
, context
);
3206 appendStringInfoChar(buf
, ' ');
3209 /* Deparse operator name. */
3210 deparseOperatorName(buf
, form
);
3212 /* Deparse right operand. */
3213 appendStringInfoChar(buf
, ' ');
3215 if (canSuppressRightConstCast
)
3216 deparseConst((Const
*) right
, context
, -2);
3218 deparseExpr(right
, context
);
3220 appendStringInfoChar(buf
, ')');
3222 ReleaseSysCache(tuple
);
3226 * Will "node" deparse as a plain foreign Var?
3229 isPlainForeignVar(Expr
*node
, deparse_expr_cxt
*context
)
3232 * We allow the foreign Var to have an implicit RelabelType, mainly so
3233 * that this'll work with varchar columns. Note that deparseRelabelType
3234 * will not print such a cast, so we're not breaking the restriction that
3235 * the expression print as a plain Var. We won't risk it for an implicit
3236 * cast that requires a function, nor for non-implicit RelabelType; such
3237 * cases seem too likely to involve semantics changes compared to what
3238 * would happen on the remote side.
3240 if (IsA(node
, RelabelType
) &&
3241 ((RelabelType
*) node
)->relabelformat
== COERCE_IMPLICIT_CAST
)
3242 node
= ((RelabelType
*) node
)->arg
;
3247 * The Var must be one that'll deparse as a foreign column reference
3250 Var
*var
= (Var
*) node
;
3251 Relids relids
= context
->scanrel
->relids
;
3253 if (bms_is_member(var
->varno
, relids
) && var
->varlevelsup
== 0)
3261 * Print the name of an operator.
3264 deparseOperatorName(StringInfo buf
, Form_pg_operator opform
)
3268 /* opname is not a SQL identifier, so we should not quote it. */
3269 opname
= NameStr(opform
->oprname
);
3271 /* Print schema name only if it's not pg_catalog */
3272 if (opform
->oprnamespace
!= PG_CATALOG_NAMESPACE
)
3274 const char *opnspname
;
3276 opnspname
= get_namespace_name(opform
->oprnamespace
);
3277 /* Print fully qualified operator name. */
3278 appendStringInfo(buf
, "OPERATOR(%s.%s)",
3279 quote_identifier(opnspname
), opname
);
3283 /* Just print operator name. */
3284 appendStringInfoString(buf
, opname
);
3289 * Deparse IS DISTINCT FROM.
3292 deparseDistinctExpr(DistinctExpr
*node
, deparse_expr_cxt
*context
)
3294 StringInfo buf
= context
->buf
;
3296 Assert(list_length(node
->args
) == 2);
3298 appendStringInfoChar(buf
, '(');
3299 deparseExpr(linitial(node
->args
), context
);
3300 appendStringInfoString(buf
, " IS DISTINCT FROM ");
3301 deparseExpr(lsecond(node
->args
), context
);
3302 appendStringInfoChar(buf
, ')');
3306 * Deparse given ScalarArrayOpExpr expression. To avoid problems
3307 * around priority of operations, we always parenthesize the arguments.
3310 deparseScalarArrayOpExpr(ScalarArrayOpExpr
*node
, deparse_expr_cxt
*context
)
3312 StringInfo buf
= context
->buf
;
3314 Form_pg_operator form
;
3318 /* Retrieve information about the operator from system catalog. */
3319 tuple
= SearchSysCache1(OPEROID
, ObjectIdGetDatum(node
->opno
));
3320 if (!HeapTupleIsValid(tuple
))
3321 elog(ERROR
, "cache lookup failed for operator %u", node
->opno
);
3322 form
= (Form_pg_operator
) GETSTRUCT(tuple
);
3325 Assert(list_length(node
->args
) == 2);
3327 /* Always parenthesize the expression. */
3328 appendStringInfoChar(buf
, '(');
3330 /* Deparse left operand. */
3331 arg1
= linitial(node
->args
);
3332 deparseExpr(arg1
, context
);
3333 appendStringInfoChar(buf
, ' ');
3335 /* Deparse operator name plus decoration. */
3336 deparseOperatorName(buf
, form
);
3337 appendStringInfo(buf
, " %s (", node
->useOr
? "ANY" : "ALL");
3339 /* Deparse right operand. */
3340 arg2
= lsecond(node
->args
);
3341 deparseExpr(arg2
, context
);
3343 appendStringInfoChar(buf
, ')');
3345 /* Always parenthesize the expression. */
3346 appendStringInfoChar(buf
, ')');
3348 ReleaseSysCache(tuple
);
3352 * Deparse a RelabelType (binary-compatible cast) node.
3355 deparseRelabelType(RelabelType
*node
, deparse_expr_cxt
*context
)
3357 deparseExpr(node
->arg
, context
);
3358 if (node
->relabelformat
!= COERCE_IMPLICIT_CAST
)
3359 appendStringInfo(context
->buf
, "::%s",
3360 deparse_type_name(node
->resulttype
,
3361 node
->resulttypmod
));
3365 * Deparse a BoolExpr node.
3368 deparseBoolExpr(BoolExpr
*node
, deparse_expr_cxt
*context
)
3370 StringInfo buf
= context
->buf
;
3371 const char *op
= NULL
; /* keep compiler quiet */
3375 switch (node
->boolop
)
3384 appendStringInfoString(buf
, "(NOT ");
3385 deparseExpr(linitial(node
->args
), context
);
3386 appendStringInfoChar(buf
, ')');
3390 appendStringInfoChar(buf
, '(');
3392 foreach(lc
, node
->args
)
3395 appendStringInfo(buf
, " %s ", op
);
3396 deparseExpr((Expr
*) lfirst(lc
), context
);
3399 appendStringInfoChar(buf
, ')');
3403 * Deparse IS [NOT] NULL expression.
3406 deparseNullTest(NullTest
*node
, deparse_expr_cxt
*context
)
3408 StringInfo buf
= context
->buf
;
3410 appendStringInfoChar(buf
, '(');
3411 deparseExpr(node
->arg
, context
);
3414 * For scalar inputs, we prefer to print as IS [NOT] NULL, which is
3415 * shorter and traditional. If it's a rowtype input but we're applying a
3416 * scalar test, must print IS [NOT] DISTINCT FROM NULL to be semantically
3419 if (node
->argisrow
|| !type_is_rowtype(exprType((Node
*) node
->arg
)))
3421 if (node
->nulltesttype
== IS_NULL
)
3422 appendStringInfoString(buf
, " IS NULL)");
3424 appendStringInfoString(buf
, " IS NOT NULL)");
3428 if (node
->nulltesttype
== IS_NULL
)
3429 appendStringInfoString(buf
, " IS NOT DISTINCT FROM NULL)");
3431 appendStringInfoString(buf
, " IS DISTINCT FROM NULL)");
3436 * Deparse CASE expression
3439 deparseCaseExpr(CaseExpr
*node
, deparse_expr_cxt
*context
)
3441 StringInfo buf
= context
->buf
;
3444 appendStringInfoString(buf
, "(CASE");
3446 /* If this is a CASE arg WHEN then emit the arg expression */
3447 if (node
->arg
!= NULL
)
3449 appendStringInfoChar(buf
, ' ');
3450 deparseExpr(node
->arg
, context
);
3453 /* Add each condition/result of the CASE clause */
3454 foreach(lc
, node
->args
)
3456 CaseWhen
*whenclause
= (CaseWhen
*) lfirst(lc
);
3459 appendStringInfoString(buf
, " WHEN ");
3460 if (node
->arg
== NULL
) /* CASE WHEN */
3461 deparseExpr(whenclause
->expr
, context
);
3462 else /* CASE arg WHEN */
3464 /* Ignore the CaseTestExpr and equality operator. */
3465 deparseExpr(lsecond(castNode(OpExpr
, whenclause
->expr
)->args
),
3470 appendStringInfoString(buf
, " THEN ");
3471 deparseExpr(whenclause
->result
, context
);
3474 /* add ELSE if present */
3475 if (node
->defresult
!= NULL
)
3477 appendStringInfoString(buf
, " ELSE ");
3478 deparseExpr(node
->defresult
, context
);
3482 appendStringInfoString(buf
, " END)");
3486 * Deparse ARRAY[...] construct.
3489 deparseArrayExpr(ArrayExpr
*node
, deparse_expr_cxt
*context
)
3491 StringInfo buf
= context
->buf
;
3495 appendStringInfoString(buf
, "ARRAY[");
3496 foreach(lc
, node
->elements
)
3499 appendStringInfoString(buf
, ", ");
3500 deparseExpr(lfirst(lc
), context
);
3503 appendStringInfoChar(buf
, ']');
3505 /* If the array is empty, we need an explicit cast to the array type. */
3506 if (node
->elements
== NIL
)
3507 appendStringInfo(buf
, "::%s",
3508 deparse_type_name(node
->array_typeid
, -1));
3512 * Deparse an Aggref node.
3515 deparseAggref(Aggref
*node
, deparse_expr_cxt
*context
)
3517 StringInfo buf
= context
->buf
;
3520 /* Only basic, non-split aggregation accepted. */
3521 Assert(node
->aggsplit
== AGGSPLIT_SIMPLE
);
3523 /* Check if need to print VARIADIC (cf. ruleutils.c) */
3524 use_variadic
= node
->aggvariadic
;
3526 /* Find aggregate name from aggfnoid which is a pg_proc entry */
3527 appendFunctionName(node
->aggfnoid
, context
);
3528 appendStringInfoChar(buf
, '(');
3531 appendStringInfoString(buf
, (node
->aggdistinct
!= NIL
) ? "DISTINCT " : "");
3533 if (AGGKIND_IS_ORDERED_SET(node
->aggkind
))
3535 /* Add WITHIN GROUP (ORDER BY ..) */
3539 Assert(!node
->aggvariadic
);
3540 Assert(node
->aggorder
!= NIL
);
3542 foreach(arg
, node
->aggdirectargs
)
3545 appendStringInfoString(buf
, ", ");
3548 deparseExpr((Expr
*) lfirst(arg
), context
);
3551 appendStringInfoString(buf
, ") WITHIN GROUP (ORDER BY ");
3552 appendAggOrderBy(node
->aggorder
, node
->args
, context
);
3556 /* aggstar can be set only in zero-argument aggregates */
3558 appendStringInfoChar(buf
, '*');
3564 /* Add all the arguments */
3565 foreach(arg
, node
->args
)
3567 TargetEntry
*tle
= (TargetEntry
*) lfirst(arg
);
3568 Node
*n
= (Node
*) tle
->expr
;
3574 appendStringInfoString(buf
, ", ");
3578 if (use_variadic
&& lnext(node
->args
, arg
) == NULL
)
3579 appendStringInfoString(buf
, "VARIADIC ");
3581 deparseExpr((Expr
*) n
, context
);
3586 if (node
->aggorder
!= NIL
)
3588 appendStringInfoString(buf
, " ORDER BY ");
3589 appendAggOrderBy(node
->aggorder
, node
->args
, context
);
3593 /* Add FILTER (WHERE ..) */
3594 if (node
->aggfilter
!= NULL
)
3596 appendStringInfoString(buf
, ") FILTER (WHERE ");
3597 deparseExpr((Expr
*) node
->aggfilter
, context
);
3600 appendStringInfoChar(buf
, ')');
3604 * Append ORDER BY within aggregate function.
3607 appendAggOrderBy(List
*orderList
, List
*targetList
, deparse_expr_cxt
*context
)
3609 StringInfo buf
= context
->buf
;
3613 foreach(lc
, orderList
)
3615 SortGroupClause
*srt
= (SortGroupClause
*) lfirst(lc
);
3619 appendStringInfoString(buf
, ", ");
3622 /* Deparse the sort expression proper. */
3623 sortexpr
= deparseSortGroupClause(srt
->tleSortGroupRef
, targetList
,
3625 /* Add decoration as needed. */
3626 appendOrderBySuffix(srt
->sortop
, exprType(sortexpr
), srt
->nulls_first
,
3632 * Append the ASC, DESC, USING <OPERATOR> and NULLS FIRST / NULLS LAST parts
3633 * of an ORDER BY clause.
3636 appendOrderBySuffix(Oid sortop
, Oid sortcoltype
, bool nulls_first
,
3637 deparse_expr_cxt
*context
)
3639 StringInfo buf
= context
->buf
;
3640 TypeCacheEntry
*typentry
;
3642 /* See whether operator is default < or > for sort expr's datatype. */
3643 typentry
= lookup_type_cache(sortcoltype
,
3644 TYPECACHE_LT_OPR
| TYPECACHE_GT_OPR
);
3646 if (sortop
== typentry
->lt_opr
)
3647 appendStringInfoString(buf
, " ASC");
3648 else if (sortop
== typentry
->gt_opr
)
3649 appendStringInfoString(buf
, " DESC");
3653 Form_pg_operator operform
;
3655 appendStringInfoString(buf
, " USING ");
3657 /* Append operator name. */
3658 opertup
= SearchSysCache1(OPEROID
, ObjectIdGetDatum(sortop
));
3659 if (!HeapTupleIsValid(opertup
))
3660 elog(ERROR
, "cache lookup failed for operator %u", sortop
);
3661 operform
= (Form_pg_operator
) GETSTRUCT(opertup
);
3662 deparseOperatorName(buf
, operform
);
3663 ReleaseSysCache(opertup
);
3667 appendStringInfoString(buf
, " NULLS FIRST");
3669 appendStringInfoString(buf
, " NULLS LAST");
3673 * Print the representation of a parameter to be sent to the remote side.
3675 * Note: we always label the Param's type explicitly rather than relying on
3676 * transmitting a numeric type OID in PQexecParams(). This allows us to
3677 * avoid assuming that types have the same OIDs on the remote side as they
3678 * do locally --- they need only have the same names.
3681 printRemoteParam(int paramindex
, Oid paramtype
, int32 paramtypmod
,
3682 deparse_expr_cxt
*context
)
3684 StringInfo buf
= context
->buf
;
3685 char *ptypename
= deparse_type_name(paramtype
, paramtypmod
);
3687 appendStringInfo(buf
, "$%d::%s", paramindex
, ptypename
);
3691 * Print the representation of a placeholder for a parameter that will be
3692 * sent to the remote side at execution time.
3694 * This is used when we're just trying to EXPLAIN the remote query.
3695 * We don't have the actual value of the runtime parameter yet, and we don't
3696 * want the remote planner to generate a plan that depends on such a value
3697 * anyway. Thus, we can't do something simple like "$1::paramtype".
3698 * Instead, we emit "((SELECT null::paramtype)::paramtype)".
3699 * In all extant versions of Postgres, the planner will see that as an unknown
3700 * constant value, which is what we want. This might need adjustment if we
3701 * ever make the planner flatten scalar subqueries. Note: the reason for the
3702 * apparently useless outer cast is to ensure that the representation as a
3703 * whole will be parsed as an a_expr and not a select_with_parens; the latter
3704 * would do the wrong thing in the context "x = ANY(...)".
3707 printRemotePlaceholder(Oid paramtype
, int32 paramtypmod
,
3708 deparse_expr_cxt
*context
)
3710 StringInfo buf
= context
->buf
;
3711 char *ptypename
= deparse_type_name(paramtype
, paramtypmod
);
3713 appendStringInfo(buf
, "((SELECT null::%s)::%s)", ptypename
, ptypename
);
3717 * Deparse GROUP BY clause.
3720 appendGroupByClause(List
*tlist
, deparse_expr_cxt
*context
)
3722 StringInfo buf
= context
->buf
;
3723 Query
*query
= context
->root
->parse
;
3727 /* Nothing to be done, if there's no GROUP BY clause in the query. */
3728 if (!query
->groupClause
)
3731 appendStringInfoString(buf
, " GROUP BY ");
3734 * Queries with grouping sets are not pushed down, so we don't expect
3735 * grouping sets here.
3737 Assert(!query
->groupingSets
);
3740 * We intentionally print query->groupClause not processed_groupClause,
3741 * leaving it to the remote planner to get rid of any redundant GROUP BY
3742 * items again. This is necessary in case processed_groupClause reduced
3743 * to empty, and in any case the redundancy situation on the remote might
3744 * be different than what we think here.
3746 foreach(lc
, query
->groupClause
)
3748 SortGroupClause
*grp
= (SortGroupClause
*) lfirst(lc
);
3751 appendStringInfoString(buf
, ", ");
3754 deparseSortGroupClause(grp
->tleSortGroupRef
, tlist
, true, context
);
3759 * Deparse ORDER BY clause defined by the given pathkeys.
3761 * The clause should use Vars from context->scanrel if !has_final_sort,
3762 * or from context->foreignrel's targetlist if has_final_sort.
3764 * We find a suitable pathkey expression (some earlier step
3765 * should have verified that there is one) and deparse it.
3768 appendOrderByClause(List
*pathkeys
, bool has_final_sort
,
3769 deparse_expr_cxt
*context
)
3773 const char *delim
= " ";
3774 StringInfo buf
= context
->buf
;
3776 /* Make sure any constants in the exprs are printed portably */
3777 nestlevel
= set_transmission_modes();
3779 appendStringInfoString(buf
, " ORDER BY");
3780 foreach(lcell
, pathkeys
)
3782 PathKey
*pathkey
= lfirst(lcell
);
3783 EquivalenceMember
*em
;
3790 * By construction, context->foreignrel is the input relation to
3793 em
= find_em_for_rel_target(context
->root
,
3795 context
->foreignrel
);
3798 em
= find_em_for_rel(context
->root
,
3803 * We don't expect any error here; it would mean that shippability
3804 * wasn't verified earlier. For the same reason, we don't recheck
3805 * shippability of the sort operator.
3808 elog(ERROR
, "could not find pathkey item to sort");
3810 em_expr
= em
->em_expr
;
3813 * Lookup the operator corresponding to the strategy in the opclass.
3814 * The datatype used by the opfamily is not necessarily the same as
3815 * the expression type (for array types for example).
3817 oprid
= get_opfamily_member(pathkey
->pk_opfamily
,
3820 pathkey
->pk_strategy
);
3821 if (!OidIsValid(oprid
))
3822 elog(ERROR
, "missing operator %d(%u,%u) in opfamily %u",
3823 pathkey
->pk_strategy
, em
->em_datatype
, em
->em_datatype
,
3824 pathkey
->pk_opfamily
);
3826 appendStringInfoString(buf
, delim
);
3827 deparseExpr(em_expr
, context
);
3830 * Here we need to use the expression's actual type to discover
3831 * whether the desired operator will be the default or not.
3833 appendOrderBySuffix(oprid
, exprType((Node
*) em_expr
),
3834 pathkey
->pk_nulls_first
, context
);
3838 reset_transmission_modes(nestlevel
);
3842 * Deparse LIMIT/OFFSET clause.
3845 appendLimitClause(deparse_expr_cxt
*context
)
3847 PlannerInfo
*root
= context
->root
;
3848 StringInfo buf
= context
->buf
;
3851 /* Make sure any constants in the exprs are printed portably */
3852 nestlevel
= set_transmission_modes();
3854 if (root
->parse
->limitCount
)
3856 appendStringInfoString(buf
, " LIMIT ");
3857 deparseExpr((Expr
*) root
->parse
->limitCount
, context
);
3859 if (root
->parse
->limitOffset
)
3861 appendStringInfoString(buf
, " OFFSET ");
3862 deparseExpr((Expr
*) root
->parse
->limitOffset
, context
);
3865 reset_transmission_modes(nestlevel
);
3869 * appendFunctionName
3870 * Deparses function name from given function oid.
3873 appendFunctionName(Oid funcid
, deparse_expr_cxt
*context
)
3875 StringInfo buf
= context
->buf
;
3877 Form_pg_proc procform
;
3878 const char *proname
;
3880 proctup
= SearchSysCache1(PROCOID
, ObjectIdGetDatum(funcid
));
3881 if (!HeapTupleIsValid(proctup
))
3882 elog(ERROR
, "cache lookup failed for function %u", funcid
);
3883 procform
= (Form_pg_proc
) GETSTRUCT(proctup
);
3885 /* Print schema name only if it's not pg_catalog */
3886 if (procform
->pronamespace
!= PG_CATALOG_NAMESPACE
)
3888 const char *schemaname
;
3890 schemaname
= get_namespace_name(procform
->pronamespace
);
3891 appendStringInfo(buf
, "%s.", quote_identifier(schemaname
));
3894 /* Always print the function name */
3895 proname
= NameStr(procform
->proname
);
3896 appendStringInfoString(buf
, quote_identifier(proname
));
3898 ReleaseSysCache(proctup
);
3902 * Appends a sort or group clause.
3904 * Like get_rule_sortgroupclause(), returns the expression tree, so caller
3905 * need not find it again.
3908 deparseSortGroupClause(Index ref
, List
*tlist
, bool force_colno
,
3909 deparse_expr_cxt
*context
)
3911 StringInfo buf
= context
->buf
;
3915 tle
= get_sortgroupref_tle(ref
, tlist
);
3920 /* Use column-number form when requested by caller. */
3921 Assert(!tle
->resjunk
);
3922 appendStringInfo(buf
, "%d", tle
->resno
);
3924 else if (expr
&& IsA(expr
, Const
))
3927 * Force a typecast here so that we don't emit something like "GROUP
3928 * BY 2", which will be misconstrued as a column position rather than
3931 deparseConst((Const
*) expr
, context
, 1);
3933 else if (!expr
|| IsA(expr
, Var
))
3934 deparseExpr(expr
, context
);
3937 /* Always parenthesize the expression. */
3938 appendStringInfoChar(buf
, '(');
3939 deparseExpr(expr
, context
);
3940 appendStringInfoChar(buf
, ')');
3943 return (Node
*) expr
;
3948 * Returns true if given Var is deparsed as a subquery output column, in
3949 * which case, *relno and *colno are set to the IDs for the relation and
3950 * column alias to the Var provided by the subquery.
3953 is_subquery_var(Var
*node
, RelOptInfo
*foreignrel
, int *relno
, int *colno
)
3955 PgFdwRelationInfo
*fpinfo
= (PgFdwRelationInfo
*) foreignrel
->fdw_private
;
3956 RelOptInfo
*outerrel
= fpinfo
->outerrel
;
3957 RelOptInfo
*innerrel
= fpinfo
->innerrel
;
3959 /* Should only be called in these cases. */
3960 Assert(IS_SIMPLE_REL(foreignrel
) || IS_JOIN_REL(foreignrel
));
3963 * If the given relation isn't a join relation, it doesn't have any lower
3964 * subqueries, so the Var isn't a subquery output column.
3966 if (!IS_JOIN_REL(foreignrel
))
3970 * If the Var doesn't belong to any lower subqueries, it isn't a subquery
3973 if (!bms_is_member(node
->varno
, fpinfo
->lower_subquery_rels
))
3976 if (bms_is_member(node
->varno
, outerrel
->relids
))
3979 * If outer relation is deparsed as a subquery, the Var is an output
3980 * column of the subquery; get the IDs for the relation/column alias.
3982 if (fpinfo
->make_outerrel_subquery
)
3984 get_relation_column_alias_ids(node
, outerrel
, relno
, colno
);
3988 /* Otherwise, recurse into the outer relation. */
3989 return is_subquery_var(node
, outerrel
, relno
, colno
);
3993 Assert(bms_is_member(node
->varno
, innerrel
->relids
));
3996 * If inner relation is deparsed as a subquery, the Var is an output
3997 * column of the subquery; get the IDs for the relation/column alias.
3999 if (fpinfo
->make_innerrel_subquery
)
4001 get_relation_column_alias_ids(node
, innerrel
, relno
, colno
);
4005 /* Otherwise, recurse into the inner relation. */
4006 return is_subquery_var(node
, innerrel
, relno
, colno
);
4011 * Get the IDs for the relation and column alias to given Var belonging to
4012 * given relation, which are returned into *relno and *colno.
4015 get_relation_column_alias_ids(Var
*node
, RelOptInfo
*foreignrel
,
4016 int *relno
, int *colno
)
4018 PgFdwRelationInfo
*fpinfo
= (PgFdwRelationInfo
*) foreignrel
->fdw_private
;
4022 /* Get the relation alias ID */
4023 *relno
= fpinfo
->relation_index
;
4025 /* Get the column alias ID */
4027 foreach(lc
, foreignrel
->reltarget
->exprs
)
4029 Var
*tlvar
= (Var
*) lfirst(lc
);
4032 * Match reltarget entries only on varno/varattno. Ideally there
4033 * would be some cross-check on varnullingrels, but it's unclear what
4034 * to do exactly; we don't have enough context to know what that value
4037 if (IsA(tlvar
, Var
) &&
4038 tlvar
->varno
== node
->varno
&&
4039 tlvar
->varattno
== node
->varattno
)
4047 /* Shouldn't get here */
4048 elog(ERROR
, "unexpected expression in subquery output");