Add docs for pg_matviews, which were missed in the initial MV commit.
[pgsql.git] / contrib / postgres_fdw / deparse.c
blob9816f550ca57cd9af4e07bc2f2bc1c96cde50ec7
1 /*-------------------------------------------------------------------------
3 * deparse.c
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 * Portions Copyright (c) 2012-2013, PostgreSQL Global Development Group
19 * IDENTIFICATION
20 * contrib/postgres_fdw/deparse.c
22 *-------------------------------------------------------------------------
24 #include "postgres.h"
26 #include "postgres_fdw.h"
28 #include "access/htup_details.h"
29 #include "access/sysattr.h"
30 #include "access/transam.h"
31 #include "catalog/pg_namespace.h"
32 #include "catalog/pg_operator.h"
33 #include "catalog/pg_proc.h"
34 #include "catalog/pg_type.h"
35 #include "commands/defrem.h"
36 #include "nodes/nodeFuncs.h"
37 #include "optimizer/clauses.h"
38 #include "optimizer/var.h"
39 #include "parser/parsetree.h"
40 #include "utils/builtins.h"
41 #include "utils/lsyscache.h"
42 #include "utils/syscache.h"
46 * Context for foreign_expr_walker's search of an expression tree.
48 typedef struct foreign_expr_cxt
50 /* Input values */
51 PlannerInfo *root;
52 RelOptInfo *foreignrel;
53 /* Result values */
54 List *param_numbers; /* Param IDs of PARAM_EXTERN Params */
55 } foreign_expr_cxt;
58 * Functions to determine whether an expression can be evaluated safely on
59 * remote server.
61 static bool is_foreign_expr(PlannerInfo *root, RelOptInfo *baserel,
62 Expr *expr, List **param_numbers);
63 static bool foreign_expr_walker(Node *node, foreign_expr_cxt *context);
64 static bool is_builtin(Oid procid);
67 * Functions to construct string representation of a node tree.
69 static void deparseColumnRef(StringInfo buf, int varno, int varattno,
70 PlannerInfo *root);
71 static void deparseRelation(StringInfo buf, Oid relid);
72 static void deparseStringLiteral(StringInfo buf, const char *val);
73 static void deparseExpr(StringInfo buf, Expr *expr, PlannerInfo *root);
74 static void deparseVar(StringInfo buf, Var *node, PlannerInfo *root);
75 static void deparseConst(StringInfo buf, Const *node, PlannerInfo *root);
76 static void deparseParam(StringInfo buf, Param *node, PlannerInfo *root);
77 static void deparseArrayRef(StringInfo buf, ArrayRef *node, PlannerInfo *root);
78 static void deparseFuncExpr(StringInfo buf, FuncExpr *node, PlannerInfo *root);
79 static void deparseOpExpr(StringInfo buf, OpExpr *node, PlannerInfo *root);
80 static void deparseOperatorName(StringInfo buf, Form_pg_operator opform);
81 static void deparseDistinctExpr(StringInfo buf, DistinctExpr *node,
82 PlannerInfo *root);
83 static void deparseScalarArrayOpExpr(StringInfo buf, ScalarArrayOpExpr *node,
84 PlannerInfo *root);
85 static void deparseRelabelType(StringInfo buf, RelabelType *node,
86 PlannerInfo *root);
87 static void deparseBoolExpr(StringInfo buf, BoolExpr *node, PlannerInfo *root);
88 static void deparseNullTest(StringInfo buf, NullTest *node, PlannerInfo *root);
89 static void deparseArrayExpr(StringInfo buf, ArrayExpr *node,
90 PlannerInfo *root);
94 * Examine each restriction clause in baserel's baserestrictinfo list,
95 * and classify them into three groups, which are returned as three lists:
96 * - remote_conds contains expressions that can be evaluated remotely,
97 * and contain no PARAM_EXTERN Params
98 * - param_conds contains expressions that can be evaluated remotely,
99 * but contain one or more PARAM_EXTERN Params
100 * - local_conds contains all expressions that can't be evaluated remotely
102 * In addition, the fourth output parameter param_numbers receives an integer
103 * list of the param IDs of the PARAM_EXTERN Params used in param_conds.
105 * The reason for segregating param_conds is mainly that it's difficult to
106 * use such conditions in remote EXPLAIN. We could do it, but unless the
107 * planner has been given representative values for all the Params, we'd
108 * have to guess at representative values to use in EXPLAIN EXECUTE.
109 * So for now we don't include them when doing remote EXPLAIN.
111 void
112 classifyConditions(PlannerInfo *root,
113 RelOptInfo *baserel,
114 List **remote_conds,
115 List **param_conds,
116 List **local_conds,
117 List **param_numbers)
119 ListCell *lc;
121 *remote_conds = NIL;
122 *param_conds = NIL;
123 *local_conds = NIL;
124 *param_numbers = NIL;
126 foreach(lc, baserel->baserestrictinfo)
128 RestrictInfo *ri = (RestrictInfo *) lfirst(lc);
129 List *cur_param_numbers;
131 if (is_foreign_expr(root, baserel, ri->clause, &cur_param_numbers))
133 if (cur_param_numbers == NIL)
134 *remote_conds = lappend(*remote_conds, ri);
135 else
137 *param_conds = lappend(*param_conds, ri);
138 /* Use list_concat_unique_int to get rid of duplicates */
139 *param_numbers = list_concat_unique_int(*param_numbers,
140 cur_param_numbers);
143 else
144 *local_conds = lappend(*local_conds, ri);
149 * Returns true if given expr is safe to evaluate on the foreign server.
151 * If result is true, we also return a list of param IDs of PARAM_EXTERN
152 * Params appearing in the expr into *param_numbers.
154 static bool
155 is_foreign_expr(PlannerInfo *root,
156 RelOptInfo *baserel,
157 Expr *expr,
158 List **param_numbers)
160 foreign_expr_cxt context;
162 *param_numbers = NIL; /* default result */
165 * Check that the expression consists of nodes that are safe to execute
166 * remotely.
168 context.root = root;
169 context.foreignrel = baserel;
170 context.param_numbers = NIL;
171 if (foreign_expr_walker((Node *) expr, &context))
172 return false;
175 * An expression which includes any mutable functions can't be sent over
176 * because its result is not stable. For example, sending now() remote
177 * side could cause confusion from clock offsets. Future versions might
178 * be able to make this choice with more granularity. (We check this last
179 * because it requires a lot of expensive catalog lookups.)
181 if (contain_mutable_functions((Node *) expr))
182 return false;
185 * OK, so return list of param IDs too.
187 *param_numbers = context.param_numbers;
189 return true;
193 * Return true if expression includes any node that is not safe to execute
194 * remotely. (We use this convention because expression_tree_walker is
195 * designed to abort the tree walk as soon as a TRUE result is detected.)
197 static bool
198 foreign_expr_walker(Node *node, foreign_expr_cxt *context)
200 bool check_type = true;
202 if (node == NULL)
203 return false;
205 switch (nodeTag(node))
207 case T_Var:
210 * Var can be used if it is in the foreign table (we shouldn't
211 * really see anything else in baserestrict clauses, but let's
212 * check anyway).
214 Var *var = (Var *) node;
216 if (var->varno != context->foreignrel->relid ||
217 var->varlevelsup != 0)
218 return true;
220 break;
221 case T_Const:
222 /* OK */
223 break;
224 case T_Param:
226 Param *p = (Param *) node;
229 * Only external parameters can be sent to remote. (XXX This
230 * needs to be improved, but at the point where this code
231 * runs, we should only see PARAM_EXTERN Params anyway.)
233 if (p->paramkind != PARAM_EXTERN)
234 return true;
237 * Report IDs of PARAM_EXTERN Params. We don't bother to
238 * eliminate duplicate list elements here; classifyConditions
239 * will do that.
241 context->param_numbers = lappend_int(context->param_numbers,
242 p->paramid);
244 break;
245 case T_ArrayRef:
247 ArrayRef *ar = (ArrayRef *) node;;
249 /* Assignment should not be in restrictions. */
250 if (ar->refassgnexpr != NULL)
251 return true;
253 break;
254 case T_FuncExpr:
257 * If function used by the expression is not built-in, it
258 * can't be sent to remote because it might have incompatible
259 * semantics on remote side.
261 FuncExpr *fe = (FuncExpr *) node;
263 if (!is_builtin(fe->funcid))
264 return true;
266 break;
267 case T_OpExpr:
268 case T_DistinctExpr: /* struct-equivalent to OpExpr */
271 * Similarly, only built-in operators can be sent to remote.
272 * (If the operator is, surely its underlying function is
273 * too.)
275 OpExpr *oe = (OpExpr *) node;
277 if (!is_builtin(oe->opno))
278 return true;
280 break;
281 case T_ScalarArrayOpExpr:
284 * Again, only built-in operators can be sent to remote.
286 ScalarArrayOpExpr *oe = (ScalarArrayOpExpr *) node;
288 if (!is_builtin(oe->opno))
289 return true;
291 break;
292 case T_RelabelType:
293 case T_BoolExpr:
294 case T_NullTest:
295 case T_ArrayExpr:
296 /* OK */
297 break;
298 case T_List:
301 * We need only fall through to let expression_tree_walker scan
302 * the list elements --- but don't apply exprType() to the list.
304 check_type = false;
305 break;
306 default:
309 * If it's anything else, assume it's unsafe. This list can be
310 * expanded later, but don't forget to add deparse support below.
312 return true;
316 * If result type of given expression is not built-in, it can't be sent to
317 * remote because it might have incompatible semantics on remote side.
319 if (check_type && !is_builtin(exprType(node)))
320 return true;
322 /* Recurse to examine sub-nodes */
323 return expression_tree_walker(node, foreign_expr_walker, context);
327 * Return true if given object is one of PostgreSQL's built-in objects.
329 * We use FirstBootstrapObjectId as the cutoff, so that we only consider
330 * objects with hand-assigned OIDs to be "built in", not for instance any
331 * function or type defined in the information_schema.
333 * Our constraints for dealing with types are tighter than they are for
334 * functions or operators: we want to accept only types that are in pg_catalog,
335 * else format_type might incorrectly fail to schema-qualify their names.
336 * (This could be fixed with some changes to format_type, but for now there's
337 * no need.) Thus we must exclude information_schema types.
339 * XXX there is a problem with this, which is that the set of built-in
340 * objects expands over time. Something that is built-in to us might not
341 * be known to the remote server, if it's of an older version. But keeping
342 * track of that would be a huge exercise.
344 static bool
345 is_builtin(Oid oid)
347 return (oid < FirstBootstrapObjectId);
352 * Construct a simple SELECT statement that retrieves interesting columns
353 * of the specified foreign table, and append it to "buf". The output
354 * contains just "SELECT ... FROM tablename".
356 * "Interesting" columns are those appearing in the rel's targetlist or
357 * in local_conds (conditions which can't be executed remotely).
359 void
360 deparseSimpleSql(StringInfo buf,
361 PlannerInfo *root,
362 RelOptInfo *baserel,
363 List *local_conds)
365 RangeTblEntry *rte = root->simple_rte_array[baserel->relid];
366 Bitmapset *attrs_used = NULL;
367 bool have_wholerow;
368 bool first;
369 AttrNumber attr;
370 ListCell *lc;
372 /* Collect all the attributes needed for joins or final output. */
373 pull_varattnos((Node *) baserel->reltargetlist, baserel->relid,
374 &attrs_used);
376 /* Add all the attributes used by local_conds. */
377 foreach(lc, local_conds)
379 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
381 pull_varattnos((Node *) rinfo->clause, baserel->relid,
382 &attrs_used);
385 /* If there's a whole-row reference, we'll need all the columns. */
386 have_wholerow = bms_is_member(0 - FirstLowInvalidHeapAttributeNumber,
387 attrs_used);
390 * Construct SELECT list
392 * We list attributes in order of the foreign table's columns, but replace
393 * any attributes that need not be fetched with NULL constants. (We can't
394 * just omit such attributes, or we'll lose track of which columns are
395 * which at runtime.) Note however that any dropped columns are ignored.
397 appendStringInfo(buf, "SELECT ");
398 first = true;
399 for (attr = 1; attr <= baserel->max_attr; attr++)
401 /* Ignore dropped attributes. */
402 if (get_rte_attribute_is_dropped(rte, attr))
403 continue;
405 if (!first)
406 appendStringInfo(buf, ", ");
407 first = false;
409 if (have_wholerow ||
410 bms_is_member(attr - FirstLowInvalidHeapAttributeNumber,
411 attrs_used))
412 deparseColumnRef(buf, baserel->relid, attr, root);
413 else
414 appendStringInfo(buf, "NULL");
417 /* Don't generate bad syntax if no undropped columns */
418 if (first)
419 appendStringInfo(buf, "NULL");
422 * Construct FROM clause
424 appendStringInfo(buf, " FROM ");
425 deparseRelation(buf, rte->relid);
429 * Deparse WHERE clauses in given list of RestrictInfos and append them to buf.
431 * If no WHERE clause already exists in the buffer, is_first should be true.
433 void
434 appendWhereClause(StringInfo buf,
435 bool is_first,
436 List *exprs,
437 PlannerInfo *root)
439 ListCell *lc;
441 foreach(lc, exprs)
443 RestrictInfo *ri = (RestrictInfo *) lfirst(lc);
445 /* Connect expressions with "AND" and parenthesize each condition. */
446 if (is_first)
447 appendStringInfo(buf, " WHERE ");
448 else
449 appendStringInfo(buf, " AND ");
451 appendStringInfoChar(buf, '(');
452 deparseExpr(buf, ri->clause, root);
453 appendStringInfoChar(buf, ')');
455 is_first = false;
460 * Construct SELECT statement to acquire size in blocks of given relation.
462 * Note: we use local definition of block size, not remote definition.
463 * This is perhaps debatable.
465 * Note: pg_relation_size() exists in 8.1 and later.
467 void
468 deparseAnalyzeSizeSql(StringInfo buf, Relation rel)
470 Oid relid = RelationGetRelid(rel);
471 StringInfoData relname;
473 /* We'll need the remote relation name as a literal. */
474 initStringInfo(&relname);
475 deparseRelation(&relname, relid);
477 appendStringInfo(buf, "SELECT pg_catalog.pg_relation_size(");
478 deparseStringLiteral(buf, relname.data);
479 appendStringInfo(buf, "::pg_catalog.regclass) / %d", BLCKSZ);
483 * Construct SELECT statement to acquire sample rows of given relation.
485 * Note: command is appended to whatever might be in buf already.
487 void
488 deparseAnalyzeSql(StringInfo buf, Relation rel)
490 Oid relid = RelationGetRelid(rel);
491 TupleDesc tupdesc = RelationGetDescr(rel);
492 int i;
493 char *colname;
494 List *options;
495 ListCell *lc;
496 bool first = true;
498 appendStringInfo(buf, "SELECT ");
499 for (i = 0; i < tupdesc->natts; i++)
501 /* Ignore dropped columns. */
502 if (tupdesc->attrs[i]->attisdropped)
503 continue;
505 /* Use attribute name or column_name option. */
506 colname = NameStr(tupdesc->attrs[i]->attname);
507 options = GetForeignColumnOptions(relid, i + 1);
509 foreach(lc, options)
511 DefElem *def = (DefElem *) lfirst(lc);
513 if (strcmp(def->defname, "column_name") == 0)
515 colname = defGetString(def);
516 break;
520 if (!first)
521 appendStringInfo(buf, ", ");
522 appendStringInfoString(buf, quote_identifier(colname));
523 first = false;
526 /* Don't generate bad syntax for zero-column relation. */
527 if (first)
528 appendStringInfo(buf, "NULL");
531 * Construct FROM clause
533 appendStringInfo(buf, " FROM ");
534 deparseRelation(buf, relid);
538 * Construct name to use for given column, and emit it into buf.
539 * If it has a column_name FDW option, use that instead of attribute name.
541 static void
542 deparseColumnRef(StringInfo buf, int varno, int varattno, PlannerInfo *root)
544 RangeTblEntry *rte;
545 char *colname = NULL;
546 List *options;
547 ListCell *lc;
549 /* varno must not be any of OUTER_VAR, INNER_VAR and INDEX_VAR. */
550 Assert(varno >= 1 && varno <= root->simple_rel_array_size);
552 /* Get RangeTblEntry from array in PlannerInfo. */
553 rte = root->simple_rte_array[varno];
556 * If it's a column of a foreign table, and it has the column_name FDW
557 * option, use that value.
559 options = GetForeignColumnOptions(rte->relid, varattno);
560 foreach(lc, options)
562 DefElem *def = (DefElem *) lfirst(lc);
564 if (strcmp(def->defname, "column_name") == 0)
566 colname = defGetString(def);
567 break;
572 * If it's a column of a regular table or it doesn't have column_name FDW
573 * option, use attribute name.
575 if (colname == NULL)
576 colname = get_relid_attribute_name(rte->relid, varattno);
578 appendStringInfoString(buf, quote_identifier(colname));
582 * Append remote name of specified foreign table to buf.
583 * Use value of table_name FDW option (if any) instead of relation's name.
584 * Similarly, schema_name FDW option overrides schema name.
586 static void
587 deparseRelation(StringInfo buf, Oid relid)
589 ForeignTable *table;
590 const char *nspname = NULL;
591 const char *relname = NULL;
592 ListCell *lc;
594 /* obtain additional catalog information. */
595 table = GetForeignTable(relid);
598 * Use value of FDW options if any, instead of the name of object itself.
600 foreach(lc, table->options)
602 DefElem *def = (DefElem *) lfirst(lc);
604 if (strcmp(def->defname, "schema_name") == 0)
605 nspname = defGetString(def);
606 else if (strcmp(def->defname, "table_name") == 0)
607 relname = defGetString(def);
611 * Note: we could skip printing the schema name if it's pg_catalog,
612 * but that doesn't seem worth the trouble.
614 if (nspname == NULL)
615 nspname = get_namespace_name(get_rel_namespace(relid));
616 if (relname == NULL)
617 relname = get_rel_name(relid);
619 appendStringInfo(buf, "%s.%s",
620 quote_identifier(nspname), quote_identifier(relname));
624 * Append a SQL string literal representing "val" to buf.
626 static void
627 deparseStringLiteral(StringInfo buf, const char *val)
629 const char *valptr;
632 * Rather than making assumptions about the remote server's value of
633 * standard_conforming_strings, always use E'foo' syntax if there are any
634 * backslashes. This will fail on remote servers before 8.1, but those
635 * are long out of support.
637 if (strchr(val, '\\') != NULL)
638 appendStringInfoChar(buf, ESCAPE_STRING_SYNTAX);
639 appendStringInfoChar(buf, '\'');
640 for (valptr = val; *valptr; valptr++)
642 char ch = *valptr;
644 if (SQL_STR_DOUBLE(ch, true))
645 appendStringInfoChar(buf, ch);
646 appendStringInfoChar(buf, ch);
648 appendStringInfoChar(buf, '\'');
652 * Deparse given expression into buf.
654 * This function must support all the same node types that foreign_expr_walker
655 * accepts.
657 * Note: unlike ruleutils.c, we just use a simple hard-wired parenthesization
658 * scheme: anything more complex than a Var, Const, function call or cast
659 * should be self-parenthesized.
661 static void
662 deparseExpr(StringInfo buf, Expr *node, PlannerInfo *root)
664 if (node == NULL)
665 return;
667 switch (nodeTag(node))
669 case T_Var:
670 deparseVar(buf, (Var *) node, root);
671 break;
672 case T_Const:
673 deparseConst(buf, (Const *) node, root);
674 break;
675 case T_Param:
676 deparseParam(buf, (Param *) node, root);
677 break;
678 case T_ArrayRef:
679 deparseArrayRef(buf, (ArrayRef *) node, root);
680 break;
681 case T_FuncExpr:
682 deparseFuncExpr(buf, (FuncExpr *) node, root);
683 break;
684 case T_OpExpr:
685 deparseOpExpr(buf, (OpExpr *) node, root);
686 break;
687 case T_DistinctExpr:
688 deparseDistinctExpr(buf, (DistinctExpr *) node, root);
689 break;
690 case T_ScalarArrayOpExpr:
691 deparseScalarArrayOpExpr(buf, (ScalarArrayOpExpr *) node, root);
692 break;
693 case T_RelabelType:
694 deparseRelabelType(buf, (RelabelType *) node, root);
695 break;
696 case T_BoolExpr:
697 deparseBoolExpr(buf, (BoolExpr *) node, root);
698 break;
699 case T_NullTest:
700 deparseNullTest(buf, (NullTest *) node, root);
701 break;
702 case T_ArrayExpr:
703 deparseArrayExpr(buf, (ArrayExpr *) node, root);
704 break;
705 default:
706 elog(ERROR, "unsupported expression type for deparse: %d",
707 (int) nodeTag(node));
708 break;
713 * Deparse given Var node into buf.
715 static void
716 deparseVar(StringInfo buf, Var *node, PlannerInfo *root)
718 Assert(node->varlevelsup == 0);
719 deparseColumnRef(buf, node->varno, node->varattno, root);
723 * Deparse given constant value into buf.
725 * This function has to be kept in sync with ruleutils.c's get_const_expr.
727 static void
728 deparseConst(StringInfo buf, Const *node, PlannerInfo *root)
730 Oid typoutput;
731 bool typIsVarlena;
732 char *extval;
733 bool isfloat = false;
734 bool needlabel;
736 if (node->constisnull)
738 appendStringInfo(buf, "NULL");
739 appendStringInfo(buf, "::%s",
740 format_type_with_typemod(node->consttype,
741 node->consttypmod));
742 return;
745 getTypeOutputInfo(node->consttype,
746 &typoutput, &typIsVarlena);
747 extval = OidOutputFunctionCall(typoutput, node->constvalue);
749 switch (node->consttype)
751 case INT2OID:
752 case INT4OID:
753 case INT8OID:
754 case OIDOID:
755 case FLOAT4OID:
756 case FLOAT8OID:
757 case NUMERICOID:
760 * No need to quote unless it's a special value such as 'NaN'.
761 * See comments in get_const_expr().
763 if (strspn(extval, "0123456789+-eE.") == strlen(extval))
765 if (extval[0] == '+' || extval[0] == '-')
766 appendStringInfo(buf, "(%s)", extval);
767 else
768 appendStringInfoString(buf, extval);
769 if (strcspn(extval, "eE.") != strlen(extval))
770 isfloat = true; /* it looks like a float */
772 else
773 appendStringInfo(buf, "'%s'", extval);
775 break;
776 case BITOID:
777 case VARBITOID:
778 appendStringInfo(buf, "B'%s'", extval);
779 break;
780 case BOOLOID:
781 if (strcmp(extval, "t") == 0)
782 appendStringInfoString(buf, "true");
783 else
784 appendStringInfoString(buf, "false");
785 break;
786 default:
787 deparseStringLiteral(buf, extval);
788 break;
792 * Append ::typename unless the constant will be implicitly typed as the
793 * right type when it is read in.
795 * XXX this code has to be kept in sync with the behavior of the parser,
796 * especially make_const.
798 switch (node->consttype)
800 case BOOLOID:
801 case INT4OID:
802 case UNKNOWNOID:
803 needlabel = false;
804 break;
805 case NUMERICOID:
806 needlabel = !isfloat || (node->consttypmod >= 0);
807 break;
808 default:
809 needlabel = true;
810 break;
812 if (needlabel)
813 appendStringInfo(buf, "::%s",
814 format_type_with_typemod(node->consttype,
815 node->consttypmod));
819 * Deparse given Param node into buf.
821 * We don't need to renumber the parameter ID, because the executor functions
822 * in postgres_fdw.c preserve the numbering of PARAM_EXTERN Params.
823 * (This might change soon.)
825 * Note: we label the Param's type explicitly rather than relying on
826 * transmitting a numeric type OID in PQexecParams(). This allows us to
827 * avoid assuming that types have the same OIDs on the remote side as they
828 * do locally --- they need only have the same names.
830 static void
831 deparseParam(StringInfo buf, Param *node, PlannerInfo *root)
833 Assert(node->paramkind == PARAM_EXTERN);
834 appendStringInfo(buf, "$%d", node->paramid);
835 appendStringInfo(buf, "::%s",
836 format_type_with_typemod(node->paramtype,
837 node->paramtypmod));
841 * Deparse an array subscript expression.
843 static void
844 deparseArrayRef(StringInfo buf, ArrayRef *node, PlannerInfo *root)
846 ListCell *lowlist_item;
847 ListCell *uplist_item;
849 /* Always parenthesize the expression. */
850 appendStringInfoChar(buf, '(');
853 * Deparse referenced array expression first. If that expression includes
854 * a cast, we have to parenthesize to prevent the array subscript from
855 * being taken as typename decoration. We can avoid that in the typical
856 * case of subscripting a Var, but otherwise do it.
858 if (IsA(node->refexpr, Var))
859 deparseExpr(buf, node->refexpr, root);
860 else
862 appendStringInfoChar(buf, '(');
863 deparseExpr(buf, node->refexpr, root);
864 appendStringInfoChar(buf, ')');
867 /* Deparse subscript expressions. */
868 lowlist_item = list_head(node->reflowerindexpr); /* could be NULL */
869 foreach(uplist_item, node->refupperindexpr)
871 appendStringInfoChar(buf, '[');
872 if (lowlist_item)
874 deparseExpr(buf, lfirst(lowlist_item), root);
875 appendStringInfoChar(buf, ':');
876 lowlist_item = lnext(lowlist_item);
878 deparseExpr(buf, lfirst(uplist_item), root);
879 appendStringInfoChar(buf, ']');
882 appendStringInfoChar(buf, ')');
886 * Deparse given node which represents a function call into buf.
888 static void
889 deparseFuncExpr(StringInfo buf, FuncExpr *node, PlannerInfo *root)
891 HeapTuple proctup;
892 Form_pg_proc procform;
893 const char *proname;
894 bool use_variadic;
895 bool first;
896 ListCell *arg;
899 * If the function call came from an implicit coercion, then just show the
900 * first argument.
902 if (node->funcformat == COERCE_IMPLICIT_CAST)
904 deparseExpr(buf, (Expr *) linitial(node->args), root);
905 return;
909 * If the function call came from a cast, then show the first argument
910 * plus an explicit cast operation.
912 if (node->funcformat == COERCE_EXPLICIT_CAST)
914 Oid rettype = node->funcresulttype;
915 int32 coercedTypmod;
917 /* Get the typmod if this is a length-coercion function */
918 (void) exprIsLengthCoercion((Node *) node, &coercedTypmod);
920 deparseExpr(buf, (Expr *) linitial(node->args), root);
921 appendStringInfo(buf, "::%s",
922 format_type_with_typemod(rettype, coercedTypmod));
923 return;
927 * Normal function: display as proname(args).
929 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(node->funcid));
930 if (!HeapTupleIsValid(proctup))
931 elog(ERROR, "cache lookup failed for function %u", node->funcid);
932 procform = (Form_pg_proc) GETSTRUCT(proctup);
934 /* Check if need to print VARIADIC (cf. ruleutils.c) */
935 if (OidIsValid(procform->provariadic))
937 if (procform->provariadic != ANYOID)
938 use_variadic = true;
939 else
940 use_variadic = node->funcvariadic;
942 else
943 use_variadic = false;
945 /* Print schema name only if it's not pg_catalog */
946 if (procform->pronamespace != PG_CATALOG_NAMESPACE)
948 const char *schemaname;
950 schemaname = get_namespace_name(procform->pronamespace);
951 appendStringInfo(buf, "%s.", quote_identifier(schemaname));
954 /* Deparse the function name ... */
955 proname = NameStr(procform->proname);
956 appendStringInfo(buf, "%s(", quote_identifier(proname));
957 /* ... and all the arguments */
958 first = true;
959 foreach(arg, node->args)
961 if (!first)
962 appendStringInfoString(buf, ", ");
963 if (use_variadic && lnext(arg) == NULL)
964 appendStringInfoString(buf, "VARIADIC ");
965 deparseExpr(buf, (Expr *) lfirst(arg), root);
966 first = false;
968 appendStringInfoChar(buf, ')');
970 ReleaseSysCache(proctup);
974 * Deparse given operator expression into buf. To avoid problems around
975 * priority of operations, we always parenthesize the arguments.
977 static void
978 deparseOpExpr(StringInfo buf, OpExpr *node, PlannerInfo *root)
980 HeapTuple tuple;
981 Form_pg_operator form;
982 char oprkind;
983 ListCell *arg;
985 /* Retrieve information about the operator from system catalog. */
986 tuple = SearchSysCache1(OPEROID, ObjectIdGetDatum(node->opno));
987 if (!HeapTupleIsValid(tuple))
988 elog(ERROR, "cache lookup failed for operator %u", node->opno);
989 form = (Form_pg_operator) GETSTRUCT(tuple);
990 oprkind = form->oprkind;
992 /* Sanity check. */
993 Assert((oprkind == 'r' && list_length(node->args) == 1) ||
994 (oprkind == 'l' && list_length(node->args) == 1) ||
995 (oprkind == 'b' && list_length(node->args) == 2));
997 /* Always parenthesize the expression. */
998 appendStringInfoChar(buf, '(');
1000 /* Deparse left operand. */
1001 if (oprkind == 'r' || oprkind == 'b')
1003 arg = list_head(node->args);
1004 deparseExpr(buf, lfirst(arg), root);
1005 appendStringInfoChar(buf, ' ');
1008 /* Deparse operator name. */
1009 deparseOperatorName(buf, form);
1011 /* Deparse right operand. */
1012 if (oprkind == 'l' || oprkind == 'b')
1014 arg = list_tail(node->args);
1015 appendStringInfoChar(buf, ' ');
1016 deparseExpr(buf, lfirst(arg), root);
1019 appendStringInfoChar(buf, ')');
1021 ReleaseSysCache(tuple);
1025 * Print the name of an operator.
1027 static void
1028 deparseOperatorName(StringInfo buf, Form_pg_operator opform)
1030 char *opname;
1032 /* opname is not a SQL identifier, so we should not quote it. */
1033 opname = NameStr(opform->oprname);
1035 /* Print schema name only if it's not pg_catalog */
1036 if (opform->oprnamespace != PG_CATALOG_NAMESPACE)
1038 const char *opnspname;
1040 opnspname = get_namespace_name(opform->oprnamespace);
1041 /* Print fully qualified operator name. */
1042 appendStringInfo(buf, "OPERATOR(%s.%s)",
1043 quote_identifier(opnspname), opname);
1045 else
1047 /* Just print operator name. */
1048 appendStringInfo(buf, "%s", opname);
1053 * Deparse IS DISTINCT FROM.
1055 static void
1056 deparseDistinctExpr(StringInfo buf, DistinctExpr *node, PlannerInfo *root)
1058 Assert(list_length(node->args) == 2);
1060 appendStringInfoChar(buf, '(');
1061 deparseExpr(buf, linitial(node->args), root);
1062 appendStringInfo(buf, " IS DISTINCT FROM ");
1063 deparseExpr(buf, lsecond(node->args), root);
1064 appendStringInfoChar(buf, ')');
1068 * Deparse given ScalarArrayOpExpr expression into buf. To avoid problems
1069 * around priority of operations, we always parenthesize the arguments.
1071 static void
1072 deparseScalarArrayOpExpr(StringInfo buf,
1073 ScalarArrayOpExpr *node,
1074 PlannerInfo *root)
1076 HeapTuple tuple;
1077 Form_pg_operator form;
1078 Expr *arg1;
1079 Expr *arg2;
1081 /* Retrieve information about the operator from system catalog. */
1082 tuple = SearchSysCache1(OPEROID, ObjectIdGetDatum(node->opno));
1083 if (!HeapTupleIsValid(tuple))
1084 elog(ERROR, "cache lookup failed for operator %u", node->opno);
1085 form = (Form_pg_operator) GETSTRUCT(tuple);
1087 /* Sanity check. */
1088 Assert(list_length(node->args) == 2);
1090 /* Always parenthesize the expression. */
1091 appendStringInfoChar(buf, '(');
1093 /* Deparse left operand. */
1094 arg1 = linitial(node->args);
1095 deparseExpr(buf, arg1, root);
1096 appendStringInfoChar(buf, ' ');
1098 /* Deparse operator name plus decoration. */
1099 deparseOperatorName(buf, form);
1100 appendStringInfo(buf, " %s (", node->useOr ? "ANY" : "ALL");
1102 /* Deparse right operand. */
1103 arg2 = lsecond(node->args);
1104 deparseExpr(buf, arg2, root);
1106 appendStringInfoChar(buf, ')');
1108 /* Always parenthesize the expression. */
1109 appendStringInfoChar(buf, ')');
1111 ReleaseSysCache(tuple);
1115 * Deparse a RelabelType (binary-compatible cast) node.
1117 static void
1118 deparseRelabelType(StringInfo buf, RelabelType *node, PlannerInfo *root)
1120 deparseExpr(buf, node->arg, root);
1121 if (node->relabelformat != COERCE_IMPLICIT_CAST)
1122 appendStringInfo(buf, "::%s",
1123 format_type_with_typemod(node->resulttype,
1124 node->resulttypmod));
1128 * Deparse a BoolExpr node.
1130 * Note: by the time we get here, AND and OR expressions have been flattened
1131 * into N-argument form, so we'd better be prepared to deal with that.
1133 static void
1134 deparseBoolExpr(StringInfo buf, BoolExpr *node, PlannerInfo *root)
1136 const char *op = NULL; /* keep compiler quiet */
1137 bool first;
1138 ListCell *lc;
1140 switch (node->boolop)
1142 case AND_EXPR:
1143 op = "AND";
1144 break;
1145 case OR_EXPR:
1146 op = "OR";
1147 break;
1148 case NOT_EXPR:
1149 appendStringInfo(buf, "(NOT ");
1150 deparseExpr(buf, linitial(node->args), root);
1151 appendStringInfoChar(buf, ')');
1152 return;
1155 appendStringInfoChar(buf, '(');
1156 first = true;
1157 foreach(lc, node->args)
1159 if (!first)
1160 appendStringInfo(buf, " %s ", op);
1161 deparseExpr(buf, (Expr *) lfirst(lc), root);
1162 first = false;
1164 appendStringInfoChar(buf, ')');
1168 * Deparse IS [NOT] NULL expression.
1170 static void
1171 deparseNullTest(StringInfo buf, NullTest *node, PlannerInfo *root)
1173 appendStringInfoChar(buf, '(');
1174 deparseExpr(buf, node->arg, root);
1175 if (node->nulltesttype == IS_NULL)
1176 appendStringInfo(buf, " IS NULL)");
1177 else
1178 appendStringInfo(buf, " IS NOT NULL)");
1182 * Deparse ARRAY[...] construct.
1184 static void
1185 deparseArrayExpr(StringInfo buf, ArrayExpr *node, PlannerInfo *root)
1187 bool first = true;
1188 ListCell *lc;
1190 appendStringInfo(buf, "ARRAY[");
1191 foreach(lc, node->elements)
1193 if (!first)
1194 appendStringInfo(buf, ", ");
1195 deparseExpr(buf, lfirst(lc), root);
1196 first = false;
1198 appendStringInfoChar(buf, ']');
1200 /* If the array is empty, we need an explicit cast to the array type. */
1201 if (node->elements == NIL)
1202 appendStringInfo(buf, "::%s",
1203 format_type_with_typemod(node->array_typeid, -1));