1 /*-------------------------------------------------------------------------
2  *
3  * deparse.c
4  *		  Query deparser for postgres_fdw
5  *
6  * This file includes functions that examine query WHERE clauses to see
7  * whether they're safe to send to the remote server for execution, as
8  * well as functions to construct the query text to be sent.  The latter
9  * functionality is annoyingly duplicative of ruleutils.c, but there are
10  * enough special considerations that it seems best to keep this separate.
11  * One saving grace is that we only need deparse logic for node types that
12  * we consider safe to send.
13  *
14  * We assume that the remote session's search_path is exactly "pg_catalog",
15  * and thus we need schema-qualify all and only names outside pg_catalog.
16  *
17  * We do not consider that it is ever safe to send COLLATE expressions to
18  * the remote server: it might not have the same collation names we do.
19  * (Later we might consider it safe to send COLLATE "C", but even that would
20  * fail on old remote servers.)  An expression is considered safe to send
21  * only if all operator/function input collations used in it are traceable to
22  * Var(s) of the foreign table.  That implies that if the remote server gets
23  * a different answer than we do, the foreign table's columns are not marked
24  * with collations that match the remote table's columns, which we can
25  * consider to be user error.
26  *
27  * Portions Copyright (c) 2012-2016, PostgreSQL Global Development Group
28  *
29  * IDENTIFICATION
30  *		  contrib/postgres_fdw/deparse.c
31  *
32  *-------------------------------------------------------------------------
33  */
34 #include "postgres.h"
35 
36 #include "postgres_fdw.h"
37 
38 #include "access/heapam.h"
39 #include "access/htup_details.h"
40 #include "access/sysattr.h"
41 #include "catalog/pg_collation.h"
42 #include "catalog/pg_namespace.h"
43 #include "catalog/pg_operator.h"
44 #include "catalog/pg_proc.h"
45 #include "catalog/pg_type.h"
46 #include "commands/defrem.h"
47 #include "nodes/makefuncs.h"
48 #include "nodes/nodeFuncs.h"
49 #include "nodes/plannodes.h"
50 #include "optimizer/clauses.h"
51 #include "optimizer/prep.h"
52 #include "optimizer/tlist.h"
53 #include "optimizer/var.h"
54 #include "parser/parsetree.h"
55 #include "utils/builtins.h"
56 #include "utils/lsyscache.h"
57 #include "utils/rel.h"
58 #include "utils/syscache.h"
59 
60 
61 /*
62  * Global context for foreign_expr_walker's search of an expression tree.
63  */
64 typedef struct foreign_glob_cxt
65 {
66 	PlannerInfo *root;			/* global planner state */
67 	RelOptInfo *foreignrel;		/* the foreign relation we are planning for */
68 } foreign_glob_cxt;
69 
70 /*
71  * Local (per-tree-level) context for foreign_expr_walker's search.
72  * This is concerned with identifying collations used in the expression.
73  */
74 typedef enum
75 {
76 	FDW_COLLATE_NONE,			/* expression is of a noncollatable type, or
77 								 * it has default collation that is not
78 								 * traceable to a foreign Var */
79 	FDW_COLLATE_SAFE,			/* collation derives from a foreign Var */
80 	FDW_COLLATE_UNSAFE			/* collation is non-default and derives from
81 								 * something other than a foreign Var */
82 } FDWCollateState;
83 
84 typedef struct foreign_loc_cxt
85 {
86 	Oid			collation;		/* OID of current collation, if any */
87 	FDWCollateState state;		/* state of current collation choice */
88 } foreign_loc_cxt;
89 
90 /*
91  * Context for deparseExpr
92  */
93 typedef struct deparse_expr_cxt
94 {
95 	PlannerInfo *root;			/* global planner state */
96 	RelOptInfo *foreignrel;		/* the foreign relation we are planning for */
97 	StringInfo	buf;			/* output buffer to append to */
98 	List	  **params_list;	/* exprs that will become remote Params */
99 } deparse_expr_cxt;
100 
101 #define REL_ALIAS_PREFIX	"r"
102 /* Handy macro to add relation name qualification */
103 #define ADD_REL_QUALIFIER(buf, varno)	\
104 		appendStringInfo((buf), "%s%d.", REL_ALIAS_PREFIX, (varno))
105 
106 /*
107  * Functions to determine whether an expression can be evaluated safely on
108  * remote server.
109  */
110 static bool foreign_expr_walker(Node *node,
111 					foreign_glob_cxt *glob_cxt,
112 					foreign_loc_cxt *outer_cxt);
113 static char *deparse_type_name(Oid type_oid, int32 typemod);
114 
115 /*
116  * Functions to construct string representation of a node tree.
117  */
118 static void deparseTargetList(StringInfo buf,
119 				  PlannerInfo *root,
120 				  Index rtindex,
121 				  Relation rel,
122 				  bool is_returning,
123 				  Bitmapset *attrs_used,
124 				  bool qualify_col,
125 				  List **retrieved_attrs);
126 static void deparseExplicitTargetList(List *tlist, List **retrieved_attrs,
127 						  deparse_expr_cxt *context);
128 static void deparseReturningList(StringInfo buf, PlannerInfo *root,
129 					 Index rtindex, Relation rel,
130 					 bool trig_after_row,
131 					 List *returningList,
132 					 List **retrieved_attrs);
133 static void deparseColumnRef(StringInfo buf, int varno, int varattno,
134 				 PlannerInfo *root, bool qualify_col);
135 static void deparseRelation(StringInfo buf, Relation rel);
136 static void deparseExpr(Expr *expr, deparse_expr_cxt *context);
137 static void deparseVar(Var *node, deparse_expr_cxt *context);
138 static void deparseConst(Const *node, deparse_expr_cxt *context);
139 static void deparseParam(Param *node, deparse_expr_cxt *context);
140 static void deparseArrayRef(ArrayRef *node, deparse_expr_cxt *context);
141 static void deparseFuncExpr(FuncExpr *node, deparse_expr_cxt *context);
142 static void deparseOpExpr(OpExpr *node, deparse_expr_cxt *context);
143 static void deparseOperatorName(StringInfo buf, Form_pg_operator opform);
144 static void deparseDistinctExpr(DistinctExpr *node, deparse_expr_cxt *context);
145 static void deparseScalarArrayOpExpr(ScalarArrayOpExpr *node,
146 						 deparse_expr_cxt *context);
147 static void deparseRelabelType(RelabelType *node, deparse_expr_cxt *context);
148 static void deparseBoolExpr(BoolExpr *node, deparse_expr_cxt *context);
149 static void deparseNullTest(NullTest *node, deparse_expr_cxt *context);
150 static void deparseArrayExpr(ArrayExpr *node, deparse_expr_cxt *context);
151 static void printRemoteParam(int paramindex, Oid paramtype, int32 paramtypmod,
152 				 deparse_expr_cxt *context);
153 static void printRemotePlaceholder(Oid paramtype, int32 paramtypmod,
154 					   deparse_expr_cxt *context);
155 static void deparseSelectSql(List *tlist, List **retrieved_attrs,
156 				 deparse_expr_cxt *context);
157 static void deparseLockingClause(deparse_expr_cxt *context);
158 static void appendOrderByClause(List *pathkeys, deparse_expr_cxt *context);
159 static void appendConditions(List *exprs, deparse_expr_cxt *context);
160 static void deparseFromExprForRel(StringInfo buf, PlannerInfo *root,
161 					RelOptInfo *joinrel, bool use_alias, List **params_list);
162 
163 
164 /*
165  * Examine each qual clause in input_conds, and classify them into two groups,
166  * which are returned as two lists:
167  *	- remote_conds contains expressions that can be evaluated remotely
168  *	- local_conds contains expressions that can't be evaluated remotely
169  */
170 void
classifyConditions(PlannerInfo * root,RelOptInfo * baserel,List * input_conds,List ** remote_conds,List ** local_conds)171 classifyConditions(PlannerInfo *root,
172 				   RelOptInfo *baserel,
173 				   List *input_conds,
174 				   List **remote_conds,
175 				   List **local_conds)
176 {
177 	ListCell   *lc;
178 
179 	*remote_conds = NIL;
180 	*local_conds = NIL;
181 
182 	foreach(lc, input_conds)
183 	{
184 		RestrictInfo *ri = (RestrictInfo *) lfirst(lc);
185 
186 		if (is_foreign_expr(root, baserel, ri->clause))
187 			*remote_conds = lappend(*remote_conds, ri);
188 		else
189 			*local_conds = lappend(*local_conds, ri);
190 	}
191 }
192 
193 /*
194  * Returns true if given expr is safe to evaluate on the foreign server.
195  */
196 bool
is_foreign_expr(PlannerInfo * root,RelOptInfo * baserel,Expr * expr)197 is_foreign_expr(PlannerInfo *root,
198 				RelOptInfo *baserel,
199 				Expr *expr)
200 {
201 	foreign_glob_cxt glob_cxt;
202 	foreign_loc_cxt loc_cxt;
203 
204 	/*
205 	 * Check that the expression consists of nodes that are safe to execute
206 	 * remotely.
207 	 */
208 	glob_cxt.root = root;
209 	glob_cxt.foreignrel = baserel;
210 	loc_cxt.collation = InvalidOid;
211 	loc_cxt.state = FDW_COLLATE_NONE;
212 	if (!foreign_expr_walker((Node *) expr, &glob_cxt, &loc_cxt))
213 		return false;
214 
215 	/*
216 	 * If the expression has a valid collation that does not arise from a
217 	 * foreign var, the expression can not be sent over.
218 	 */
219 	if (loc_cxt.state == FDW_COLLATE_UNSAFE)
220 		return false;
221 
222 	/*
223 	 * An expression which includes any mutable functions can't be sent over
224 	 * because its result is not stable.  For example, sending now() remote
225 	 * side could cause confusion from clock offsets.  Future versions might
226 	 * be able to make this choice with more granularity.  (We check this last
227 	 * because it requires a lot of expensive catalog lookups.)
228 	 */
229 	if (contain_mutable_functions((Node *) expr))
230 		return false;
231 
232 	/* OK to evaluate on the remote server */
233 	return true;
234 }
235 
236 /*
237  * Check if expression is safe to execute remotely, and return true if so.
238  *
239  * In addition, *outer_cxt is updated with collation information.
240  *
241  * We must check that the expression contains only node types we can deparse,
242  * that all types/functions/operators are safe to send (they are "shippable"),
243  * and that all collations used in the expression derive from Vars of the
244  * foreign table.  Because of the latter, the logic is pretty close to
245  * assign_collations_walker() in parse_collate.c, though we can assume here
246  * that the given expression is valid.  Note function mutability is not
247  * currently considered here.
248  */
249 static bool
foreign_expr_walker(Node * node,foreign_glob_cxt * glob_cxt,foreign_loc_cxt * outer_cxt)250 foreign_expr_walker(Node *node,
251 					foreign_glob_cxt *glob_cxt,
252 					foreign_loc_cxt *outer_cxt)
253 {
254 	bool		check_type = true;
255 	PgFdwRelationInfo *fpinfo;
256 	foreign_loc_cxt inner_cxt;
257 	Oid			collation;
258 	FDWCollateState state;
259 
260 	/* Need do nothing for empty subexpressions */
261 	if (node == NULL)
262 		return true;
263 
264 	/* May need server info from baserel's fdw_private struct */
265 	fpinfo = (PgFdwRelationInfo *) (glob_cxt->foreignrel->fdw_private);
266 
267 	/* Set up inner_cxt for possible recursion to child nodes */
268 	inner_cxt.collation = InvalidOid;
269 	inner_cxt.state = FDW_COLLATE_NONE;
270 
271 	switch (nodeTag(node))
272 	{
273 		case T_Var:
274 			{
275 				Var		   *var = (Var *) node;
276 
277 				/*
278 				 * If the Var is from the foreign table, we consider its
279 				 * collation (if any) safe to use.  If it is from another
280 				 * table, we treat its collation the same way as we would a
281 				 * Param's collation, ie it's not safe for it to have a
282 				 * non-default collation.
283 				 */
284 				if (bms_is_member(var->varno, glob_cxt->foreignrel->relids) &&
285 					var->varlevelsup == 0)
286 				{
287 					/* Var belongs to foreign table */
288 
289 					/*
290 					 * System columns other than ctid should not be sent to
291 					 * the remote, since we don't make any effort to ensure
292 					 * that local and remote values match (tableoid, in
293 					 * particular, almost certainly doesn't match).
294 					 */
295 					if (var->varattno < 0 &&
296 						var->varattno != SelfItemPointerAttributeNumber)
297 						return false;
298 
299 					/* Else check the collation */
300 					collation = var->varcollid;
301 					state = OidIsValid(collation) ? FDW_COLLATE_SAFE : FDW_COLLATE_NONE;
302 				}
303 				else
304 				{
305 					/* Var belongs to some other table */
306 					collation = var->varcollid;
307 					if (collation == InvalidOid ||
308 						collation == DEFAULT_COLLATION_OID)
309 					{
310 						/*
311 						 * It's noncollatable, or it's safe to combine with a
312 						 * collatable foreign Var, so set state to NONE.
313 						 */
314 						state = FDW_COLLATE_NONE;
315 					}
316 					else
317 					{
318 						/*
319 						 * Do not fail right away, since the Var might appear
320 						 * in a collation-insensitive context.
321 						 */
322 						state = FDW_COLLATE_UNSAFE;
323 					}
324 				}
325 			}
326 			break;
327 		case T_Const:
328 			{
329 				Const	   *c = (Const *) node;
330 
331 				/*
332 				 * If the constant has nondefault collation, either it's of a
333 				 * non-builtin type, or it reflects folding of a CollateExpr.
334 				 * It's unsafe to send to the remote unless it's used in a
335 				 * non-collation-sensitive context.
336 				 */
337 				collation = c->constcollid;
338 				if (collation == InvalidOid ||
339 					collation == DEFAULT_COLLATION_OID)
340 					state = FDW_COLLATE_NONE;
341 				else
342 					state = FDW_COLLATE_UNSAFE;
343 			}
344 			break;
345 		case T_Param:
346 			{
347 				Param	   *p = (Param *) node;
348 
349 				/*
350 				 * If it's a MULTIEXPR Param, punt.  We can't tell from here
351 				 * whether the referenced sublink/subplan contains any remote
352 				 * Vars; if it does, handling that is too complicated to
353 				 * consider supporting at present.  Fortunately, MULTIEXPR
354 				 * Params are not reduced to plain PARAM_EXEC until the end of
355 				 * planning, so we can easily detect this case.  (Normal
356 				 * PARAM_EXEC Params are safe to ship because their values
357 				 * come from somewhere else in the plan tree; but a MULTIEXPR
358 				 * references a sub-select elsewhere in the same targetlist,
359 				 * so we'd be on the hook to evaluate it somehow if we wanted
360 				 * to handle such cases as direct foreign updates.)
361 				 */
362 				if (p->paramkind == PARAM_MULTIEXPR)
363 					return false;
364 
365 				/*
366 				 * Collation rule is same as for Consts and non-foreign Vars.
367 				 */
368 				collation = p->paramcollid;
369 				if (collation == InvalidOid ||
370 					collation == DEFAULT_COLLATION_OID)
371 					state = FDW_COLLATE_NONE;
372 				else
373 					state = FDW_COLLATE_UNSAFE;
374 			}
375 			break;
376 		case T_ArrayRef:
377 			{
378 				ArrayRef   *ar = (ArrayRef *) node;
379 
380 				/* Assignment should not be in restrictions. */
381 				if (ar->refassgnexpr != NULL)
382 					return false;
383 
384 				/*
385 				 * Recurse to remaining subexpressions.  Since the array
386 				 * subscripts must yield (noncollatable) integers, they won't
387 				 * affect the inner_cxt state.
388 				 */
389 				if (!foreign_expr_walker((Node *) ar->refupperindexpr,
390 										 glob_cxt, &inner_cxt))
391 					return false;
392 				if (!foreign_expr_walker((Node *) ar->reflowerindexpr,
393 										 glob_cxt, &inner_cxt))
394 					return false;
395 				if (!foreign_expr_walker((Node *) ar->refexpr,
396 										 glob_cxt, &inner_cxt))
397 					return false;
398 
399 				/*
400 				 * Array subscripting should yield same collation as input,
401 				 * but for safety use same logic as for function nodes.
402 				 */
403 				collation = ar->refcollid;
404 				if (collation == InvalidOid)
405 					state = FDW_COLLATE_NONE;
406 				else if (inner_cxt.state == FDW_COLLATE_SAFE &&
407 						 collation == inner_cxt.collation)
408 					state = FDW_COLLATE_SAFE;
409 				else if (collation == DEFAULT_COLLATION_OID)
410 					state = FDW_COLLATE_NONE;
411 				else
412 					state = FDW_COLLATE_UNSAFE;
413 			}
414 			break;
415 		case T_FuncExpr:
416 			{
417 				FuncExpr   *fe = (FuncExpr *) node;
418 
419 				/*
420 				 * If function used by the expression is not shippable, it
421 				 * can't be sent to remote because it might have incompatible
422 				 * semantics on remote side.
423 				 */
424 				if (!is_shippable(fe->funcid, ProcedureRelationId, fpinfo))
425 					return false;
426 
427 				/*
428 				 * Recurse to input subexpressions.
429 				 */
430 				if (!foreign_expr_walker((Node *) fe->args,
431 										 glob_cxt, &inner_cxt))
432 					return false;
433 
434 				/*
435 				 * If function's input collation is not derived from a foreign
436 				 * Var, it can't be sent to remote.
437 				 */
438 				if (fe->inputcollid == InvalidOid)
439 					 /* OK, inputs are all noncollatable */ ;
440 				else if (inner_cxt.state != FDW_COLLATE_SAFE ||
441 						 fe->inputcollid != inner_cxt.collation)
442 					return false;
443 
444 				/*
445 				 * Detect whether node is introducing a collation not derived
446 				 * from a foreign Var.  (If so, we just mark it unsafe for now
447 				 * rather than immediately returning false, since the parent
448 				 * node might not care.)
449 				 */
450 				collation = fe->funccollid;
451 				if (collation == InvalidOid)
452 					state = FDW_COLLATE_NONE;
453 				else if (inner_cxt.state == FDW_COLLATE_SAFE &&
454 						 collation == inner_cxt.collation)
455 					state = FDW_COLLATE_SAFE;
456 				else if (collation == DEFAULT_COLLATION_OID)
457 					state = FDW_COLLATE_NONE;
458 				else
459 					state = FDW_COLLATE_UNSAFE;
460 			}
461 			break;
462 		case T_OpExpr:
463 		case T_DistinctExpr:	/* struct-equivalent to OpExpr */
464 			{
465 				OpExpr	   *oe = (OpExpr *) node;
466 
467 				/*
468 				 * Similarly, only shippable operators can be sent to remote.
469 				 * (If the operator is shippable, we assume its underlying
470 				 * function is too.)
471 				 */
472 				if (!is_shippable(oe->opno, OperatorRelationId, fpinfo))
473 					return false;
474 
475 				/*
476 				 * Recurse to input subexpressions.
477 				 */
478 				if (!foreign_expr_walker((Node *) oe->args,
479 										 glob_cxt, &inner_cxt))
480 					return false;
481 
482 				/*
483 				 * If operator's input collation is not derived from a foreign
484 				 * Var, it can't be sent to remote.
485 				 */
486 				if (oe->inputcollid == InvalidOid)
487 					 /* OK, inputs are all noncollatable */ ;
488 				else if (inner_cxt.state != FDW_COLLATE_SAFE ||
489 						 oe->inputcollid != inner_cxt.collation)
490 					return false;
491 
492 				/* Result-collation handling is same as for functions */
493 				collation = oe->opcollid;
494 				if (collation == InvalidOid)
495 					state = FDW_COLLATE_NONE;
496 				else if (inner_cxt.state == FDW_COLLATE_SAFE &&
497 						 collation == inner_cxt.collation)
498 					state = FDW_COLLATE_SAFE;
499 				else if (collation == DEFAULT_COLLATION_OID)
500 					state = FDW_COLLATE_NONE;
501 				else
502 					state = FDW_COLLATE_UNSAFE;
503 			}
504 			break;
505 		case T_ScalarArrayOpExpr:
506 			{
507 				ScalarArrayOpExpr *oe = (ScalarArrayOpExpr *) node;
508 
509 				/*
510 				 * Again, only shippable operators can be sent to remote.
511 				 */
512 				if (!is_shippable(oe->opno, OperatorRelationId, fpinfo))
513 					return false;
514 
515 				/*
516 				 * Recurse to input subexpressions.
517 				 */
518 				if (!foreign_expr_walker((Node *) oe->args,
519 										 glob_cxt, &inner_cxt))
520 					return false;
521 
522 				/*
523 				 * If operator's input collation is not derived from a foreign
524 				 * Var, it can't be sent to remote.
525 				 */
526 				if (oe->inputcollid == InvalidOid)
527 					 /* OK, inputs are all noncollatable */ ;
528 				else if (inner_cxt.state != FDW_COLLATE_SAFE ||
529 						 oe->inputcollid != inner_cxt.collation)
530 					return false;
531 
532 				/* Output is always boolean and so noncollatable. */
533 				collation = InvalidOid;
534 				state = FDW_COLLATE_NONE;
535 			}
536 			break;
537 		case T_RelabelType:
538 			{
539 				RelabelType *r = (RelabelType *) node;
540 
541 				/*
542 				 * Recurse to input subexpression.
543 				 */
544 				if (!foreign_expr_walker((Node *) r->arg,
545 										 glob_cxt, &inner_cxt))
546 					return false;
547 
548 				/*
549 				 * RelabelType must not introduce a collation not derived from
550 				 * an input foreign Var (same logic as for a real function).
551 				 */
552 				collation = r->resultcollid;
553 				if (collation == InvalidOid)
554 					state = FDW_COLLATE_NONE;
555 				else if (inner_cxt.state == FDW_COLLATE_SAFE &&
556 						 collation == inner_cxt.collation)
557 					state = FDW_COLLATE_SAFE;
558 				else if (collation == DEFAULT_COLLATION_OID)
559 					state = FDW_COLLATE_NONE;
560 				else
561 					state = FDW_COLLATE_UNSAFE;
562 			}
563 			break;
564 		case T_BoolExpr:
565 			{
566 				BoolExpr   *b = (BoolExpr *) node;
567 
568 				/*
569 				 * Recurse to input subexpressions.
570 				 */
571 				if (!foreign_expr_walker((Node *) b->args,
572 										 glob_cxt, &inner_cxt))
573 					return false;
574 
575 				/* Output is always boolean and so noncollatable. */
576 				collation = InvalidOid;
577 				state = FDW_COLLATE_NONE;
578 			}
579 			break;
580 		case T_NullTest:
581 			{
582 				NullTest   *nt = (NullTest *) node;
583 
584 				/*
585 				 * Recurse to input subexpressions.
586 				 */
587 				if (!foreign_expr_walker((Node *) nt->arg,
588 										 glob_cxt, &inner_cxt))
589 					return false;
590 
591 				/* Output is always boolean and so noncollatable. */
592 				collation = InvalidOid;
593 				state = FDW_COLLATE_NONE;
594 			}
595 			break;
596 		case T_ArrayExpr:
597 			{
598 				ArrayExpr  *a = (ArrayExpr *) node;
599 
600 				/*
601 				 * Recurse to input subexpressions.
602 				 */
603 				if (!foreign_expr_walker((Node *) a->elements,
604 										 glob_cxt, &inner_cxt))
605 					return false;
606 
607 				/*
608 				 * ArrayExpr must not introduce a collation not derived from
609 				 * an input foreign Var (same logic as for a function).
610 				 */
611 				collation = a->array_collid;
612 				if (collation == InvalidOid)
613 					state = FDW_COLLATE_NONE;
614 				else if (inner_cxt.state == FDW_COLLATE_SAFE &&
615 						 collation == inner_cxt.collation)
616 					state = FDW_COLLATE_SAFE;
617 				else if (collation == DEFAULT_COLLATION_OID)
618 					state = FDW_COLLATE_NONE;
619 				else
620 					state = FDW_COLLATE_UNSAFE;
621 			}
622 			break;
623 		case T_List:
624 			{
625 				List	   *l = (List *) node;
626 				ListCell   *lc;
627 
628 				/*
629 				 * Recurse to component subexpressions.
630 				 */
631 				foreach(lc, l)
632 				{
633 					if (!foreign_expr_walker((Node *) lfirst(lc),
634 											 glob_cxt, &inner_cxt))
635 						return false;
636 				}
637 
638 				/*
639 				 * When processing a list, collation state just bubbles up
640 				 * from the list elements.
641 				 */
642 				collation = inner_cxt.collation;
643 				state = inner_cxt.state;
644 
645 				/* Don't apply exprType() to the list. */
646 				check_type = false;
647 			}
648 			break;
649 		default:
650 
651 			/*
652 			 * If it's anything else, assume it's unsafe.  This list can be
653 			 * expanded later, but don't forget to add deparse support below.
654 			 */
655 			return false;
656 	}
657 
658 	/*
659 	 * If result type of given expression is not shippable, it can't be sent
660 	 * to remote because it might have incompatible semantics on remote side.
661 	 */
662 	if (check_type && !is_shippable(exprType(node), TypeRelationId, fpinfo))
663 		return false;
664 
665 	/*
666 	 * Now, merge my collation information into my parent's state.
667 	 */
668 	if (state > outer_cxt->state)
669 	{
670 		/* Override previous parent state */
671 		outer_cxt->collation = collation;
672 		outer_cxt->state = state;
673 	}
674 	else if (state == outer_cxt->state)
675 	{
676 		/* Merge, or detect error if there's a collation conflict */
677 		switch (state)
678 		{
679 			case FDW_COLLATE_NONE:
680 				/* Nothing + nothing is still nothing */
681 				break;
682 			case FDW_COLLATE_SAFE:
683 				if (collation != outer_cxt->collation)
684 				{
685 					/*
686 					 * Non-default collation always beats default.
687 					 */
688 					if (outer_cxt->collation == DEFAULT_COLLATION_OID)
689 					{
690 						/* Override previous parent state */
691 						outer_cxt->collation = collation;
692 					}
693 					else if (collation != DEFAULT_COLLATION_OID)
694 					{
695 						/*
696 						 * Conflict; show state as indeterminate.  We don't
697 						 * want to "return false" right away, since parent
698 						 * node might not care about collation.
699 						 */
700 						outer_cxt->state = FDW_COLLATE_UNSAFE;
701 					}
702 				}
703 				break;
704 			case FDW_COLLATE_UNSAFE:
705 				/* We're still conflicted ... */
706 				break;
707 		}
708 	}
709 
710 	/* It looks OK */
711 	return true;
712 }
713 
714 /*
715  * Convert type OID + typmod info into a type name we can ship to the remote
716  * server.  Someplace else had better have verified that this type name is
717  * expected to be known on the remote end.
718  *
719  * This is almost just format_type_with_typemod(), except that if left to its
720  * own devices, that function will make schema-qualification decisions based
721  * on the local search_path, which is wrong.  We must schema-qualify all
722  * type names that are not in pg_catalog.  We assume here that built-in types
723  * are all in pg_catalog and need not be qualified; otherwise, qualify.
724  */
725 static char *
deparse_type_name(Oid type_oid,int32 typemod)726 deparse_type_name(Oid type_oid, int32 typemod)
727 {
728 	if (is_builtin(type_oid))
729 		return format_type_with_typemod(type_oid, typemod);
730 	else
731 		return format_type_with_typemod_qualified(type_oid, typemod);
732 }
733 
734 /*
735  * Build the targetlist for given relation to be deparsed as SELECT clause.
736  *
737  * The output targetlist contains the columns that need to be fetched from the
738  * foreign server for the given relation.
739  */
740 List *
build_tlist_to_deparse(RelOptInfo * foreignrel)741 build_tlist_to_deparse(RelOptInfo *foreignrel)
742 {
743 	List	   *tlist = NIL;
744 	PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
745 
746 	/*
747 	 * We require columns specified in foreignrel->reltarget->exprs and those
748 	 * required for evaluating the local conditions.
749 	 */
750 	tlist = add_to_flat_tlist(tlist,
751 					   pull_var_clause((Node *) foreignrel->reltarget->exprs,
752 									   PVC_RECURSE_PLACEHOLDERS));
753 	tlist = add_to_flat_tlist(tlist,
754 							  pull_var_clause((Node *) fpinfo->local_conds,
755 											  PVC_RECURSE_PLACEHOLDERS));
756 
757 	return tlist;
758 }
759 
760 /*
761  * Deparse SELECT statement for given relation into buf.
762  *
763  * tlist contains the list of desired columns to be fetched from foreign server.
764  * For a base relation fpinfo->attrs_used is used to construct SELECT clause,
765  * hence the tlist is ignored for a base relation.
766  *
767  * remote_conds is the list of conditions to be deparsed as WHERE clause.
768  *
769  * If params_list is not NULL, it receives a list of Params and other-relation
770  * Vars used in the clauses; these values must be transmitted to the remote
771  * server as parameter values.
772  *
773  * If params_list is NULL, we're generating the query for EXPLAIN purposes,
774  * so Params and other-relation Vars should be replaced by dummy values.
775  *
776  * pathkeys is the list of pathkeys to order the result by.
777  *
778  * List of columns selected is returned in retrieved_attrs.
779  */
780 extern void
deparseSelectStmtForRel(StringInfo buf,PlannerInfo * root,RelOptInfo * rel,List * tlist,List * remote_conds,List * pathkeys,List ** retrieved_attrs,List ** params_list)781 deparseSelectStmtForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *rel,
782 						List *tlist, List *remote_conds, List *pathkeys,
783 						List **retrieved_attrs, List **params_list)
784 {
785 	deparse_expr_cxt context;
786 
787 	/* We handle relations for foreign tables and joins between those */
788 	Assert(rel->reloptkind == RELOPT_JOINREL ||
789 		   rel->reloptkind == RELOPT_BASEREL ||
790 		   rel->reloptkind == RELOPT_OTHER_MEMBER_REL);
791 
792 	/* Fill portions of context common to join and base relation */
793 	context.buf = buf;
794 	context.root = root;
795 	context.foreignrel = rel;
796 	context.params_list = params_list;
797 
798 	/* Construct SELECT clause and FROM clause */
799 	deparseSelectSql(tlist, retrieved_attrs, &context);
800 
801 	/*
802 	 * Construct WHERE clause
803 	 */
804 	if (remote_conds)
805 	{
806 		appendStringInfo(buf, " WHERE ");
807 		appendConditions(remote_conds, &context);
808 	}
809 
810 	/* Add ORDER BY clause if we found any useful pathkeys */
811 	if (pathkeys)
812 		appendOrderByClause(pathkeys, &context);
813 
814 	/* Add any necessary FOR UPDATE/SHARE. */
815 	deparseLockingClause(&context);
816 }
817 
818 /*
819  * Construct a simple SELECT statement that retrieves desired columns
820  * of the specified foreign table, and append it to "buf".  The output
821  * contains just "SELECT ... FROM ....".
822  *
823  * We also create an integer List of the columns being retrieved, which is
824  * returned to *retrieved_attrs.
825  *
826  * tlist is the list of desired columns. Read prologue of
827  * deparseSelectStmtForRel() for details.
828  */
829 static void
deparseSelectSql(List * tlist,List ** retrieved_attrs,deparse_expr_cxt * context)830 deparseSelectSql(List *tlist, List **retrieved_attrs, deparse_expr_cxt *context)
831 {
832 	StringInfo	buf = context->buf;
833 	RelOptInfo *foreignrel = context->foreignrel;
834 	PlannerInfo *root = context->root;
835 	PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
836 
837 	/*
838 	 * Construct SELECT list
839 	 */
840 	appendStringInfoString(buf, "SELECT ");
841 
842 	if (foreignrel->reloptkind == RELOPT_JOINREL)
843 	{
844 		/* For a join relation use the input tlist */
845 		deparseExplicitTargetList(tlist, retrieved_attrs, context);
846 	}
847 	else
848 	{
849 		/*
850 		 * For a base relation fpinfo->attrs_used gives the list of columns
851 		 * required to be fetched from the foreign server.
852 		 */
853 		RangeTblEntry *rte = planner_rt_fetch(foreignrel->relid, root);
854 
855 		/*
856 		 * Core code already has some lock on each rel being planned, so we
857 		 * can use NoLock here.
858 		 */
859 		Relation	rel = heap_open(rte->relid, NoLock);
860 
861 		deparseTargetList(buf, root, foreignrel->relid, rel, false,
862 						  fpinfo->attrs_used, false, retrieved_attrs);
863 		heap_close(rel, NoLock);
864 	}
865 
866 	/*
867 	 * Construct FROM clause
868 	 */
869 	appendStringInfoString(buf, " FROM ");
870 	deparseFromExprForRel(buf, root, foreignrel,
871 						  (foreignrel->reloptkind == RELOPT_JOINREL),
872 						  context->params_list);
873 }
874 
875 /*
876  * Emit a target list that retrieves the columns specified in attrs_used.
877  * This is used for both SELECT and RETURNING targetlists; the is_returning
878  * parameter is true only for a RETURNING targetlist.
879  *
880  * The tlist text is appended to buf, and we also create an integer List
881  * of the columns being retrieved, which is returned to *retrieved_attrs.
882  *
883  * If qualify_col is true, add relation alias before the column name.
884  */
885 static void
deparseTargetList(StringInfo buf,PlannerInfo * root,Index rtindex,Relation rel,bool is_returning,Bitmapset * attrs_used,bool qualify_col,List ** retrieved_attrs)886 deparseTargetList(StringInfo buf,
887 				  PlannerInfo *root,
888 				  Index rtindex,
889 				  Relation rel,
890 				  bool is_returning,
891 				  Bitmapset *attrs_used,
892 				  bool qualify_col,
893 				  List **retrieved_attrs)
894 {
895 	TupleDesc	tupdesc = RelationGetDescr(rel);
896 	bool		have_wholerow;
897 	bool		first;
898 	int			i;
899 
900 	*retrieved_attrs = NIL;
901 
902 	/* If there's a whole-row reference, we'll need all the columns. */
903 	have_wholerow = bms_is_member(0 - FirstLowInvalidHeapAttributeNumber,
904 								  attrs_used);
905 
906 	first = true;
907 	for (i = 1; i <= tupdesc->natts; i++)
908 	{
909 		Form_pg_attribute attr = tupdesc->attrs[i - 1];
910 
911 		/* Ignore dropped attributes. */
912 		if (attr->attisdropped)
913 			continue;
914 
915 		if (have_wholerow ||
916 			bms_is_member(i - FirstLowInvalidHeapAttributeNumber,
917 						  attrs_used))
918 		{
919 			if (!first)
920 				appendStringInfoString(buf, ", ");
921 			else if (is_returning)
922 				appendStringInfoString(buf, " RETURNING ");
923 			first = false;
924 
925 			deparseColumnRef(buf, rtindex, i, root, qualify_col);
926 
927 			*retrieved_attrs = lappend_int(*retrieved_attrs, i);
928 		}
929 	}
930 
931 	/*
932 	 * Add ctid if needed.  We currently don't support retrieving any other
933 	 * system columns.
934 	 */
935 	if (bms_is_member(SelfItemPointerAttributeNumber - FirstLowInvalidHeapAttributeNumber,
936 					  attrs_used))
937 	{
938 		if (!first)
939 			appendStringInfoString(buf, ", ");
940 		else if (is_returning)
941 			appendStringInfoString(buf, " RETURNING ");
942 		first = false;
943 
944 		if (qualify_col)
945 			ADD_REL_QUALIFIER(buf, rtindex);
946 		appendStringInfoString(buf, "ctid");
947 
948 		*retrieved_attrs = lappend_int(*retrieved_attrs,
949 									   SelfItemPointerAttributeNumber);
950 	}
951 
952 	/* Don't generate bad syntax if no undropped columns */
953 	if (first && !is_returning)
954 		appendStringInfoString(buf, "NULL");
955 }
956 
957 /*
958  * Deparse the appropriate locking clause (FOR SELECT or FOR SHARE) for a
959  * given relation (context->foreignrel).
960  */
961 static void
deparseLockingClause(deparse_expr_cxt * context)962 deparseLockingClause(deparse_expr_cxt *context)
963 {
964 	StringInfo	buf = context->buf;
965 	PlannerInfo *root = context->root;
966 	RelOptInfo *rel = context->foreignrel;
967 	int			relid = -1;
968 
969 	while ((relid = bms_next_member(rel->relids, relid)) >= 0)
970 	{
971 		/*
972 		 * Add FOR UPDATE/SHARE if appropriate.  We apply locking during the
973 		 * initial row fetch, rather than later on as is done for local
974 		 * tables. The extra roundtrips involved in trying to duplicate the
975 		 * local semantics exactly don't seem worthwhile (see also comments
976 		 * for RowMarkType).
977 		 *
978 		 * Note: because we actually run the query as a cursor, this assumes
979 		 * that DECLARE CURSOR ... FOR UPDATE is supported, which it isn't
980 		 * before 8.3.
981 		 */
982 		if (relid == root->parse->resultRelation &&
983 			(root->parse->commandType == CMD_UPDATE ||
984 			 root->parse->commandType == CMD_DELETE))
985 		{
986 			/* Relation is UPDATE/DELETE target, so use FOR UPDATE */
987 			appendStringInfoString(buf, " FOR UPDATE");
988 
989 			/* Add the relation alias if we are here for a join relation */
990 			if (rel->reloptkind == RELOPT_JOINREL)
991 				appendStringInfo(buf, " OF %s%d", REL_ALIAS_PREFIX, relid);
992 		}
993 		else
994 		{
995 			PlanRowMark *rc = get_plan_rowmark(root->rowMarks, relid);
996 
997 			if (rc)
998 			{
999 				/*
1000 				 * Relation is specified as a FOR UPDATE/SHARE target, so
1001 				 * handle that.  (But we could also see LCS_NONE, meaning this
1002 				 * isn't a target relation after all.)
1003 				 *
1004 				 * For now, just ignore any [NO] KEY specification, since (a)
1005 				 * it's not clear what that means for a remote table that we
1006 				 * don't have complete information about, and (b) it wouldn't
1007 				 * work anyway on older remote servers.  Likewise, we don't
1008 				 * worry about NOWAIT.
1009 				 */
1010 				switch (rc->strength)
1011 				{
1012 					case LCS_NONE:
1013 						/* No locking needed */
1014 						break;
1015 					case LCS_FORKEYSHARE:
1016 					case LCS_FORSHARE:
1017 						appendStringInfoString(buf, " FOR SHARE");
1018 						break;
1019 					case LCS_FORNOKEYUPDATE:
1020 					case LCS_FORUPDATE:
1021 						appendStringInfoString(buf, " FOR UPDATE");
1022 						break;
1023 				}
1024 
1025 				/* Add the relation alias if we are here for a join relation */
1026 				if (rel->reloptkind == RELOPT_JOINREL &&
1027 					rc->strength != LCS_NONE)
1028 					appendStringInfo(buf, " OF %s%d", REL_ALIAS_PREFIX, relid);
1029 			}
1030 		}
1031 	}
1032 }
1033 
1034 /*
1035  * Deparse conditions from the provided list and append them to buf.
1036  *
1037  * The conditions in the list are assumed to be ANDed. This function is used to
1038  * deparse both WHERE clauses and JOIN .. ON clauses.
1039  */
1040 static void
appendConditions(List * exprs,deparse_expr_cxt * context)1041 appendConditions(List *exprs, deparse_expr_cxt *context)
1042 {
1043 	int			nestlevel;
1044 	ListCell   *lc;
1045 	bool		is_first = true;
1046 	StringInfo	buf = context->buf;
1047 
1048 	/* Make sure any constants in the exprs are printed portably */
1049 	nestlevel = set_transmission_modes();
1050 
1051 	foreach(lc, exprs)
1052 	{
1053 		Expr	   *expr = (Expr *) lfirst(lc);
1054 
1055 		/*
1056 		 * Extract clause from RestrictInfo, if required. See comments in
1057 		 * declaration of PgFdwRelationInfo for details.
1058 		 */
1059 		if (IsA(expr, RestrictInfo))
1060 		{
1061 			RestrictInfo *ri = (RestrictInfo *) expr;
1062 
1063 			expr = ri->clause;
1064 		}
1065 
1066 		/* Connect expressions with "AND" and parenthesize each condition. */
1067 		if (!is_first)
1068 			appendStringInfoString(buf, " AND ");
1069 
1070 		appendStringInfoChar(buf, '(');
1071 		deparseExpr(expr, context);
1072 		appendStringInfoChar(buf, ')');
1073 
1074 		is_first = false;
1075 	}
1076 
1077 	reset_transmission_modes(nestlevel);
1078 }
1079 
1080 /* Output join name for given join type */
1081 extern const char *
get_jointype_name(JoinType jointype)1082 get_jointype_name(JoinType jointype)
1083 {
1084 	switch (jointype)
1085 	{
1086 		case JOIN_INNER:
1087 			return "INNER";
1088 
1089 		case JOIN_LEFT:
1090 			return "LEFT";
1091 
1092 		case JOIN_RIGHT:
1093 			return "RIGHT";
1094 
1095 		case JOIN_FULL:
1096 			return "FULL";
1097 
1098 		default:
1099 			/* Shouldn't come here, but protect from buggy code. */
1100 			elog(ERROR, "unsupported join type %d", jointype);
1101 	}
1102 
1103 	/* Keep compiler happy */
1104 	return NULL;
1105 }
1106 
1107 /*
1108  * Deparse given targetlist and append it to context->buf.
1109  *
1110  * tlist is list of TargetEntry's which in turn contain Var nodes.
1111  *
1112  * retrieved_attrs is the list of continuously increasing integers starting
1113  * from 1. It has same number of entries as tlist.
1114  */
1115 static void
deparseExplicitTargetList(List * tlist,List ** retrieved_attrs,deparse_expr_cxt * context)1116 deparseExplicitTargetList(List *tlist, List **retrieved_attrs,
1117 						  deparse_expr_cxt *context)
1118 {
1119 	ListCell   *lc;
1120 	StringInfo	buf = context->buf;
1121 	int			i = 0;
1122 
1123 	*retrieved_attrs = NIL;
1124 
1125 	foreach(lc, tlist)
1126 	{
1127 		TargetEntry *tle = (TargetEntry *) lfirst(lc);
1128 		Var		   *var;
1129 
1130 		/* Extract expression if TargetEntry node */
1131 		Assert(IsA(tle, TargetEntry));
1132 		var = (Var *) tle->expr;
1133 
1134 		/* We expect only Var nodes here */
1135 		if (!IsA(var, Var))
1136 			elog(ERROR, "non-Var not expected in target list");
1137 
1138 		if (i > 0)
1139 			appendStringInfoString(buf, ", ");
1140 		deparseVar(var, context);
1141 
1142 		*retrieved_attrs = lappend_int(*retrieved_attrs, i + 1);
1143 
1144 		i++;
1145 	}
1146 
1147 	if (i == 0)
1148 		appendStringInfoString(buf, "NULL");
1149 }
1150 
1151 /*
1152  * Construct FROM clause for given relation
1153  *
1154  * The function constructs ... JOIN ... ON ... for join relation. For a base
1155  * relation it just returns schema-qualified tablename, with the appropriate
1156  * alias if so requested.
1157  */
1158 static void
deparseFromExprForRel(StringInfo buf,PlannerInfo * root,RelOptInfo * foreignrel,bool use_alias,List ** params_list)1159 deparseFromExprForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel,
1160 					  bool use_alias, List **params_list)
1161 {
1162 	PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
1163 
1164 	if (foreignrel->reloptkind == RELOPT_JOINREL)
1165 	{
1166 		RelOptInfo *rel_o = fpinfo->outerrel;
1167 		RelOptInfo *rel_i = fpinfo->innerrel;
1168 		StringInfoData join_sql_o;
1169 		StringInfoData join_sql_i;
1170 
1171 		/* Deparse outer relation */
1172 		initStringInfo(&join_sql_o);
1173 		deparseFromExprForRel(&join_sql_o, root, rel_o, true, params_list);
1174 
1175 		/* Deparse inner relation */
1176 		initStringInfo(&join_sql_i);
1177 		deparseFromExprForRel(&join_sql_i, root, rel_i, true, params_list);
1178 
1179 		/*
1180 		 * For a join relation FROM clause entry is deparsed as
1181 		 *
1182 		 * ((outer relation) <join type> (inner relation) ON (joinclauses)
1183 		 */
1184 		appendStringInfo(buf, "(%s %s JOIN %s ON ", join_sql_o.data,
1185 					   get_jointype_name(fpinfo->jointype), join_sql_i.data);
1186 
1187 		/* Append join clause; (TRUE) if no join clause */
1188 		if (fpinfo->joinclauses)
1189 		{
1190 			deparse_expr_cxt context;
1191 
1192 			context.buf = buf;
1193 			context.foreignrel = foreignrel;
1194 			context.root = root;
1195 			context.params_list = params_list;
1196 
1197 			appendStringInfo(buf, "(");
1198 			appendConditions(fpinfo->joinclauses, &context);
1199 			appendStringInfo(buf, ")");
1200 		}
1201 		else
1202 			appendStringInfoString(buf, "(TRUE)");
1203 
1204 		/* End the FROM clause entry. */
1205 		appendStringInfo(buf, ")");
1206 	}
1207 	else
1208 	{
1209 		RangeTblEntry *rte = planner_rt_fetch(foreignrel->relid, root);
1210 
1211 		/*
1212 		 * Core code already has some lock on each rel being planned, so we
1213 		 * can use NoLock here.
1214 		 */
1215 		Relation	rel = heap_open(rte->relid, NoLock);
1216 
1217 		deparseRelation(buf, rel);
1218 
1219 		/*
1220 		 * Add a unique alias to avoid any conflict in relation names due to
1221 		 * pulled up subqueries in the query being built for a pushed down
1222 		 * join.
1223 		 */
1224 		if (use_alias)
1225 			appendStringInfo(buf, " %s%d", REL_ALIAS_PREFIX, foreignrel->relid);
1226 
1227 		heap_close(rel, NoLock);
1228 	}
1229 }
1230 
1231 /*
1232  * deparse remote INSERT statement
1233  *
1234  * The statement text is appended to buf, and we also create an integer List
1235  * of the columns being retrieved by RETURNING (if any), which is returned
1236  * to *retrieved_attrs.
1237  */
1238 void
deparseInsertSql(StringInfo buf,PlannerInfo * root,Index rtindex,Relation rel,List * targetAttrs,bool doNothing,List * returningList,List ** retrieved_attrs)1239 deparseInsertSql(StringInfo buf, PlannerInfo *root,
1240 				 Index rtindex, Relation rel,
1241 				 List *targetAttrs, bool doNothing,
1242 				 List *returningList, List **retrieved_attrs)
1243 {
1244 	AttrNumber	pindex;
1245 	bool		first;
1246 	ListCell   *lc;
1247 
1248 	appendStringInfoString(buf, "INSERT INTO ");
1249 	deparseRelation(buf, rel);
1250 
1251 	if (targetAttrs)
1252 	{
1253 		appendStringInfoChar(buf, '(');
1254 
1255 		first = true;
1256 		foreach(lc, targetAttrs)
1257 		{
1258 			int			attnum = lfirst_int(lc);
1259 
1260 			if (!first)
1261 				appendStringInfoString(buf, ", ");
1262 			first = false;
1263 
1264 			deparseColumnRef(buf, rtindex, attnum, root, false);
1265 		}
1266 
1267 		appendStringInfoString(buf, ") VALUES (");
1268 
1269 		pindex = 1;
1270 		first = true;
1271 		foreach(lc, targetAttrs)
1272 		{
1273 			if (!first)
1274 				appendStringInfoString(buf, ", ");
1275 			first = false;
1276 
1277 			appendStringInfo(buf, "$%d", pindex);
1278 			pindex++;
1279 		}
1280 
1281 		appendStringInfoChar(buf, ')');
1282 	}
1283 	else
1284 		appendStringInfoString(buf, " DEFAULT VALUES");
1285 
1286 	if (doNothing)
1287 		appendStringInfoString(buf, " ON CONFLICT DO NOTHING");
1288 
1289 	deparseReturningList(buf, root, rtindex, rel,
1290 					   rel->trigdesc && rel->trigdesc->trig_insert_after_row,
1291 						 returningList, retrieved_attrs);
1292 }
1293 
1294 /*
1295  * deparse remote UPDATE statement
1296  *
1297  * The statement text is appended to buf, and we also create an integer List
1298  * of the columns being retrieved by RETURNING (if any), which is returned
1299  * to *retrieved_attrs.
1300  */
1301 void
deparseUpdateSql(StringInfo buf,PlannerInfo * root,Index rtindex,Relation rel,List * targetAttrs,List * returningList,List ** retrieved_attrs)1302 deparseUpdateSql(StringInfo buf, PlannerInfo *root,
1303 				 Index rtindex, Relation rel,
1304 				 List *targetAttrs, List *returningList,
1305 				 List **retrieved_attrs)
1306 {
1307 	AttrNumber	pindex;
1308 	bool		first;
1309 	ListCell   *lc;
1310 
1311 	appendStringInfoString(buf, "UPDATE ");
1312 	deparseRelation(buf, rel);
1313 	appendStringInfoString(buf, " SET ");
1314 
1315 	pindex = 2;					/* ctid is always the first param */
1316 	first = true;
1317 	foreach(lc, targetAttrs)
1318 	{
1319 		int			attnum = lfirst_int(lc);
1320 
1321 		if (!first)
1322 			appendStringInfoString(buf, ", ");
1323 		first = false;
1324 
1325 		deparseColumnRef(buf, rtindex, attnum, root, false);
1326 		appendStringInfo(buf, " = $%d", pindex);
1327 		pindex++;
1328 	}
1329 	appendStringInfoString(buf, " WHERE ctid = $1");
1330 
1331 	deparseReturningList(buf, root, rtindex, rel,
1332 					   rel->trigdesc && rel->trigdesc->trig_update_after_row,
1333 						 returningList, retrieved_attrs);
1334 }
1335 
1336 /*
1337  * deparse remote UPDATE statement
1338  *
1339  * The statement text is appended to buf, and we also create an integer List
1340  * of the columns being retrieved by RETURNING (if any), which is returned
1341  * to *retrieved_attrs.
1342  */
1343 void
deparseDirectUpdateSql(StringInfo buf,PlannerInfo * root,Index rtindex,Relation rel,List * targetlist,List * targetAttrs,List * remote_conds,List ** params_list,List * returningList,List ** retrieved_attrs)1344 deparseDirectUpdateSql(StringInfo buf, PlannerInfo *root,
1345 					   Index rtindex, Relation rel,
1346 					   List *targetlist,
1347 					   List *targetAttrs,
1348 					   List *remote_conds,
1349 					   List **params_list,
1350 					   List *returningList,
1351 					   List **retrieved_attrs)
1352 {
1353 	RelOptInfo *baserel = root->simple_rel_array[rtindex];
1354 	deparse_expr_cxt context;
1355 	int			nestlevel;
1356 	bool		first;
1357 	ListCell   *lc;
1358 
1359 	/* Set up context struct for recursion */
1360 	context.root = root;
1361 	context.foreignrel = baserel;
1362 	context.buf = buf;
1363 	context.params_list = params_list;
1364 
1365 	appendStringInfoString(buf, "UPDATE ");
1366 	deparseRelation(buf, rel);
1367 	appendStringInfoString(buf, " SET ");
1368 
1369 	/* Make sure any constants in the exprs are printed portably */
1370 	nestlevel = set_transmission_modes();
1371 
1372 	first = true;
1373 	foreach(lc, targetAttrs)
1374 	{
1375 		int			attnum = lfirst_int(lc);
1376 		TargetEntry *tle = get_tle_by_resno(targetlist, attnum);
1377 
1378 		if (!tle)
1379 			elog(ERROR, "attribute number %d not found in UPDATE targetlist",
1380 				 attnum);
1381 
1382 		if (!first)
1383 			appendStringInfoString(buf, ", ");
1384 		first = false;
1385 
1386 		deparseColumnRef(buf, rtindex, attnum, root, false);
1387 		appendStringInfoString(buf, " = ");
1388 		deparseExpr((Expr *) tle->expr, &context);
1389 	}
1390 
1391 	reset_transmission_modes(nestlevel);
1392 
1393 	if (remote_conds)
1394 	{
1395 		appendStringInfo(buf, " WHERE ");
1396 		appendConditions(remote_conds, &context);
1397 	}
1398 
1399 	deparseReturningList(buf, root, rtindex, rel, false,
1400 						 returningList, retrieved_attrs);
1401 }
1402 
1403 /*
1404  * deparse remote DELETE statement
1405  *
1406  * The statement text is appended to buf, and we also create an integer List
1407  * of the columns being retrieved by RETURNING (if any), which is returned
1408  * to *retrieved_attrs.
1409  */
1410 void
deparseDeleteSql(StringInfo buf,PlannerInfo * root,Index rtindex,Relation rel,List * returningList,List ** retrieved_attrs)1411 deparseDeleteSql(StringInfo buf, PlannerInfo *root,
1412 				 Index rtindex, Relation rel,
1413 				 List *returningList,
1414 				 List **retrieved_attrs)
1415 {
1416 	appendStringInfoString(buf, "DELETE FROM ");
1417 	deparseRelation(buf, rel);
1418 	appendStringInfoString(buf, " WHERE ctid = $1");
1419 
1420 	deparseReturningList(buf, root, rtindex, rel,
1421 					   rel->trigdesc && rel->trigdesc->trig_delete_after_row,
1422 						 returningList, retrieved_attrs);
1423 }
1424 
1425 /*
1426  * deparse remote DELETE statement
1427  *
1428  * The statement text is appended to buf, and we also create an integer List
1429  * of the columns being retrieved by RETURNING (if any), which is returned
1430  * to *retrieved_attrs.
1431  */
1432 void
deparseDirectDeleteSql(StringInfo buf,PlannerInfo * root,Index rtindex,Relation rel,List * remote_conds,List ** params_list,List * returningList,List ** retrieved_attrs)1433 deparseDirectDeleteSql(StringInfo buf, PlannerInfo *root,
1434 					   Index rtindex, Relation rel,
1435 					   List *remote_conds,
1436 					   List **params_list,
1437 					   List *returningList,
1438 					   List **retrieved_attrs)
1439 {
1440 	RelOptInfo *baserel = root->simple_rel_array[rtindex];
1441 	deparse_expr_cxt context;
1442 
1443 	/* Set up context struct for recursion */
1444 	context.root = root;
1445 	context.foreignrel = baserel;
1446 	context.buf = buf;
1447 	context.params_list = params_list;
1448 
1449 	appendStringInfoString(buf, "DELETE FROM ");
1450 	deparseRelation(buf, rel);
1451 
1452 	if (remote_conds)
1453 	{
1454 		appendStringInfo(buf, " WHERE ");
1455 		appendConditions(remote_conds, &context);
1456 	}
1457 
1458 	deparseReturningList(buf, root, rtindex, rel, false,
1459 						 returningList, retrieved_attrs);
1460 }
1461 
1462 /*
1463  * Add a RETURNING clause, if needed, to an INSERT/UPDATE/DELETE.
1464  */
1465 static void
deparseReturningList(StringInfo buf,PlannerInfo * root,Index rtindex,Relation rel,bool trig_after_row,List * returningList,List ** retrieved_attrs)1466 deparseReturningList(StringInfo buf, PlannerInfo *root,
1467 					 Index rtindex, Relation rel,
1468 					 bool trig_after_row,
1469 					 List *returningList,
1470 					 List **retrieved_attrs)
1471 {
1472 	Bitmapset  *attrs_used = NULL;
1473 
1474 	if (trig_after_row)
1475 	{
1476 		/* whole-row reference acquires all non-system columns */
1477 		attrs_used =
1478 			bms_make_singleton(0 - FirstLowInvalidHeapAttributeNumber);
1479 	}
1480 
1481 	if (returningList != NIL)
1482 	{
1483 		/*
1484 		 * We need the attrs, non-system and system, mentioned in the local
1485 		 * query's RETURNING list.
1486 		 */
1487 		pull_varattnos((Node *) returningList, rtindex,
1488 					   &attrs_used);
1489 	}
1490 
1491 	if (attrs_used != NULL)
1492 		deparseTargetList(buf, root, rtindex, rel, true, attrs_used, false,
1493 						  retrieved_attrs);
1494 	else
1495 		*retrieved_attrs = NIL;
1496 }
1497 
1498 /*
1499  * Construct SELECT statement to acquire size in blocks of given relation.
1500  *
1501  * Note: we use local definition of block size, not remote definition.
1502  * This is perhaps debatable.
1503  *
1504  * Note: pg_relation_size() exists in 8.1 and later.
1505  */
1506 void
deparseAnalyzeSizeSql(StringInfo buf,Relation rel)1507 deparseAnalyzeSizeSql(StringInfo buf, Relation rel)
1508 {
1509 	StringInfoData relname;
1510 
1511 	/* We'll need the remote relation name as a literal. */
1512 	initStringInfo(&relname);
1513 	deparseRelation(&relname, rel);
1514 
1515 	appendStringInfoString(buf, "SELECT pg_catalog.pg_relation_size(");
1516 	deparseStringLiteral(buf, relname.data);
1517 	appendStringInfo(buf, "::pg_catalog.regclass) / %d", BLCKSZ);
1518 }
1519 
1520 /*
1521  * Construct SELECT statement to acquire sample rows of given relation.
1522  *
1523  * SELECT command is appended to buf, and list of columns retrieved
1524  * is returned to *retrieved_attrs.
1525  */
1526 void
deparseAnalyzeSql(StringInfo buf,Relation rel,List ** retrieved_attrs)1527 deparseAnalyzeSql(StringInfo buf, Relation rel, List **retrieved_attrs)
1528 {
1529 	Oid			relid = RelationGetRelid(rel);
1530 	TupleDesc	tupdesc = RelationGetDescr(rel);
1531 	int			i;
1532 	char	   *colname;
1533 	List	   *options;
1534 	ListCell   *lc;
1535 	bool		first = true;
1536 
1537 	*retrieved_attrs = NIL;
1538 
1539 	appendStringInfoString(buf, "SELECT ");
1540 	for (i = 0; i < tupdesc->natts; i++)
1541 	{
1542 		/* Ignore dropped columns. */
1543 		if (tupdesc->attrs[i]->attisdropped)
1544 			continue;
1545 
1546 		if (!first)
1547 			appendStringInfoString(buf, ", ");
1548 		first = false;
1549 
1550 		/* Use attribute name or column_name option. */
1551 		colname = NameStr(tupdesc->attrs[i]->attname);
1552 		options = GetForeignColumnOptions(relid, i + 1);
1553 
1554 		foreach(lc, options)
1555 		{
1556 			DefElem    *def = (DefElem *) lfirst(lc);
1557 
1558 			if (strcmp(def->defname, "column_name") == 0)
1559 			{
1560 				colname = defGetString(def);
1561 				break;
1562 			}
1563 		}
1564 
1565 		appendStringInfoString(buf, quote_identifier(colname));
1566 
1567 		*retrieved_attrs = lappend_int(*retrieved_attrs, i + 1);
1568 	}
1569 
1570 	/* Don't generate bad syntax for zero-column relation. */
1571 	if (first)
1572 		appendStringInfoString(buf, "NULL");
1573 
1574 	/*
1575 	 * Construct FROM clause
1576 	 */
1577 	appendStringInfoString(buf, " FROM ");
1578 	deparseRelation(buf, rel);
1579 }
1580 
1581 /*
1582  * Construct name to use for given column, and emit it into buf.
1583  * If it has a column_name FDW option, use that instead of attribute name.
1584  *
1585  * If qualify_col is true, qualify column name with the alias of relation.
1586  */
1587 static void
deparseColumnRef(StringInfo buf,int varno,int varattno,PlannerInfo * root,bool qualify_col)1588 deparseColumnRef(StringInfo buf, int varno, int varattno, PlannerInfo *root,
1589 				 bool qualify_col)
1590 {
1591 	RangeTblEntry *rte;
1592 
1593 	if (varattno == SelfItemPointerAttributeNumber)
1594 	{
1595 		/* We support fetching the remote side's CTID. */
1596 		if (qualify_col)
1597 			ADD_REL_QUALIFIER(buf, varno);
1598 		appendStringInfoString(buf, "ctid");
1599 	}
1600 	else if (varattno < 0)
1601 	{
1602 		/*
1603 		 * All other system attributes are fetched as 0, except for table OID,
1604 		 * which is fetched as the local table OID.  However, we must be
1605 		 * careful; the table could be beneath an outer join, in which case it
1606 		 * must go to NULL whenever the rest of the row does.
1607 		 */
1608 		Oid			fetchval = 0;
1609 
1610 		if (varattno == TableOidAttributeNumber)
1611 		{
1612 			rte = planner_rt_fetch(varno, root);
1613 			fetchval = rte->relid;
1614 		}
1615 
1616 		if (qualify_col)
1617 		{
1618 			appendStringInfoString(buf, "CASE WHEN (");
1619 			ADD_REL_QUALIFIER(buf, varno);
1620 			appendStringInfo(buf, "*)::text IS NOT NULL THEN %u END", fetchval);
1621 		}
1622 		else
1623 			appendStringInfo(buf, "%u", fetchval);
1624 	}
1625 	else if (varattno == 0)
1626 	{
1627 		/* Whole row reference */
1628 		Relation	rel;
1629 		Bitmapset  *attrs_used;
1630 
1631 		/* Required only to be passed down to deparseTargetList(). */
1632 		List	   *retrieved_attrs;
1633 
1634 		/* Get RangeTblEntry from array in PlannerInfo. */
1635 		rte = planner_rt_fetch(varno, root);
1636 
1637 		/*
1638 		 * The lock on the relation will be held by upper callers, so it's
1639 		 * fine to open it with no lock here.
1640 		 */
1641 		rel = heap_open(rte->relid, NoLock);
1642 
1643 		/*
1644 		 * The local name of the foreign table can not be recognized by the
1645 		 * foreign server and the table it references on foreign server might
1646 		 * have different column ordering or different columns than those
1647 		 * declared locally. Hence we have to deparse whole-row reference as
1648 		 * ROW(columns referenced locally). Construct this by deparsing a
1649 		 * "whole row" attribute.
1650 		 */
1651 		attrs_used = bms_add_member(NULL,
1652 									0 - FirstLowInvalidHeapAttributeNumber);
1653 
1654 		/*
1655 		 * In case the whole-row reference is under an outer join then it has
1656 		 * to go NULL whenever the rest of the row goes NULL. Deparsing a join
1657 		 * query would always involve multiple relations, thus qualify_col
1658 		 * would be true.
1659 		 */
1660 		if (qualify_col)
1661 		{
1662 			appendStringInfoString(buf, "CASE WHEN (");
1663 			ADD_REL_QUALIFIER(buf, varno);
1664 			appendStringInfo(buf, "*)::text IS NOT NULL THEN ");
1665 		}
1666 
1667 		appendStringInfoString(buf, "ROW(");
1668 		deparseTargetList(buf, root, varno, rel, false, attrs_used, qualify_col,
1669 						  &retrieved_attrs);
1670 		appendStringInfoString(buf, ")");
1671 
1672 		/* Complete the CASE WHEN statement started above. */
1673 		if (qualify_col)
1674 			appendStringInfo(buf, " END");
1675 
1676 		heap_close(rel, NoLock);
1677 		bms_free(attrs_used);
1678 	}
1679 	else
1680 	{
1681 		char	   *colname = NULL;
1682 		List	   *options;
1683 		ListCell   *lc;
1684 
1685 		/* varno must not be any of OUTER_VAR, INNER_VAR and INDEX_VAR. */
1686 		Assert(!IS_SPECIAL_VARNO(varno));
1687 
1688 		/* Get RangeTblEntry from array in PlannerInfo. */
1689 		rte = planner_rt_fetch(varno, root);
1690 
1691 		/*
1692 		 * If it's a column of a foreign table, and it has the column_name FDW
1693 		 * option, use that value.
1694 		 */
1695 		options = GetForeignColumnOptions(rte->relid, varattno);
1696 		foreach(lc, options)
1697 		{
1698 			DefElem    *def = (DefElem *) lfirst(lc);
1699 
1700 			if (strcmp(def->defname, "column_name") == 0)
1701 			{
1702 				colname = defGetString(def);
1703 				break;
1704 			}
1705 		}
1706 
1707 		/*
1708 		 * If it's a column of a regular table or it doesn't have column_name
1709 		 * FDW option, use attribute name.
1710 		 */
1711 		if (colname == NULL)
1712 			colname = get_relid_attribute_name(rte->relid, varattno);
1713 
1714 		if (qualify_col)
1715 			ADD_REL_QUALIFIER(buf, varno);
1716 
1717 		appendStringInfoString(buf, quote_identifier(colname));
1718 	}
1719 }
1720 
1721 /*
1722  * Append remote name of specified foreign table to buf.
1723  * Use value of table_name FDW option (if any) instead of relation's name.
1724  * Similarly, schema_name FDW option overrides schema name.
1725  */
1726 static void
deparseRelation(StringInfo buf,Relation rel)1727 deparseRelation(StringInfo buf, Relation rel)
1728 {
1729 	ForeignTable *table;
1730 	const char *nspname = NULL;
1731 	const char *relname = NULL;
1732 	ListCell   *lc;
1733 
1734 	/* obtain additional catalog information. */
1735 	table = GetForeignTable(RelationGetRelid(rel));
1736 
1737 	/*
1738 	 * Use value of FDW options if any, instead of the name of object itself.
1739 	 */
1740 	foreach(lc, table->options)
1741 	{
1742 		DefElem    *def = (DefElem *) lfirst(lc);
1743 
1744 		if (strcmp(def->defname, "schema_name") == 0)
1745 			nspname = defGetString(def);
1746 		else if (strcmp(def->defname, "table_name") == 0)
1747 			relname = defGetString(def);
1748 	}
1749 
1750 	/*
1751 	 * Note: we could skip printing the schema name if it's pg_catalog, but
1752 	 * that doesn't seem worth the trouble.
1753 	 */
1754 	if (nspname == NULL)
1755 		nspname = get_namespace_name(RelationGetNamespace(rel));
1756 	if (relname == NULL)
1757 		relname = RelationGetRelationName(rel);
1758 
1759 	appendStringInfo(buf, "%s.%s",
1760 					 quote_identifier(nspname), quote_identifier(relname));
1761 }
1762 
1763 /*
1764  * Append a SQL string literal representing "val" to buf.
1765  */
1766 void
deparseStringLiteral(StringInfo buf,const char * val)1767 deparseStringLiteral(StringInfo buf, const char *val)
1768 {
1769 	const char *valptr;
1770 
1771 	/*
1772 	 * Rather than making assumptions about the remote server's value of
1773 	 * standard_conforming_strings, always use E'foo' syntax if there are any
1774 	 * backslashes.  This will fail on remote servers before 8.1, but those
1775 	 * are long out of support.
1776 	 */
1777 	if (strchr(val, '\\') != NULL)
1778 		appendStringInfoChar(buf, ESCAPE_STRING_SYNTAX);
1779 	appendStringInfoChar(buf, '\'');
1780 	for (valptr = val; *valptr; valptr++)
1781 	{
1782 		char		ch = *valptr;
1783 
1784 		if (SQL_STR_DOUBLE(ch, true))
1785 			appendStringInfoChar(buf, ch);
1786 		appendStringInfoChar(buf, ch);
1787 	}
1788 	appendStringInfoChar(buf, '\'');
1789 }
1790 
1791 /*
1792  * Deparse given expression into context->buf.
1793  *
1794  * This function must support all the same node types that foreign_expr_walker
1795  * accepts.
1796  *
1797  * Note: unlike ruleutils.c, we just use a simple hard-wired parenthesization
1798  * scheme: anything more complex than a Var, Const, function call or cast
1799  * should be self-parenthesized.
1800  */
1801 static void
deparseExpr(Expr * node,deparse_expr_cxt * context)1802 deparseExpr(Expr *node, deparse_expr_cxt *context)
1803 {
1804 	if (node == NULL)
1805 		return;
1806 
1807 	switch (nodeTag(node))
1808 	{
1809 		case T_Var:
1810 			deparseVar((Var *) node, context);
1811 			break;
1812 		case T_Const:
1813 			deparseConst((Const *) node, context);
1814 			break;
1815 		case T_Param:
1816 			deparseParam((Param *) node, context);
1817 			break;
1818 		case T_ArrayRef:
1819 			deparseArrayRef((ArrayRef *) node, context);
1820 			break;
1821 		case T_FuncExpr:
1822 			deparseFuncExpr((FuncExpr *) node, context);
1823 			break;
1824 		case T_OpExpr:
1825 			deparseOpExpr((OpExpr *) node, context);
1826 			break;
1827 		case T_DistinctExpr:
1828 			deparseDistinctExpr((DistinctExpr *) node, context);
1829 			break;
1830 		case T_ScalarArrayOpExpr:
1831 			deparseScalarArrayOpExpr((ScalarArrayOpExpr *) node, context);
1832 			break;
1833 		case T_RelabelType:
1834 			deparseRelabelType((RelabelType *) node, context);
1835 			break;
1836 		case T_BoolExpr:
1837 			deparseBoolExpr((BoolExpr *) node, context);
1838 			break;
1839 		case T_NullTest:
1840 			deparseNullTest((NullTest *) node, context);
1841 			break;
1842 		case T_ArrayExpr:
1843 			deparseArrayExpr((ArrayExpr *) node, context);
1844 			break;
1845 		default:
1846 			elog(ERROR, "unsupported expression type for deparse: %d",
1847 				 (int) nodeTag(node));
1848 			break;
1849 	}
1850 }
1851 
1852 /*
1853  * Deparse given Var node into context->buf.
1854  *
1855  * If the Var belongs to the foreign relation, just print its remote name.
1856  * Otherwise, it's effectively a Param (and will in fact be a Param at
1857  * run time).  Handle it the same way we handle plain Params --- see
1858  * deparseParam for comments.
1859  */
1860 static void
deparseVar(Var * node,deparse_expr_cxt * context)1861 deparseVar(Var *node, deparse_expr_cxt *context)
1862 {
1863 	bool		qualify_col = (context->foreignrel->reloptkind == RELOPT_JOINREL);
1864 
1865 	if (bms_is_member(node->varno, context->foreignrel->relids) &&
1866 		node->varlevelsup == 0)
1867 		deparseColumnRef(context->buf, node->varno, node->varattno,
1868 						 context->root, qualify_col);
1869 	else
1870 	{
1871 		/* Treat like a Param */
1872 		if (context->params_list)
1873 		{
1874 			int			pindex = 0;
1875 			ListCell   *lc;
1876 
1877 			/* find its index in params_list */
1878 			foreach(lc, *context->params_list)
1879 			{
1880 				pindex++;
1881 				if (equal(node, (Node *) lfirst(lc)))
1882 					break;
1883 			}
1884 			if (lc == NULL)
1885 			{
1886 				/* not in list, so add it */
1887 				pindex++;
1888 				*context->params_list = lappend(*context->params_list, node);
1889 			}
1890 
1891 			printRemoteParam(pindex, node->vartype, node->vartypmod, context);
1892 		}
1893 		else
1894 		{
1895 			printRemotePlaceholder(node->vartype, node->vartypmod, context);
1896 		}
1897 	}
1898 }
1899 
1900 /*
1901  * Deparse given constant value into context->buf.
1902  *
1903  * This function has to be kept in sync with ruleutils.c's get_const_expr.
1904  */
1905 static void
deparseConst(Const * node,deparse_expr_cxt * context)1906 deparseConst(Const *node, deparse_expr_cxt *context)
1907 {
1908 	StringInfo	buf = context->buf;
1909 	Oid			typoutput;
1910 	bool		typIsVarlena;
1911 	char	   *extval;
1912 	bool		isfloat = false;
1913 	bool		needlabel;
1914 
1915 	if (node->constisnull)
1916 	{
1917 		appendStringInfoString(buf, "NULL");
1918 		appendStringInfo(buf, "::%s",
1919 						 deparse_type_name(node->consttype,
1920 										   node->consttypmod));
1921 		return;
1922 	}
1923 
1924 	getTypeOutputInfo(node->consttype,
1925 					  &typoutput, &typIsVarlena);
1926 	extval = OidOutputFunctionCall(typoutput, node->constvalue);
1927 
1928 	switch (node->consttype)
1929 	{
1930 		case INT2OID:
1931 		case INT4OID:
1932 		case INT8OID:
1933 		case OIDOID:
1934 		case FLOAT4OID:
1935 		case FLOAT8OID:
1936 		case NUMERICOID:
1937 			{
1938 				/*
1939 				 * No need to quote unless it's a special value such as 'NaN'.
1940 				 * See comments in get_const_expr().
1941 				 */
1942 				if (strspn(extval, "0123456789+-eE.") == strlen(extval))
1943 				{
1944 					if (extval[0] == '+' || extval[0] == '-')
1945 						appendStringInfo(buf, "(%s)", extval);
1946 					else
1947 						appendStringInfoString(buf, extval);
1948 					if (strcspn(extval, "eE.") != strlen(extval))
1949 						isfloat = true; /* it looks like a float */
1950 				}
1951 				else
1952 					appendStringInfo(buf, "'%s'", extval);
1953 			}
1954 			break;
1955 		case BITOID:
1956 		case VARBITOID:
1957 			appendStringInfo(buf, "B'%s'", extval);
1958 			break;
1959 		case BOOLOID:
1960 			if (strcmp(extval, "t") == 0)
1961 				appendStringInfoString(buf, "true");
1962 			else
1963 				appendStringInfoString(buf, "false");
1964 			break;
1965 		default:
1966 			deparseStringLiteral(buf, extval);
1967 			break;
1968 	}
1969 
1970 	/*
1971 	 * Append ::typename unless the constant will be implicitly typed as the
1972 	 * right type when it is read in.
1973 	 *
1974 	 * XXX this code has to be kept in sync with the behavior of the parser,
1975 	 * especially make_const.
1976 	 */
1977 	switch (node->consttype)
1978 	{
1979 		case BOOLOID:
1980 		case INT4OID:
1981 		case UNKNOWNOID:
1982 			needlabel = false;
1983 			break;
1984 		case NUMERICOID:
1985 			needlabel = !isfloat || (node->consttypmod >= 0);
1986 			break;
1987 		default:
1988 			needlabel = true;
1989 			break;
1990 	}
1991 	if (needlabel)
1992 		appendStringInfo(buf, "::%s",
1993 						 deparse_type_name(node->consttype,
1994 										   node->consttypmod));
1995 }
1996 
1997 /*
1998  * Deparse given Param node.
1999  *
2000  * If we're generating the query "for real", add the Param to
2001  * context->params_list if it's not already present, and then use its index
2002  * in that list as the remote parameter number.  During EXPLAIN, there's
2003  * no need to identify a parameter number.
2004  */
2005 static void
deparseParam(Param * node,deparse_expr_cxt * context)2006 deparseParam(Param *node, deparse_expr_cxt *context)
2007 {
2008 	if (context->params_list)
2009 	{
2010 		int			pindex = 0;
2011 		ListCell   *lc;
2012 
2013 		/* find its index in params_list */
2014 		foreach(lc, *context->params_list)
2015 		{
2016 			pindex++;
2017 			if (equal(node, (Node *) lfirst(lc)))
2018 				break;
2019 		}
2020 		if (lc == NULL)
2021 		{
2022 			/* not in list, so add it */
2023 			pindex++;
2024 			*context->params_list = lappend(*context->params_list, node);
2025 		}
2026 
2027 		printRemoteParam(pindex, node->paramtype, node->paramtypmod, context);
2028 	}
2029 	else
2030 	{
2031 		printRemotePlaceholder(node->paramtype, node->paramtypmod, context);
2032 	}
2033 }
2034 
2035 /*
2036  * Deparse an array subscript expression.
2037  */
2038 static void
deparseArrayRef(ArrayRef * node,deparse_expr_cxt * context)2039 deparseArrayRef(ArrayRef *node, deparse_expr_cxt *context)
2040 {
2041 	StringInfo	buf = context->buf;
2042 	ListCell   *lowlist_item;
2043 	ListCell   *uplist_item;
2044 
2045 	/* Always parenthesize the expression. */
2046 	appendStringInfoChar(buf, '(');
2047 
2048 	/*
2049 	 * Deparse referenced array expression first.  If that expression includes
2050 	 * a cast, we have to parenthesize to prevent the array subscript from
2051 	 * being taken as typename decoration.  We can avoid that in the typical
2052 	 * case of subscripting a Var, but otherwise do it.
2053 	 */
2054 	if (IsA(node->refexpr, Var))
2055 		deparseExpr(node->refexpr, context);
2056 	else
2057 	{
2058 		appendStringInfoChar(buf, '(');
2059 		deparseExpr(node->refexpr, context);
2060 		appendStringInfoChar(buf, ')');
2061 	}
2062 
2063 	/* Deparse subscript expressions. */
2064 	lowlist_item = list_head(node->reflowerindexpr);	/* could be NULL */
2065 	foreach(uplist_item, node->refupperindexpr)
2066 	{
2067 		appendStringInfoChar(buf, '[');
2068 		if (lowlist_item)
2069 		{
2070 			deparseExpr(lfirst(lowlist_item), context);
2071 			appendStringInfoChar(buf, ':');
2072 			lowlist_item = lnext(lowlist_item);
2073 		}
2074 		deparseExpr(lfirst(uplist_item), context);
2075 		appendStringInfoChar(buf, ']');
2076 	}
2077 
2078 	appendStringInfoChar(buf, ')');
2079 }
2080 
2081 /*
2082  * Deparse a function call.
2083  */
2084 static void
deparseFuncExpr(FuncExpr * node,deparse_expr_cxt * context)2085 deparseFuncExpr(FuncExpr *node, deparse_expr_cxt *context)
2086 {
2087 	StringInfo	buf = context->buf;
2088 	HeapTuple	proctup;
2089 	Form_pg_proc procform;
2090 	const char *proname;
2091 	bool		use_variadic;
2092 	bool		first;
2093 	ListCell   *arg;
2094 
2095 	/*
2096 	 * If the function call came from an implicit coercion, then just show the
2097 	 * first argument.
2098 	 */
2099 	if (node->funcformat == COERCE_IMPLICIT_CAST)
2100 	{
2101 		deparseExpr((Expr *) linitial(node->args), context);
2102 		return;
2103 	}
2104 
2105 	/*
2106 	 * If the function call came from a cast, then show the first argument
2107 	 * plus an explicit cast operation.
2108 	 */
2109 	if (node->funcformat == COERCE_EXPLICIT_CAST)
2110 	{
2111 		Oid			rettype = node->funcresulttype;
2112 		int32		coercedTypmod;
2113 
2114 		/* Get the typmod if this is a length-coercion function */
2115 		(void) exprIsLengthCoercion((Node *) node, &coercedTypmod);
2116 
2117 		deparseExpr((Expr *) linitial(node->args), context);
2118 		appendStringInfo(buf, "::%s",
2119 						 deparse_type_name(rettype, coercedTypmod));
2120 		return;
2121 	}
2122 
2123 	/*
2124 	 * Normal function: display as proname(args).
2125 	 */
2126 	proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(node->funcid));
2127 	if (!HeapTupleIsValid(proctup))
2128 		elog(ERROR, "cache lookup failed for function %u", node->funcid);
2129 	procform = (Form_pg_proc) GETSTRUCT(proctup);
2130 
2131 	/* Check if need to print VARIADIC (cf. ruleutils.c) */
2132 	use_variadic = node->funcvariadic;
2133 
2134 	/* Print schema name only if it's not pg_catalog */
2135 	if (procform->pronamespace != PG_CATALOG_NAMESPACE)
2136 	{
2137 		const char *schemaname;
2138 
2139 		schemaname = get_namespace_name(procform->pronamespace);
2140 		appendStringInfo(buf, "%s.", quote_identifier(schemaname));
2141 	}
2142 
2143 	/* Deparse the function name ... */
2144 	proname = NameStr(procform->proname);
2145 	appendStringInfo(buf, "%s(", quote_identifier(proname));
2146 	/* ... and all the arguments */
2147 	first = true;
2148 	foreach(arg, node->args)
2149 	{
2150 		if (!first)
2151 			appendStringInfoString(buf, ", ");
2152 		if (use_variadic && lnext(arg) == NULL)
2153 			appendStringInfoString(buf, "VARIADIC ");
2154 		deparseExpr((Expr *) lfirst(arg), context);
2155 		first = false;
2156 	}
2157 	appendStringInfoChar(buf, ')');
2158 
2159 	ReleaseSysCache(proctup);
2160 }
2161 
2162 /*
2163  * Deparse given operator expression.   To avoid problems around
2164  * priority of operations, we always parenthesize the arguments.
2165  */
2166 static void
deparseOpExpr(OpExpr * node,deparse_expr_cxt * context)2167 deparseOpExpr(OpExpr *node, deparse_expr_cxt *context)
2168 {
2169 	StringInfo	buf = context->buf;
2170 	HeapTuple	tuple;
2171 	Form_pg_operator form;
2172 	char		oprkind;
2173 	ListCell   *arg;
2174 
2175 	/* Retrieve information about the operator from system catalog. */
2176 	tuple = SearchSysCache1(OPEROID, ObjectIdGetDatum(node->opno));
2177 	if (!HeapTupleIsValid(tuple))
2178 		elog(ERROR, "cache lookup failed for operator %u", node->opno);
2179 	form = (Form_pg_operator) GETSTRUCT(tuple);
2180 	oprkind = form->oprkind;
2181 
2182 	/* Sanity check. */
2183 	Assert((oprkind == 'r' && list_length(node->args) == 1) ||
2184 		   (oprkind == 'l' && list_length(node->args) == 1) ||
2185 		   (oprkind == 'b' && list_length(node->args) == 2));
2186 
2187 	/* Always parenthesize the expression. */
2188 	appendStringInfoChar(buf, '(');
2189 
2190 	/* Deparse left operand. */
2191 	if (oprkind == 'r' || oprkind == 'b')
2192 	{
2193 		arg = list_head(node->args);
2194 		deparseExpr(lfirst(arg), context);
2195 		appendStringInfoChar(buf, ' ');
2196 	}
2197 
2198 	/* Deparse operator name. */
2199 	deparseOperatorName(buf, form);
2200 
2201 	/* Deparse right operand. */
2202 	if (oprkind == 'l' || oprkind == 'b')
2203 	{
2204 		arg = list_tail(node->args);
2205 		appendStringInfoChar(buf, ' ');
2206 		deparseExpr(lfirst(arg), context);
2207 	}
2208 
2209 	appendStringInfoChar(buf, ')');
2210 
2211 	ReleaseSysCache(tuple);
2212 }
2213 
2214 /*
2215  * Print the name of an operator.
2216  */
2217 static void
deparseOperatorName(StringInfo buf,Form_pg_operator opform)2218 deparseOperatorName(StringInfo buf, Form_pg_operator opform)
2219 {
2220 	char	   *opname;
2221 
2222 	/* opname is not a SQL identifier, so we should not quote it. */
2223 	opname = NameStr(opform->oprname);
2224 
2225 	/* Print schema name only if it's not pg_catalog */
2226 	if (opform->oprnamespace != PG_CATALOG_NAMESPACE)
2227 	{
2228 		const char *opnspname;
2229 
2230 		opnspname = get_namespace_name(opform->oprnamespace);
2231 		/* Print fully qualified operator name. */
2232 		appendStringInfo(buf, "OPERATOR(%s.%s)",
2233 						 quote_identifier(opnspname), opname);
2234 	}
2235 	else
2236 	{
2237 		/* Just print operator name. */
2238 		appendStringInfoString(buf, opname);
2239 	}
2240 }
2241 
2242 /*
2243  * Deparse IS DISTINCT FROM.
2244  */
2245 static void
deparseDistinctExpr(DistinctExpr * node,deparse_expr_cxt * context)2246 deparseDistinctExpr(DistinctExpr *node, deparse_expr_cxt *context)
2247 {
2248 	StringInfo	buf = context->buf;
2249 
2250 	Assert(list_length(node->args) == 2);
2251 
2252 	appendStringInfoChar(buf, '(');
2253 	deparseExpr(linitial(node->args), context);
2254 	appendStringInfoString(buf, " IS DISTINCT FROM ");
2255 	deparseExpr(lsecond(node->args), context);
2256 	appendStringInfoChar(buf, ')');
2257 }
2258 
2259 /*
2260  * Deparse given ScalarArrayOpExpr expression.  To avoid problems
2261  * around priority of operations, we always parenthesize the arguments.
2262  */
2263 static void
deparseScalarArrayOpExpr(ScalarArrayOpExpr * node,deparse_expr_cxt * context)2264 deparseScalarArrayOpExpr(ScalarArrayOpExpr *node, deparse_expr_cxt *context)
2265 {
2266 	StringInfo	buf = context->buf;
2267 	HeapTuple	tuple;
2268 	Form_pg_operator form;
2269 	Expr	   *arg1;
2270 	Expr	   *arg2;
2271 
2272 	/* Retrieve information about the operator from system catalog. */
2273 	tuple = SearchSysCache1(OPEROID, ObjectIdGetDatum(node->opno));
2274 	if (!HeapTupleIsValid(tuple))
2275 		elog(ERROR, "cache lookup failed for operator %u", node->opno);
2276 	form = (Form_pg_operator) GETSTRUCT(tuple);
2277 
2278 	/* Sanity check. */
2279 	Assert(list_length(node->args) == 2);
2280 
2281 	/* Always parenthesize the expression. */
2282 	appendStringInfoChar(buf, '(');
2283 
2284 	/* Deparse left operand. */
2285 	arg1 = linitial(node->args);
2286 	deparseExpr(arg1, context);
2287 	appendStringInfoChar(buf, ' ');
2288 
2289 	/* Deparse operator name plus decoration. */
2290 	deparseOperatorName(buf, form);
2291 	appendStringInfo(buf, " %s (", node->useOr ? "ANY" : "ALL");
2292 
2293 	/* Deparse right operand. */
2294 	arg2 = lsecond(node->args);
2295 	deparseExpr(arg2, context);
2296 
2297 	appendStringInfoChar(buf, ')');
2298 
2299 	/* Always parenthesize the expression. */
2300 	appendStringInfoChar(buf, ')');
2301 
2302 	ReleaseSysCache(tuple);
2303 }
2304 
2305 /*
2306  * Deparse a RelabelType (binary-compatible cast) node.
2307  */
2308 static void
deparseRelabelType(RelabelType * node,deparse_expr_cxt * context)2309 deparseRelabelType(RelabelType *node, deparse_expr_cxt *context)
2310 {
2311 	deparseExpr(node->arg, context);
2312 	if (node->relabelformat != COERCE_IMPLICIT_CAST)
2313 		appendStringInfo(context->buf, "::%s",
2314 						 deparse_type_name(node->resulttype,
2315 										   node->resulttypmod));
2316 }
2317 
2318 /*
2319  * Deparse a BoolExpr node.
2320  */
2321 static void
deparseBoolExpr(BoolExpr * node,deparse_expr_cxt * context)2322 deparseBoolExpr(BoolExpr *node, deparse_expr_cxt *context)
2323 {
2324 	StringInfo	buf = context->buf;
2325 	const char *op = NULL;		/* keep compiler quiet */
2326 	bool		first;
2327 	ListCell   *lc;
2328 
2329 	switch (node->boolop)
2330 	{
2331 		case AND_EXPR:
2332 			op = "AND";
2333 			break;
2334 		case OR_EXPR:
2335 			op = "OR";
2336 			break;
2337 		case NOT_EXPR:
2338 			appendStringInfoString(buf, "(NOT ");
2339 			deparseExpr(linitial(node->args), context);
2340 			appendStringInfoChar(buf, ')');
2341 			return;
2342 	}
2343 
2344 	appendStringInfoChar(buf, '(');
2345 	first = true;
2346 	foreach(lc, node->args)
2347 	{
2348 		if (!first)
2349 			appendStringInfo(buf, " %s ", op);
2350 		deparseExpr((Expr *) lfirst(lc), context);
2351 		first = false;
2352 	}
2353 	appendStringInfoChar(buf, ')');
2354 }
2355 
2356 /*
2357  * Deparse IS [NOT] NULL expression.
2358  */
2359 static void
deparseNullTest(NullTest * node,deparse_expr_cxt * context)2360 deparseNullTest(NullTest *node, deparse_expr_cxt *context)
2361 {
2362 	StringInfo	buf = context->buf;
2363 
2364 	appendStringInfoChar(buf, '(');
2365 	deparseExpr(node->arg, context);
2366 
2367 	/*
2368 	 * For scalar inputs, we prefer to print as IS [NOT] NULL, which is
2369 	 * shorter and traditional.  If it's a rowtype input but we're applying a
2370 	 * scalar test, must print IS [NOT] DISTINCT FROM NULL to be semantically
2371 	 * correct.
2372 	 */
2373 	if (node->argisrow || !type_is_rowtype(exprType((Node *) node->arg)))
2374 	{
2375 		if (node->nulltesttype == IS_NULL)
2376 			appendStringInfoString(buf, " IS NULL)");
2377 		else
2378 			appendStringInfoString(buf, " IS NOT NULL)");
2379 	}
2380 	else
2381 	{
2382 		if (node->nulltesttype == IS_NULL)
2383 			appendStringInfoString(buf, " IS NOT DISTINCT FROM NULL)");
2384 		else
2385 			appendStringInfoString(buf, " IS DISTINCT FROM NULL)");
2386 	}
2387 }
2388 
2389 /*
2390  * Deparse ARRAY[...] construct.
2391  */
2392 static void
deparseArrayExpr(ArrayExpr * node,deparse_expr_cxt * context)2393 deparseArrayExpr(ArrayExpr *node, deparse_expr_cxt *context)
2394 {
2395 	StringInfo	buf = context->buf;
2396 	bool		first = true;
2397 	ListCell   *lc;
2398 
2399 	appendStringInfoString(buf, "ARRAY[");
2400 	foreach(lc, node->elements)
2401 	{
2402 		if (!first)
2403 			appendStringInfoString(buf, ", ");
2404 		deparseExpr(lfirst(lc), context);
2405 		first = false;
2406 	}
2407 	appendStringInfoChar(buf, ']');
2408 
2409 	/* If the array is empty, we need an explicit cast to the array type. */
2410 	if (node->elements == NIL)
2411 		appendStringInfo(buf, "::%s",
2412 						 deparse_type_name(node->array_typeid, -1));
2413 }
2414 
2415 /*
2416  * Print the representation of a parameter to be sent to the remote side.
2417  *
2418  * Note: we always label the Param's type explicitly rather than relying on
2419  * transmitting a numeric type OID in PQexecParams().  This allows us to
2420  * avoid assuming that types have the same OIDs on the remote side as they
2421  * do locally --- they need only have the same names.
2422  */
2423 static void
printRemoteParam(int paramindex,Oid paramtype,int32 paramtypmod,deparse_expr_cxt * context)2424 printRemoteParam(int paramindex, Oid paramtype, int32 paramtypmod,
2425 				 deparse_expr_cxt *context)
2426 {
2427 	StringInfo	buf = context->buf;
2428 	char	   *ptypename = deparse_type_name(paramtype, paramtypmod);
2429 
2430 	appendStringInfo(buf, "$%d::%s", paramindex, ptypename);
2431 }
2432 
2433 /*
2434  * Print the representation of a placeholder for a parameter that will be
2435  * sent to the remote side at execution time.
2436  *
2437  * This is used when we're just trying to EXPLAIN the remote query.
2438  * We don't have the actual value of the runtime parameter yet, and we don't
2439  * want the remote planner to generate a plan that depends on such a value
2440  * anyway.  Thus, we can't do something simple like "$1::paramtype".
2441  * Instead, we emit "((SELECT null::paramtype)::paramtype)".
2442  * In all extant versions of Postgres, the planner will see that as an unknown
2443  * constant value, which is what we want.  This might need adjustment if we
2444  * ever make the planner flatten scalar subqueries.  Note: the reason for the
2445  * apparently useless outer cast is to ensure that the representation as a
2446  * whole will be parsed as an a_expr and not a select_with_parens; the latter
2447  * would do the wrong thing in the context "x = ANY(...)".
2448  */
2449 static void
printRemotePlaceholder(Oid paramtype,int32 paramtypmod,deparse_expr_cxt * context)2450 printRemotePlaceholder(Oid paramtype, int32 paramtypmod,
2451 					   deparse_expr_cxt *context)
2452 {
2453 	StringInfo	buf = context->buf;
2454 	char	   *ptypename = deparse_type_name(paramtype, paramtypmod);
2455 
2456 	appendStringInfo(buf, "((SELECT null::%s)::%s)", ptypename, ptypename);
2457 }
2458 
2459 /*
2460  * Deparse ORDER BY clause according to the given pathkeys for given base
2461  * relation. From given pathkeys expressions belonging entirely to the given
2462  * base relation are obtained and deparsed.
2463  */
2464 static void
appendOrderByClause(List * pathkeys,deparse_expr_cxt * context)2465 appendOrderByClause(List *pathkeys, deparse_expr_cxt *context)
2466 {
2467 	ListCell   *lcell;
2468 	int			nestlevel;
2469 	char	   *delim = " ";
2470 	RelOptInfo *baserel = context->foreignrel;
2471 	StringInfo	buf = context->buf;
2472 
2473 	/* Make sure any constants in the exprs are printed portably */
2474 	nestlevel = set_transmission_modes();
2475 
2476 	appendStringInfo(buf, " ORDER BY");
2477 	foreach(lcell, pathkeys)
2478 	{
2479 		PathKey    *pathkey = lfirst(lcell);
2480 		Expr	   *em_expr;
2481 
2482 		em_expr = find_em_expr_for_rel(pathkey->pk_eclass, baserel);
2483 		Assert(em_expr != NULL);
2484 
2485 		appendStringInfoString(buf, delim);
2486 		deparseExpr(em_expr, context);
2487 		if (pathkey->pk_strategy == BTLessStrategyNumber)
2488 			appendStringInfoString(buf, " ASC");
2489 		else
2490 			appendStringInfoString(buf, " DESC");
2491 
2492 		if (pathkey->pk_nulls_first)
2493 			appendStringInfoString(buf, " NULLS FIRST");
2494 		else
2495 			appendStringInfoString(buf, " NULLS LAST");
2496 
2497 		delim = ", ";
2498 	}
2499 	reset_transmission_modes(nestlevel);
2500 }
2501