1 /*-------------------------------------------------------------------------
4 * Query deparser for postgres_fdw
6 * This file includes functions that examine query WHERE clauses to see
7 * whether they're safe to send to the remote server for execution, as
8 * well as functions to construct the query text to be sent. The latter
9 * functionality is annoyingly duplicative of ruleutils.c, but there are
10 * enough special considerations that it seems best to keep this separate.
11 * One saving grace is that we only need deparse logic for node types that
12 * we consider safe to send.
14 * We assume that the remote session's search_path is exactly "pg_catalog",
15 * and thus we need schema-qualify all and only names outside pg_catalog.
17 * Portions Copyright (c) 2012-2013, PostgreSQL Global Development Group
20 * contrib/postgres_fdw/deparse.c
22 *-------------------------------------------------------------------------
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
52 RelOptInfo
*foreignrel
;
54 List
*param_numbers
; /* Param IDs of PARAM_EXTERN Params */
58 * Functions to determine whether an expression can be evaluated safely on
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
,
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
,
83 static void deparseScalarArrayOpExpr(StringInfo buf
, ScalarArrayOpExpr
*node
,
85 static void deparseRelabelType(StringInfo buf
, RelabelType
*node
,
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
,
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.
112 classifyConditions(PlannerInfo
*root
,
117 List
**param_numbers
)
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
);
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
,
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.
155 is_foreign_expr(PlannerInfo
*root
,
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
169 context
.foreignrel
= baserel
;
170 context
.param_numbers
= NIL
;
171 if (foreign_expr_walker((Node
*) expr
, &context
))
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
))
185 * OK, so return list of param IDs too.
187 *param_numbers
= context
.param_numbers
;
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.)
198 foreign_expr_walker(Node
*node
, foreign_expr_cxt
*context
)
200 bool check_type
= true;
205 switch (nodeTag(node
))
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
214 Var
*var
= (Var
*) node
;
216 if (var
->varno
!= context
->foreignrel
->relid
||
217 var
->varlevelsup
!= 0)
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
)
237 * Report IDs of PARAM_EXTERN Params. We don't bother to
238 * eliminate duplicate list elements here; classifyConditions
241 context
->param_numbers
= lappend_int(context
->param_numbers
,
247 ArrayRef
*ar
= (ArrayRef
*) node
;;
249 /* Assignment should not be in restrictions. */
250 if (ar
->refassgnexpr
!= NULL
)
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
))
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
275 OpExpr
*oe
= (OpExpr
*) node
;
277 if (!is_builtin(oe
->opno
))
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
))
301 * We need only fall through to let expression_tree_walker scan
302 * the list elements --- but don't apply exprType() to the list.
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.
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
)))
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.
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).
360 deparseSimpleSql(StringInfo buf
,
365 RangeTblEntry
*rte
= root
->simple_rte_array
[baserel
->relid
];
366 Bitmapset
*attrs_used
= NULL
;
372 /* Collect all the attributes needed for joins or final output. */
373 pull_varattnos((Node
*) baserel
->reltargetlist
, baserel
->relid
,
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
,
385 /* If there's a whole-row reference, we'll need all the columns. */
386 have_wholerow
= bms_is_member(0 - FirstLowInvalidHeapAttributeNumber
,
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 ");
399 for (attr
= 1; attr
<= baserel
->max_attr
; attr
++)
401 /* Ignore dropped attributes. */
402 if (get_rte_attribute_is_dropped(rte
, attr
))
406 appendStringInfo(buf
, ", ");
410 bms_is_member(attr
- FirstLowInvalidHeapAttributeNumber
,
412 deparseColumnRef(buf
, baserel
->relid
, attr
, root
);
414 appendStringInfo(buf
, "NULL");
417 /* Don't generate bad syntax if no undropped columns */
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.
434 appendWhereClause(StringInfo buf
,
443 RestrictInfo
*ri
= (RestrictInfo
*) lfirst(lc
);
445 /* Connect expressions with "AND" and parenthesize each condition. */
447 appendStringInfo(buf
, " WHERE ");
449 appendStringInfo(buf
, " AND ");
451 appendStringInfoChar(buf
, '(');
452 deparseExpr(buf
, ri
->clause
, root
);
453 appendStringInfoChar(buf
, ')');
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.
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.
488 deparseAnalyzeSql(StringInfo buf
, Relation rel
)
490 Oid relid
= RelationGetRelid(rel
);
491 TupleDesc tupdesc
= RelationGetDescr(rel
);
498 appendStringInfo(buf
, "SELECT ");
499 for (i
= 0; i
< tupdesc
->natts
; i
++)
501 /* Ignore dropped columns. */
502 if (tupdesc
->attrs
[i
]->attisdropped
)
505 /* Use attribute name or column_name option. */
506 colname
= NameStr(tupdesc
->attrs
[i
]->attname
);
507 options
= GetForeignColumnOptions(relid
, i
+ 1);
511 DefElem
*def
= (DefElem
*) lfirst(lc
);
513 if (strcmp(def
->defname
, "column_name") == 0)
515 colname
= defGetString(def
);
521 appendStringInfo(buf
, ", ");
522 appendStringInfoString(buf
, quote_identifier(colname
));
526 /* Don't generate bad syntax for zero-column relation. */
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.
542 deparseColumnRef(StringInfo buf
, int varno
, int varattno
, PlannerInfo
*root
)
545 char *colname
= NULL
;
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
);
562 DefElem
*def
= (DefElem
*) lfirst(lc
);
564 if (strcmp(def
->defname
, "column_name") == 0)
566 colname
= defGetString(def
);
572 * If it's a column of a regular table or it doesn't have column_name FDW
573 * option, use attribute name.
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.
587 deparseRelation(StringInfo buf
, Oid relid
)
590 const char *nspname
= NULL
;
591 const char *relname
= NULL
;
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.
615 nspname
= get_namespace_name(get_rel_namespace(relid
));
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.
627 deparseStringLiteral(StringInfo buf
, const char *val
)
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
++)
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
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.
662 deparseExpr(StringInfo buf
, Expr
*node
, PlannerInfo
*root
)
667 switch (nodeTag(node
))
670 deparseVar(buf
, (Var
*) node
, root
);
673 deparseConst(buf
, (Const
*) node
, root
);
676 deparseParam(buf
, (Param
*) node
, root
);
679 deparseArrayRef(buf
, (ArrayRef
*) node
, root
);
682 deparseFuncExpr(buf
, (FuncExpr
*) node
, root
);
685 deparseOpExpr(buf
, (OpExpr
*) node
, root
);
688 deparseDistinctExpr(buf
, (DistinctExpr
*) node
, root
);
690 case T_ScalarArrayOpExpr
:
691 deparseScalarArrayOpExpr(buf
, (ScalarArrayOpExpr
*) node
, root
);
694 deparseRelabelType(buf
, (RelabelType
*) node
, root
);
697 deparseBoolExpr(buf
, (BoolExpr
*) node
, root
);
700 deparseNullTest(buf
, (NullTest
*) node
, root
);
703 deparseArrayExpr(buf
, (ArrayExpr
*) node
, root
);
706 elog(ERROR
, "unsupported expression type for deparse: %d",
707 (int) nodeTag(node
));
713 * Deparse given Var node into buf.
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.
728 deparseConst(StringInfo buf
, Const
*node
, PlannerInfo
*root
)
733 bool isfloat
= false;
736 if (node
->constisnull
)
738 appendStringInfo(buf
, "NULL");
739 appendStringInfo(buf
, "::%s",
740 format_type_with_typemod(node
->consttype
,
745 getTypeOutputInfo(node
->consttype
,
746 &typoutput
, &typIsVarlena
);
747 extval
= OidOutputFunctionCall(typoutput
, node
->constvalue
);
749 switch (node
->consttype
)
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
);
768 appendStringInfoString(buf
, extval
);
769 if (strcspn(extval
, "eE.") != strlen(extval
))
770 isfloat
= true; /* it looks like a float */
773 appendStringInfo(buf
, "'%s'", extval
);
778 appendStringInfo(buf
, "B'%s'", extval
);
781 if (strcmp(extval
, "t") == 0)
782 appendStringInfoString(buf
, "true");
784 appendStringInfoString(buf
, "false");
787 deparseStringLiteral(buf
, extval
);
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
)
806 needlabel
= !isfloat
|| (node
->consttypmod
>= 0);
813 appendStringInfo(buf
, "::%s",
814 format_type_with_typemod(node
->consttype
,
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.
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
,
841 * Deparse an array subscript expression.
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
);
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
, '[');
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.
889 deparseFuncExpr(StringInfo buf
, FuncExpr
*node
, PlannerInfo
*root
)
892 Form_pg_proc procform
;
899 * If the function call came from an implicit coercion, then just show the
902 if (node
->funcformat
== COERCE_IMPLICIT_CAST
)
904 deparseExpr(buf
, (Expr
*) linitial(node
->args
), root
);
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
;
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
));
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
)
940 use_variadic
= node
->funcvariadic
;
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 */
959 foreach(arg
, node
->args
)
962 appendStringInfoString(buf
, ", ");
963 if (use_variadic
&& lnext(arg
) == NULL
)
964 appendStringInfoString(buf
, "VARIADIC ");
965 deparseExpr(buf
, (Expr
*) lfirst(arg
), root
);
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.
978 deparseOpExpr(StringInfo buf
, OpExpr
*node
, PlannerInfo
*root
)
981 Form_pg_operator form
;
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
;
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.
1028 deparseOperatorName(StringInfo buf
, Form_pg_operator opform
)
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
);
1047 /* Just print operator name. */
1048 appendStringInfo(buf
, "%s", opname
);
1053 * Deparse IS DISTINCT FROM.
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.
1072 deparseScalarArrayOpExpr(StringInfo buf
,
1073 ScalarArrayOpExpr
*node
,
1077 Form_pg_operator form
;
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
);
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.
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.
1134 deparseBoolExpr(StringInfo buf
, BoolExpr
*node
, PlannerInfo
*root
)
1136 const char *op
= NULL
; /* keep compiler quiet */
1140 switch (node
->boolop
)
1149 appendStringInfo(buf
, "(NOT ");
1150 deparseExpr(buf
, linitial(node
->args
), root
);
1151 appendStringInfoChar(buf
, ')');
1155 appendStringInfoChar(buf
, '(');
1157 foreach(lc
, node
->args
)
1160 appendStringInfo(buf
, " %s ", op
);
1161 deparseExpr(buf
, (Expr
*) lfirst(lc
), root
);
1164 appendStringInfoChar(buf
, ')');
1168 * Deparse IS [NOT] NULL expression.
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)");
1178 appendStringInfo(buf
, " IS NOT NULL)");
1182 * Deparse ARRAY[...] construct.
1185 deparseArrayExpr(StringInfo buf
, ArrayExpr
*node
, PlannerInfo
*root
)
1190 appendStringInfo(buf
, "ARRAY[");
1191 foreach(lc
, node
->elements
)
1194 appendStringInfo(buf
, ", ");
1195 deparseExpr(buf
, lfirst(lc
), root
);
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));