1 /**********************************************************************
2 * ruleutils.c - Functions to convert stored expressions/querytrees
6 * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.145 2003/07/04 02:51:34 tgl Exp $
8 * This software is copyrighted by Jan Wieck - Hamburg.
10 * The author hereby grants permission to use, copy, modify,
11 * distribute, and license this software and its documentation
12 * for any purpose, provided that existing copyright notices are
13 * retained in all copies and that this notice is included
14 * verbatim in any distributions. No written agreement, license,
15 * or royalty fee is required for any of the authorized uses.
16 * Modifications to this software may be copyrighted by their
17 * author and need not follow the licensing terms described
18 * here, provided that the new terms are clearly indicated on
19 * the first page of each file where they apply.
21 * IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
22 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
23 * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
24 * SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
25 * IF THE AUTHOR HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
28 * THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
30 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
31 * PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON
32 * AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAVE NO
33 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
34 * ENHANCEMENTS, OR MODIFICATIONS.
36 **********************************************************************/
43 #include "access/genam.h"
44 #include "catalog/catname.h"
45 #include "catalog/heap.h"
46 #include "catalog/index.h"
47 #include "catalog/indexing.h"
48 #include "catalog/namespace.h"
49 #include "catalog/pg_cast.h"
50 #include "catalog/pg_constraint.h"
51 #include "catalog/pg_index.h"
52 #include "catalog/pg_opclass.h"
53 #include "catalog/pg_operator.h"
54 #include "catalog/pg_shadow.h"
55 #include "catalog/pg_trigger.h"
56 #include "executor/spi.h"
57 #include "lib/stringinfo.h"
58 #include "nodes/makefuncs.h"
59 #include "optimizer/clauses.h"
60 #include "optimizer/tlist.h"
61 #include "parser/keywords.h"
62 #include "parser/parse_expr.h"
63 #include "parser/parse_func.h"
64 #include "parser/parse_oper.h"
65 #include "parser/parse_type.h"
66 #include "parser/parsetree.h"
67 #include "rewrite/rewriteManip.h"
68 #include "rewrite/rewriteSupport.h"
69 #include "utils/array.h"
70 #include "utils/fmgroids.h"
71 #include "utils/lsyscache.h"
79 /* Context info needed for invoking a recursive querytree display routine */
82 StringInfo buf; /* output buffer to append to */
83 List *namespaces; /* List of deparse_namespace nodes */
84 bool varprefix; /* TRUE to print prefixes on Vars */
88 * Each level of query context around a subtree needs a level of Var namespace.
89 * A Var having varlevelsup=N refers to the N'th item (counting from 0) in
90 * the current context's namespaces list.
92 * The rangetable is the list of actual RTEs from the query tree.
94 * For deparsing plan trees, we allow two special RTE entries that are not
95 * part of the rtable list (mainly because they don't have consecutively
100 List *rtable; /* List of RangeTblEntry nodes */
101 int outer_varno; /* varno for outer_rte */
102 RangeTblEntry *outer_rte; /* special RangeTblEntry, or NULL */
103 int inner_varno; /* varno for inner_rte */
104 RangeTblEntry *inner_rte; /* special RangeTblEntry, or NULL */
112 static void *plan_getrulebyoid = NULL;
113 static char *query_getrulebyoid = "SELECT * FROM pg_catalog.pg_rewrite WHERE oid = $1";
114 static void *plan_getviewrule = NULL;
115 static char *query_getviewrule = "SELECT * FROM pg_catalog.pg_rewrite WHERE ev_class = $1 AND rulename = $2";
121 * Most of these functions used to use fixed-size buffers to build their
122 * results. Now, they take an (already initialized) StringInfo object
123 * as a parameter, and append their text output to its contents.
126 static text *pg_do_getviewdef(Oid viewoid);
127 static void decompile_column_index_array(Datum column_index_array, Oid relId,
129 static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc);
130 static void make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc);
131 static void get_query_def(Query *query, StringInfo buf, List *parentnamespace,
132 TupleDesc resultDesc);
133 static void get_select_query_def(Query *query, deparse_context *context,
134 TupleDesc resultDesc);
135 static void get_insert_query_def(Query *query, deparse_context *context);
136 static void get_update_query_def(Query *query, deparse_context *context);
137 static void get_delete_query_def(Query *query, deparse_context *context);
138 static void get_utility_query_def(Query *query, deparse_context *context);
139 static void get_basic_select_query(Query *query, deparse_context *context,
140 TupleDesc resultDesc);
141 static void get_setop_query(Node *setOp, Query *query,
142 deparse_context *context,
143 TupleDesc resultDesc);
144 static Node *get_rule_sortgroupclause(SortClause *srt, List *tlist,
146 deparse_context *context);
147 static void get_names_for_var(Var *var, deparse_context *context,
148 char **schemaname, char **refname, char **attname);
149 static RangeTblEntry *find_rte_by_refname(const char *refname,
150 deparse_context *context);
151 static void get_rule_expr(Node *node, deparse_context *context,
153 static void get_oper_expr(OpExpr *expr, deparse_context *context);
154 static void get_func_expr(FuncExpr *expr, deparse_context *context,
156 static void get_agg_expr(Aggref *aggref, deparse_context *context);
157 static Node *strip_type_coercion(Node *expr, Oid resultType);
158 static void get_const_expr(Const *constval, deparse_context *context);
159 static void get_sublink_expr(SubLink *sublink, deparse_context *context);
160 static void get_from_clause(Query *query, deparse_context *context);
161 static void get_from_clause_item(Node *jtnode, Query *query,
162 deparse_context *context);
163 static void get_from_clause_coldeflist(List *coldeflist,
164 deparse_context *context);
165 static void get_opclass_name(Oid opclass, Oid actual_datatype,
167 static bool tleIsArrayAssign(TargetEntry *tle);
168 static char *generate_relation_name(Oid relid);
169 static char *generate_function_name(Oid funcid, int nargs, Oid *argtypes);
170 static char *generate_operator_name(Oid operid, Oid arg1, Oid arg2);
171 static void print_operator_name(StringInfo buf, List *opname);
172 static char *get_relid_attribute_name(Oid relid, AttrNumber attnum);
174 #define only_marker(rte) ((rte)->inh ? "" : "ONLY ")
178 * get_ruledef - Do it all and return a text
179 * that could be used as a statement
180 * to recreate the rule
184 pg_get_ruledef(PG_FUNCTION_ARGS)
186 Oid ruleoid = PG_GETARG_OID(0);
197 * Connect to SPI manager
199 if (SPI_connect() != SPI_OK_CONNECT)
200 elog(ERROR, "get_ruledef: cannot connect to SPI manager");
203 * On the first call prepare the plan to lookup pg_rewrite. We read
204 * pg_rewrite over the SPI manager instead of using the syscache to be
205 * checked for read access on pg_rewrite.
207 if (plan_getrulebyoid == NULL)
212 argtypes[0] = OIDOID;
213 plan = SPI_prepare(query_getrulebyoid, 1, argtypes);
215 elog(ERROR, "SPI_prepare() failed for \"%s\"", query_getrulebyoid);
216 plan_getrulebyoid = SPI_saveplan(plan);
220 * Get the pg_rewrite tuple for this rule
222 args[0] = ObjectIdGetDatum(ruleoid);
224 spirc = SPI_execp(plan_getrulebyoid, args, nulls, 1);
225 if (spirc != SPI_OK_SELECT)
226 elog(ERROR, "failed to get pg_rewrite tuple for %u", ruleoid);
227 if (SPI_processed != 1)
229 if (SPI_finish() != SPI_OK_FINISH)
230 elog(ERROR, "get_ruledef: SPI_finish() failed");
231 ruledef = palloc(VARHDRSZ + 1);
232 VARATT_SIZEP(ruledef) = VARHDRSZ + 1;
233 VARDATA(ruledef)[0] = '-';
234 PG_RETURN_TEXT_P(ruledef);
237 ruletup = SPI_tuptable->vals[0];
238 rulettc = SPI_tuptable->tupdesc;
241 * Get the rules definition and put it into executors memory
243 initStringInfo(&buf);
244 make_ruledef(&buf, ruletup, rulettc);
245 len = buf.len + VARHDRSZ;
246 ruledef = SPI_palloc(len);
247 VARATT_SIZEP(ruledef) = len;
248 memcpy(VARDATA(ruledef), buf.data, buf.len);
252 * Disconnect from SPI manager
254 if (SPI_finish() != SPI_OK_FINISH)
255 elog(ERROR, "get_ruledef: SPI_finish() failed");
260 PG_RETURN_TEXT_P(ruledef);
265 * get_viewdef - Mainly the same thing, but we
266 * only return the SELECT part of a view
270 pg_get_viewdef(PG_FUNCTION_ARGS)
273 Oid viewoid = PG_GETARG_OID(0);
276 ruledef = pg_do_getviewdef(viewoid);
277 PG_RETURN_TEXT_P(ruledef);
281 pg_get_viewdef_name(PG_FUNCTION_ARGS)
283 /* By qualified name */
284 text *viewname = PG_GETARG_TEXT_P(0);
289 viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname,
291 viewoid = RangeVarGetRelid(viewrel, false);
293 ruledef = pg_do_getviewdef(viewoid);
294 PG_RETURN_TEXT_P(ruledef);
298 * Common code for by-OID and by-name variants of pg_get_viewdef
301 pg_do_getviewdef(Oid viewoid)
313 * Connect to SPI manager
315 if (SPI_connect() != SPI_OK_CONNECT)
316 elog(ERROR, "get_viewdef: cannot connect to SPI manager");
319 * On the first call prepare the plan to lookup pg_rewrite. We read
320 * pg_rewrite over the SPI manager instead of using the syscache to be
321 * checked for read access on pg_rewrite.
323 if (plan_getviewrule == NULL)
328 argtypes[0] = OIDOID;
329 argtypes[1] = NAMEOID;
330 plan = SPI_prepare(query_getviewrule, 2, argtypes);
332 elog(ERROR, "SPI_prepare() failed for \"%s\"", query_getviewrule);
333 plan_getviewrule = SPI_saveplan(plan);
337 * Get the pg_rewrite tuple for the view's SELECT rule
339 args[0] = ObjectIdGetDatum(viewoid);
340 args[1] = PointerGetDatum(ViewSelectRuleName);
343 spirc = SPI_execp(plan_getviewrule, args, nulls, 2);
344 if (spirc != SPI_OK_SELECT)
345 elog(ERROR, "failed to get pg_rewrite tuple for view %u", viewoid);
346 initStringInfo(&buf);
347 if (SPI_processed != 1)
348 appendStringInfo(&buf, "Not a view");
352 * Get the rules definition and put it into executors memory
354 ruletup = SPI_tuptable->vals[0];
355 rulettc = SPI_tuptable->tupdesc;
356 make_viewdef(&buf, ruletup, rulettc);
358 len = buf.len + VARHDRSZ;
359 ruledef = SPI_palloc(len);
360 VARATT_SIZEP(ruledef) = len;
361 memcpy(VARDATA(ruledef), buf.data, buf.len);
365 * Disconnect from SPI manager
367 if (SPI_finish() != SPI_OK_FINISH)
368 elog(ERROR, "get_viewdef: SPI_finish() failed");
374 * get_triggerdef - Get the definition of a trigger
378 pg_get_triggerdef(PG_FUNCTION_ARGS)
380 Oid trigid = PG_GETARG_OID(0);
383 Form_pg_trigger trigrec;
393 * Fetch the pg_trigger tuple by the Oid of the trigger
395 tgrel = heap_openr(TriggerRelationName, AccessShareLock);
397 ScanKeyEntryInitialize(&skey[0], 0x0,
398 ObjectIdAttributeNumber, F_OIDEQ,
399 ObjectIdGetDatum(trigid));
401 tgscan = systable_beginscan(tgrel, TriggerOidIndex, true,
402 SnapshotNow, 1, skey);
404 ht_trig = systable_getnext(tgscan);
406 if (!HeapTupleIsValid(ht_trig))
407 elog(ERROR, "pg_get_triggerdef: there is no trigger with oid %u",
410 trigrec = (Form_pg_trigger) GETSTRUCT(ht_trig);
413 * Start the trigger definition. Note that the trigger's name should
414 * never be schema-qualified, but the trigger rel's name may be.
416 initStringInfo(&buf);
418 tgname = NameStr(trigrec->tgname);
419 appendStringInfo(&buf, "CREATE %sTRIGGER %s ",
420 trigrec->tgisconstraint ? "CONSTRAINT " : "",
421 quote_identifier(tgname));
423 if (TRIGGER_FOR_BEFORE(trigrec->tgtype))
424 appendStringInfo(&buf, "BEFORE");
426 appendStringInfo(&buf, "AFTER");
427 if (TRIGGER_FOR_INSERT(trigrec->tgtype))
429 appendStringInfo(&buf, " INSERT");
432 if (TRIGGER_FOR_DELETE(trigrec->tgtype))
435 appendStringInfo(&buf, " OR DELETE");
437 appendStringInfo(&buf, " DELETE");
440 if (TRIGGER_FOR_UPDATE(trigrec->tgtype))
443 appendStringInfo(&buf, " OR UPDATE");
445 appendStringInfo(&buf, " UPDATE");
447 appendStringInfo(&buf, " ON %s ",
448 generate_relation_name(trigrec->tgrelid));
450 if (trigrec->tgisconstraint)
452 if (trigrec->tgconstrrelid != InvalidOid)
453 appendStringInfo(&buf, "FROM %s ",
454 generate_relation_name(trigrec->tgconstrrelid));
455 if (!trigrec->tgdeferrable)
456 appendStringInfo(&buf, "NOT ");
457 appendStringInfo(&buf, "DEFERRABLE INITIALLY ");
458 if (trigrec->tginitdeferred)
459 appendStringInfo(&buf, "DEFERRED ");
461 appendStringInfo(&buf, "IMMEDIATE ");
465 if (TRIGGER_FOR_ROW(trigrec->tgtype))
466 appendStringInfo(&buf, "FOR EACH ROW ");
468 appendStringInfo(&buf, "FOR EACH STATEMENT ");
470 appendStringInfo(&buf, "EXECUTE PROCEDURE %s(",
471 generate_function_name(trigrec->tgfoid, 0, NULL));
473 if (trigrec->tgnargs > 0)
480 val = (bytea *) fastgetattr(ht_trig,
481 Anum_pg_trigger_tgargs,
482 tgrel->rd_att, &isnull);
484 elog(ERROR, "tgargs is null for trigger %u", trigid);
485 p = (char *) VARDATA(val);
486 for (i = 0; i < trigrec->tgnargs; i++)
489 appendStringInfo(&buf, ", ");
490 appendStringInfoChar(&buf, '\'');
493 /* escape quotes and backslashes */
494 if (*p == '\'' || *p == '\\')
495 appendStringInfoChar(&buf, '\\');
496 appendStringInfoChar(&buf, *p++);
499 appendStringInfoChar(&buf, '\'');
503 /* We deliberately do not put semi-colon at end */
504 appendStringInfo(&buf, ")");
507 * Create the result as a TEXT datum, and free working data
509 len = buf.len + VARHDRSZ;
510 trigdef = (text *) palloc(len);
511 VARATT_SIZEP(trigdef) = len;
512 memcpy(VARDATA(trigdef), buf.data, buf.len);
516 systable_endscan(tgscan);
518 heap_close(tgrel, AccessShareLock);
520 PG_RETURN_TEXT_P(trigdef);
524 * get_indexdef - Get the definition of an index
528 pg_get_indexdef(PG_FUNCTION_ARGS)
530 Oid indexrelid = PG_GETARG_OID(0);
535 Form_pg_index idxrec;
536 Form_pg_class idxrelrec;
549 * Fetch the pg_index tuple by the Oid of the index
551 ht_idx = SearchSysCache(INDEXRELID,
552 ObjectIdGetDatum(indexrelid),
554 if (!HeapTupleIsValid(ht_idx))
555 elog(ERROR, "syscache lookup for index %u failed", indexrelid);
556 idxrec = (Form_pg_index) GETSTRUCT(ht_idx);
558 indrelid = idxrec->indrelid;
559 Assert(indexrelid == idxrec->indexrelid);
562 * Fetch the pg_class tuple of the index relation
564 ht_idxrel = SearchSysCache(RELOID,
565 ObjectIdGetDatum(indexrelid),
567 if (!HeapTupleIsValid(ht_idxrel))
568 elog(ERROR, "syscache lookup for relid %u failed", indexrelid);
569 idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
572 * Fetch the pg_am tuple of the index' access method
574 ht_am = SearchSysCache(AMOID,
575 ObjectIdGetDatum(idxrelrec->relam),
577 if (!HeapTupleIsValid(ht_am))
578 elog(ERROR, "syscache lookup for AM %u failed", idxrelrec->relam);
579 amrec = (Form_pg_am) GETSTRUCT(ht_am);
582 * Get the index expressions, if any. (NOTE: we do not use the relcache
583 * versions of the expressions and predicate, because we want to display
584 * non-const-folded expressions.)
586 if (!heap_attisnull(ht_idx, Anum_pg_index_indexprs))
592 exprsDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
593 Anum_pg_index_indexprs, &isnull);
595 exprsString = DatumGetCString(DirectFunctionCall1(textout,
597 indexprs = (List *) stringToNode(exprsString);
603 context = deparse_context_for(get_rel_name(indrelid), indrelid);
606 * Start the index definition. Note that the index's name should
607 * never be schema-qualified, but the indexed rel's name may be.
609 initStringInfo(&buf);
610 appendStringInfo(&buf, "CREATE %sINDEX %s ON %s USING %s (",
611 idxrec->indisunique ? "UNIQUE " : "",
612 quote_identifier(NameStr(idxrelrec->relname)),
613 generate_relation_name(indrelid),
614 quote_identifier(NameStr(amrec->amname)));
617 * Report the indexed attributes
620 for (keyno = 0; keyno < idxrec->indnatts; keyno++)
622 AttrNumber attnum = idxrec->indkey[keyno];
624 appendStringInfo(&buf, sep);
629 /* Simple index column */
632 attname = get_relid_attribute_name(indrelid, attnum);
633 appendStringInfo(&buf, "%s", quote_identifier(attname));
634 keycoltype = get_atttype(indrelid, attnum);
638 /* expressional index */
642 elog(ERROR, "too few entries in indexprs list");
643 indexkey = (Node *) lfirst(indexprs);
644 indexprs = lnext(indexprs);
646 str = deparse_expression(indexkey, context, false, false);
647 /* Need parens if it's not a bare function call */
648 if (indexkey && IsA(indexkey, FuncExpr) &&
649 ((FuncExpr *) indexkey)->funcformat == COERCE_EXPLICIT_CALL)
650 appendStringInfo(&buf, "%s", str);
652 appendStringInfo(&buf, "(%s)", str);
653 keycoltype = exprType(indexkey);
657 * Add the operator class name
659 get_opclass_name(idxrec->indclass[keyno], keycoltype,
663 appendStringInfoChar(&buf, ')');
666 * If it's a partial index, decompile and append the predicate
668 if (!heap_attisnull(ht_idx, Anum_pg_index_indpred))
675 /* Convert text string to node tree */
676 predDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
677 Anum_pg_index_indpred, &isnull);
679 predString = DatumGetCString(DirectFunctionCall1(textout,
681 node = (Node *) stringToNode(predString);
685 * If top level is a List, assume it is an implicit-AND structure,
686 * and convert to explicit AND. This is needed for partial index
689 if (node && IsA(node, List))
690 node = (Node *) make_ands_explicit((List *) node);
692 str = deparse_expression(node, context, false, false);
693 appendStringInfo(&buf, " WHERE %s", str);
697 * Create the result as a TEXT datum, and free working data
699 len = buf.len + VARHDRSZ;
700 indexdef = (text *) palloc(len);
701 VARATT_SIZEP(indexdef) = len;
702 memcpy(VARDATA(indexdef), buf.data, buf.len);
706 ReleaseSysCache(ht_idx);
707 ReleaseSysCache(ht_idxrel);
708 ReleaseSysCache(ht_am);
710 PG_RETURN_TEXT_P(indexdef);
715 * pg_get_constraintdef
717 * Returns the definition for the constraint, ie, everything that needs to
718 * appear after "ALTER TABLE ... ADD CONSTRAINT <constraintname>".
721 pg_get_constraintdef(PG_FUNCTION_ARGS)
723 Oid constraintId = PG_GETARG_OID(0);
731 Form_pg_constraint conForm;
734 * Fetch the pg_constraint row. There's no syscache for pg_constraint
735 * so we must do it the hard way.
737 conDesc = heap_openr(ConstraintRelationName, AccessShareLock);
739 ScanKeyEntryInitialize(&skey[0], 0x0,
740 ObjectIdAttributeNumber, F_OIDEQ,
741 ObjectIdGetDatum(constraintId));
743 conscan = systable_beginscan(conDesc, ConstraintOidIndex, true,
744 SnapshotNow, 1, skey);
746 tup = systable_getnext(conscan);
747 if (!HeapTupleIsValid(tup))
748 elog(ERROR, "Failed to find constraint with OID %u", constraintId);
749 conForm = (Form_pg_constraint) GETSTRUCT(tup);
751 initStringInfo(&buf);
753 switch (conForm->contype)
755 case CONSTRAINT_FOREIGN:
761 /* Start off the constraint definition */
762 appendStringInfo(&buf, "FOREIGN KEY (");
764 /* Fetch and build referencing-column list */
765 val = heap_getattr(tup, Anum_pg_constraint_conkey,
766 RelationGetDescr(conDesc), &isnull);
768 elog(ERROR, "pg_get_constraintdef: Null conkey for constraint %u",
771 decompile_column_index_array(val, conForm->conrelid, &buf);
773 /* add foreign relation name */
774 appendStringInfo(&buf, ") REFERENCES %s(",
775 generate_relation_name(conForm->confrelid));
777 /* Fetch and build referenced-column list */
778 val = heap_getattr(tup, Anum_pg_constraint_confkey,
779 RelationGetDescr(conDesc), &isnull);
781 elog(ERROR, "pg_get_constraintdef: Null confkey for constraint %u",
784 decompile_column_index_array(val, conForm->confrelid, &buf);
786 appendStringInfo(&buf, ")");
789 switch (conForm->confmatchtype)
791 case FKCONSTR_MATCH_FULL:
792 string = " MATCH FULL";
794 case FKCONSTR_MATCH_PARTIAL:
795 string = " MATCH PARTIAL";
797 case FKCONSTR_MATCH_UNSPECIFIED:
801 elog(ERROR, "pg_get_constraintdef: Unknown confmatchtype '%c' for constraint %u",
802 conForm->confmatchtype, constraintId);
803 string = ""; /* keep compiler quiet */
806 appendStringInfo(&buf, "%s", string);
808 /* Add ON UPDATE and ON DELETE clauses, if needed */
809 switch (conForm->confupdtype)
811 case FKCONSTR_ACTION_NOACTION:
812 string = NULL; /* suppress default */
814 case FKCONSTR_ACTION_RESTRICT:
817 case FKCONSTR_ACTION_CASCADE:
820 case FKCONSTR_ACTION_SETNULL:
823 case FKCONSTR_ACTION_SETDEFAULT:
824 string = "SET DEFAULT";
827 elog(ERROR, "pg_get_constraintdef: Unknown confupdtype '%c' for constraint %u",
828 conForm->confupdtype, constraintId);
829 string = NULL; /* keep compiler quiet */
833 appendStringInfo(&buf, " ON UPDATE %s", string);
835 switch (conForm->confdeltype)
837 case FKCONSTR_ACTION_NOACTION:
838 string = NULL; /* suppress default */
840 case FKCONSTR_ACTION_RESTRICT:
843 case FKCONSTR_ACTION_CASCADE:
846 case FKCONSTR_ACTION_SETNULL:
849 case FKCONSTR_ACTION_SETDEFAULT:
850 string = "SET DEFAULT";
853 elog(ERROR, "pg_get_constraintdef: Unknown confdeltype '%c' for constraint %u",
854 conForm->confdeltype, constraintId);
855 string = NULL; /* keep compiler quiet */
859 appendStringInfo(&buf, " ON DELETE %s", string);
861 if (conForm->condeferrable)
862 appendStringInfo(&buf, " DEFERRABLE");
863 if (conForm->condeferred)
864 appendStringInfo(&buf, " INITIALLY DEFERRED");
868 case CONSTRAINT_PRIMARY:
869 case CONSTRAINT_UNIQUE:
874 /* Start off the constraint definition */
875 if (conForm->contype == CONSTRAINT_PRIMARY)
876 appendStringInfo(&buf, "PRIMARY KEY (");
878 appendStringInfo(&buf, "UNIQUE (");
880 /* Fetch and build target column list */
881 val = heap_getattr(tup, Anum_pg_constraint_conkey,
882 RelationGetDescr(conDesc), &isnull);
884 elog(ERROR, "pg_get_constraintdef: Null conkey for constraint %u",
887 decompile_column_index_array(val, conForm->conrelid, &buf);
889 appendStringInfo(&buf, ")");
893 case CONSTRAINT_CHECK:
902 /* Start off the constraint definition */
903 /* The consrc for CHECK constraints always seems to be
904 bracketed, so we don't add extra brackets here. */
905 appendStringInfo(&buf, "CHECK ");
907 /* Fetch constraint source */
908 val = heap_getattr(tup, Anum_pg_constraint_conbin,
909 RelationGetDescr(conDesc), &isnull);
911 elog(ERROR, "pg_get_constraintdef: Null consrc for constraint %u",
914 conbin = DatumGetCString(DirectFunctionCall1(textout, val));
915 expr = stringToNode(conbin);
918 * If top level is a List, assume it is an implicit-AND structure, and
919 * convert to explicit AND. This is needed for partial index
922 if (expr && IsA(expr, List))
923 expr = (Node *) make_ands_explicit((List *) expr);
925 if (conForm->conrelid != InvalidOid)
926 /* It's a Relation */
927 context = deparse_context_for(get_rel_name(conForm->conrelid),
931 * Since VARNOs aren't allowed in domain constraints, relation context
932 * isn't required as anything other than a shell.
934 context = deparse_context_for(get_typname(conForm->contypid),
937 consrc = deparse_expression(expr, context, false, false);
939 /* Append the constraint source */
940 appendStringInfoString(&buf, consrc);
945 elog(ERROR, "pg_get_constraintdef: unsupported constraint type '%c'",
950 /* Record the results */
951 len = buf.len + VARHDRSZ;
952 result = (text *) palloc(len);
953 VARATT_SIZEP(result) = len;
954 memcpy(VARDATA(result), buf.data, buf.len);
958 systable_endscan(conscan);
959 heap_close(conDesc, AccessShareLock);
961 PG_RETURN_TEXT_P(result);
966 * Convert an int16[] Datum into a comma-separated list of column names
967 * for the indicated relation; append the list to buf.
970 decompile_column_index_array(Datum column_index_array, Oid relId,
977 /* Extract data from array of int16 */
978 deconstruct_array(DatumGetArrayTypeP(column_index_array),
979 INT2OID, 2, true, 's',
982 for (j = 0; j < nKeys; j++)
986 colName = get_attname(relId, DatumGetInt16(keys[j]));
989 appendStringInfo(buf, "%s",
990 quote_identifier(colName));
992 appendStringInfo(buf, ", %s",
993 quote_identifier(colName));
999 * get_expr - Decompile an expression tree
1001 * Input: an expression tree in nodeToString form, and a relation OID
1003 * Output: reverse-listed expression
1005 * Currently, the expression can only refer to a single relation, namely
1006 * the one specified by the second parameter. This is sufficient for
1007 * partial indexes, column default expressions, etc.
1011 pg_get_expr(PG_FUNCTION_ARGS)
1013 text *expr = PG_GETARG_TEXT_P(0);
1014 Oid relid = PG_GETARG_OID(1);
1022 /* Get the name for the relation */
1023 relname = get_rel_name(relid);
1024 if (relname == NULL)
1025 PG_RETURN_NULL(); /* should we raise an error? */
1027 /* Convert input TEXT object to C string */
1028 exprstr = DatumGetCString(DirectFunctionCall1(textout,
1029 PointerGetDatum(expr)));
1031 /* Convert expression to node tree */
1032 node = (Node *) stringToNode(exprstr);
1035 * If top level is a List, assume it is an implicit-AND structure, and
1036 * convert to explicit AND. This is needed for partial index
1039 if (node && IsA(node, List))
1040 node = (Node *) make_ands_explicit((List *) node);
1043 context = deparse_context_for(relname, relid);
1044 str = deparse_expression(node, context, false, false);
1046 /* Pass the result back as TEXT */
1047 result = DatumGetTextP(DirectFunctionCall1(textin,
1048 CStringGetDatum(str)));
1050 PG_RETURN_TEXT_P(result);
1055 * get_userbyid - Get a user name by usesysid and
1056 * fallback to 'unknown (UID=n)'
1060 pg_get_userbyid(PG_FUNCTION_ARGS)
1062 int32 uid = PG_GETARG_INT32(0);
1065 Form_pg_shadow user_rec;
1068 * Allocate space for the result
1070 result = (Name) palloc(NAMEDATALEN);
1071 memset(NameStr(*result), 0, NAMEDATALEN);
1074 * Get the pg_shadow entry and print the result
1076 usertup = SearchSysCache(SHADOWSYSID,
1077 ObjectIdGetDatum(uid),
1079 if (HeapTupleIsValid(usertup))
1081 user_rec = (Form_pg_shadow) GETSTRUCT(usertup);
1082 StrNCpy(NameStr(*result), NameStr(user_rec->usename), NAMEDATALEN);
1083 ReleaseSysCache(usertup);
1086 sprintf(NameStr(*result), "unknown (UID=%d)", uid);
1088 PG_RETURN_NAME(result);
1092 * deparse_expression - General utility for deparsing expressions
1094 * expr is the node tree to be deparsed. It must be a transformed expression
1095 * tree (ie, not the raw output of gram.y).
1097 * dpcontext is a list of deparse_namespace nodes representing the context
1098 * for interpreting Vars in the node tree.
1100 * forceprefix is TRUE to force all Vars to be prefixed with their table names.
1102 * showimplicit is TRUE to force all implicit casts to be shown explicitly.
1104 * The result is a palloc'd string.
1108 deparse_expression(Node *expr, List *dpcontext,
1109 bool forceprefix, bool showimplicit)
1112 deparse_context context;
1114 initStringInfo(&buf);
1116 context.namespaces = dpcontext;
1117 context.varprefix = forceprefix;
1119 get_rule_expr(expr, &context, showimplicit);
1125 * deparse_context_for - Build deparse context for a single relation
1127 * Given the reference name (alias) and OID of a relation, build deparsing
1128 * context for an expression referencing only that relation (as varno 1,
1129 * varlevelsup 0). This is sufficient for many uses of deparse_expression.
1133 deparse_context_for(const char *aliasname, Oid relid)
1135 deparse_namespace *dpns;
1138 dpns = (deparse_namespace *) palloc(sizeof(deparse_namespace));
1140 /* Build a minimal RTE for the rel */
1141 rte = makeNode(RangeTblEntry);
1142 rte->rtekind = RTE_RELATION;
1144 rte->eref = makeAlias(aliasname, NIL);
1146 rte->inFromCl = true;
1148 /* Build one-element rtable */
1149 dpns->rtable = makeList1(rte);
1150 dpns->outer_varno = dpns->inner_varno = 0;
1151 dpns->outer_rte = dpns->inner_rte = NULL;
1153 /* Return a one-deep namespace stack */
1154 return makeList1(dpns);
1158 * deparse_context_for_plan - Build deparse context for a plan node
1160 * We assume we are dealing with an upper-level plan node having either
1161 * one or two referenceable children (pass innercontext = NULL if only one).
1162 * The passed-in Nodes should be made using deparse_context_for_subplan
1163 * and/or deparse_context_for_relation. The resulting context will work
1164 * for deparsing quals, tlists, etc of the plan node.
1166 * An rtable list can also be passed in case plain Vars might be seen.
1167 * This is not needed for true upper-level expressions, but is helpful for
1168 * Sort nodes and similar cases with slightly bogus targetlists.
1171 deparse_context_for_plan(int outer_varno, Node *outercontext,
1172 int inner_varno, Node *innercontext,
1175 deparse_namespace *dpns;
1177 dpns = (deparse_namespace *) palloc(sizeof(deparse_namespace));
1179 dpns->rtable = rtable;
1180 dpns->outer_varno = outer_varno;
1181 dpns->outer_rte = (RangeTblEntry *) outercontext;
1182 dpns->inner_varno = inner_varno;
1183 dpns->inner_rte = (RangeTblEntry *) innercontext;
1185 /* Return a one-deep namespace stack */
1186 return makeList1(dpns);
1190 * deparse_context_for_rte - Build deparse context for 1 relation
1192 * Helper routine to build one of the inputs for deparse_context_for_plan.
1194 * The returned node is actually the given RangeTblEntry, but we declare it
1195 * as just Node to discourage callers from assuming anything.
1198 deparse_context_for_rte(RangeTblEntry *rte)
1200 return (Node *) rte;
1204 * deparse_context_for_subplan - Build deparse context for a plan node
1206 * Helper routine to build one of the inputs for deparse_context_for_plan.
1207 * Pass the tlist of the subplan node, plus the query rangetable.
1209 * The returned node is actually a RangeTblEntry, but we declare it as just
1210 * Node to discourage callers from assuming anything.
1213 deparse_context_for_subplan(const char *name, List *tlist,
1216 RangeTblEntry *rte = makeNode(RangeTblEntry);
1219 int rtablelength = length(rtable);
1225 TargetEntry *tle = lfirst(tl);
1226 Resdom *resdom = tle->resdom;
1229 Assert(resdom->resno == nattrs);
1230 if (resdom->resname)
1232 attrs = lappend(attrs, makeString(resdom->resname));
1235 if (tle->expr && IsA(tle->expr, Var))
1237 Var *var = (Var *) tle->expr;
1239 /* varno/varattno won't be any good, but varnoold might be */
1240 if (var->varnoold > 0 && var->varnoold <= rtablelength)
1242 RangeTblEntry *varrte = rt_fetch(var->varnoold, rtable);
1245 varname = get_rte_attribute_name(varrte, var->varoattno);
1246 attrs = lappend(attrs, makeString(varname));
1250 /* Fallback if can't get name */
1251 snprintf(buf, sizeof(buf), "?column%d?", resdom->resno);
1252 attrs = lappend(attrs, makeString(pstrdup(buf)));
1255 rte->rtekind = RTE_SPECIAL; /* XXX */
1256 rte->relid = InvalidOid;
1257 rte->eref = makeAlias(name, attrs);
1259 rte->inFromCl = true;
1261 return (Node *) rte;
1265 * make_ruledef - reconstruct the CREATE RULE command
1266 * for a given pg_rewrite tuple
1270 make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc)
1279 List *actions = NIL;
1285 * Get the attribute values from the rules tuple
1287 fno = SPI_fnumber(rulettc, "rulename");
1288 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
1290 rulename = NameStr(*(DatumGetName(dat)));
1292 fno = SPI_fnumber(rulettc, "ev_type");
1293 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
1295 ev_type = DatumGetChar(dat);
1297 fno = SPI_fnumber(rulettc, "ev_class");
1298 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
1300 ev_class = DatumGetObjectId(dat);
1302 fno = SPI_fnumber(rulettc, "ev_attr");
1303 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
1305 ev_attr = DatumGetInt16(dat);
1307 fno = SPI_fnumber(rulettc, "is_instead");
1308 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
1310 is_instead = DatumGetBool(dat);
1312 /* these could be nulls */
1313 fno = SPI_fnumber(rulettc, "ev_qual");
1314 ev_qual = SPI_getvalue(ruletup, rulettc, fno);
1316 fno = SPI_fnumber(rulettc, "ev_action");
1317 ev_action = SPI_getvalue(ruletup, rulettc, fno);
1318 if (ev_action != NULL)
1319 actions = (List *) stringToNode(ev_action);
1322 * Build the rules definition text
1324 appendStringInfo(buf, "CREATE RULE %s AS ON ",
1325 quote_identifier(rulename));
1327 /* The event the rule is fired for */
1331 appendStringInfo(buf, "SELECT");
1335 appendStringInfo(buf, "UPDATE");
1339 appendStringInfo(buf, "INSERT");
1343 appendStringInfo(buf, "DELETE");
1347 elog(ERROR, "get_ruledef: rule %s has unsupported event type %d",
1352 /* The relation the rule is fired on */
1353 appendStringInfo(buf, " TO %s", generate_relation_name(ev_class));
1355 appendStringInfo(buf, ".%s",
1356 quote_identifier(get_relid_attribute_name(ev_class,
1359 /* If the rule has an event qualification, add it */
1360 if (ev_qual == NULL)
1362 if (strlen(ev_qual) > 0 && strcmp(ev_qual, "<>") != 0)
1366 deparse_context context;
1367 deparse_namespace dpns;
1369 appendStringInfo(buf, " WHERE ");
1371 qual = stringToNode(ev_qual);
1374 * We need to make a context for recognizing any Vars in the qual
1375 * (which can only be references to OLD and NEW). Use the rtable
1376 * of the first query in the action list for this purpose.
1378 query = (Query *) lfirst(actions);
1381 * If the action is INSERT...SELECT, OLD/NEW have been pushed down
1382 * into the SELECT, and that's what we need to look at. (Ugly
1383 * kluge ... try to fix this when we redesign querytrees.)
1385 query = getInsertSelectQuery(query, NULL);
1388 context.namespaces = makeList1(&dpns);
1389 context.varprefix = (length(query->rtable) != 1);
1390 dpns.rtable = query->rtable;
1391 dpns.outer_varno = dpns.inner_varno = 0;
1392 dpns.outer_rte = dpns.inner_rte = NULL;
1394 get_rule_expr(qual, &context, false);
1397 appendStringInfo(buf, " DO ");
1399 /* The INSTEAD keyword (if so) */
1401 appendStringInfo(buf, "INSTEAD ");
1403 /* Finally the rules actions */
1404 if (length(actions) > 1)
1409 appendStringInfo(buf, "(");
1410 foreach(action, actions)
1412 query = (Query *) lfirst(action);
1413 get_query_def(query, buf, NIL, NULL);
1414 appendStringInfo(buf, "; ");
1416 appendStringInfo(buf, ");");
1418 else if (length(actions) == 0)
1420 appendStringInfo(buf, "NOTHING;");
1426 query = (Query *) lfirst(actions);
1427 get_query_def(query, buf, NIL, NULL);
1428 appendStringInfo(buf, ";");
1434 * make_viewdef - reconstruct the SELECT part of a
1439 make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc)
1448 List *actions = NIL;
1449 Relation ev_relation;
1454 * Get the attribute values from the rules tuple
1456 fno = SPI_fnumber(rulettc, "ev_type");
1457 ev_type = (char) SPI_getbinval(ruletup, rulettc, fno, &isnull);
1459 fno = SPI_fnumber(rulettc, "ev_class");
1460 ev_class = (Oid) SPI_getbinval(ruletup, rulettc, fno, &isnull);
1462 fno = SPI_fnumber(rulettc, "ev_attr");
1463 ev_attr = (int2) SPI_getbinval(ruletup, rulettc, fno, &isnull);
1465 fno = SPI_fnumber(rulettc, "is_instead");
1466 is_instead = (bool) SPI_getbinval(ruletup, rulettc, fno, &isnull);
1468 fno = SPI_fnumber(rulettc, "ev_qual");
1469 ev_qual = SPI_getvalue(ruletup, rulettc, fno);
1471 fno = SPI_fnumber(rulettc, "ev_action");
1472 ev_action = SPI_getvalue(ruletup, rulettc, fno);
1473 if (ev_action != NULL)
1474 actions = (List *) stringToNode(ev_action);
1476 if (length(actions) != 1)
1478 appendStringInfo(buf, "Not a view");
1482 query = (Query *) lfirst(actions);
1484 if (ev_type != '1' || ev_attr >= 0 || !is_instead ||
1485 strcmp(ev_qual, "<>") != 0 || query->commandType != CMD_SELECT)
1487 appendStringInfo(buf, "Not a view");
1491 ev_relation = heap_open(ev_class, AccessShareLock);
1493 get_query_def(query, buf, NIL, RelationGetDescr(ev_relation));
1494 appendStringInfo(buf, ";");
1496 heap_close(ev_relation, AccessShareLock);
1501 * get_query_def - Parse back one query parsetree
1503 * If resultDesc is not NULL, then it is the output tuple descriptor for
1504 * the view represented by a SELECT query.
1508 get_query_def(Query *query, StringInfo buf, List *parentnamespace,
1509 TupleDesc resultDesc)
1511 deparse_context context;
1512 deparse_namespace dpns;
1515 context.namespaces = lcons(&dpns, parentnamespace);
1516 context.varprefix = (parentnamespace != NIL ||
1517 length(query->rtable) != 1);
1518 dpns.rtable = query->rtable;
1519 dpns.outer_varno = dpns.inner_varno = 0;
1520 dpns.outer_rte = dpns.inner_rte = NULL;
1522 switch (query->commandType)
1525 get_select_query_def(query, &context, resultDesc);
1529 get_update_query_def(query, &context);
1533 get_insert_query_def(query, &context);
1537 get_delete_query_def(query, &context);
1541 appendStringInfo(buf, "NOTHING");
1545 get_utility_query_def(query, &context);
1549 elog(ERROR, "get_query_def: unknown query command type %d",
1550 query->commandType);
1557 * get_select_query_def - Parse back a SELECT parsetree
1561 get_select_query_def(Query *query, deparse_context *context,
1562 TupleDesc resultDesc)
1564 StringInfo buf = context->buf;
1570 * If the Query node has a setOperations tree, then it's the top level
1571 * of a UNION/INTERSECT/EXCEPT query; only the ORDER BY and LIMIT
1572 * fields are interesting in the top query itself.
1574 if (query->setOperations)
1576 get_setop_query(query->setOperations, query, context, resultDesc);
1577 /* ORDER BY clauses must be simple in this case */
1582 get_basic_select_query(query, context, resultDesc);
1583 force_colno = false;
1586 /* Add the ORDER BY clause if given */
1587 if (query->sortClause != NIL)
1589 appendStringInfo(buf, " ORDER BY ");
1591 foreach(l, query->sortClause)
1593 SortClause *srt = (SortClause *) lfirst(l);
1598 appendStringInfo(buf, sep);
1599 sortexpr = get_rule_sortgroupclause(srt, query->targetList,
1600 force_colno, context);
1601 sortcoltype = exprType(sortexpr);
1602 opname = generate_operator_name(srt->sortop,
1603 sortcoltype, sortcoltype);
1604 if (strcmp(opname, "<") != 0)
1606 if (strcmp(opname, ">") == 0)
1607 appendStringInfo(buf, " DESC");
1609 appendStringInfo(buf, " USING %s", opname);
1615 /* Add the LIMIT clause if given */
1616 if (query->limitOffset != NULL)
1618 appendStringInfo(buf, " OFFSET ");
1619 get_rule_expr(query->limitOffset, context, false);
1621 if (query->limitCount != NULL)
1623 appendStringInfo(buf, " LIMIT ");
1624 if (IsA(query->limitCount, Const) &&
1625 ((Const *) query->limitCount)->constisnull)
1626 appendStringInfo(buf, "ALL");
1628 get_rule_expr(query->limitCount, context, false);
1633 get_basic_select_query(Query *query, deparse_context *context,
1634 TupleDesc resultDesc)
1636 StringInfo buf = context->buf;
1642 * Build up the query string - first we say SELECT
1644 appendStringInfo(buf, "SELECT");
1646 /* Add the DISTINCT clause if given */
1647 if (query->distinctClause != NIL)
1649 if (has_distinct_on_clause(query))
1651 appendStringInfo(buf, " DISTINCT ON (");
1653 foreach(l, query->distinctClause)
1655 SortClause *srt = (SortClause *) lfirst(l);
1657 appendStringInfo(buf, sep);
1658 get_rule_sortgroupclause(srt, query->targetList,
1662 appendStringInfo(buf, ")");
1665 appendStringInfo(buf, " DISTINCT");
1668 /* Then we tell what to select (the targetlist) */
1671 foreach(l, query->targetList)
1673 TargetEntry *tle = (TargetEntry *) lfirst(l);
1674 bool tell_as = false;
1677 if (tle->resdom->resjunk)
1678 continue; /* ignore junk entries */
1680 appendStringInfo(buf, sep);
1684 get_rule_expr((Node *) tle->expr, context, true);
1687 * Figure out what the result column should be called. In the
1688 * context of a view, use the view's tuple descriptor (so as to
1689 * pick up the effects of any column RENAME that's been done on
1690 * the view). Otherwise, just use what we can find in the TLE.
1692 if (resultDesc && colno <= resultDesc->natts)
1693 colname = NameStr(resultDesc->attrs[colno - 1]->attname);
1695 colname = tle->resdom->resname;
1697 /* Check if we must say AS ... */
1698 if (!IsA(tle->expr, Var))
1699 tell_as = (strcmp(colname, "?column?") != 0);
1702 Var *var = (Var *) (tle->expr);
1707 get_names_for_var(var, context, &schemaname, &refname, &attname);
1708 tell_as = (attname == NULL ||
1709 strcmp(attname, colname) != 0);
1714 appendStringInfo(buf, " AS %s", quote_identifier(colname));
1717 /* Add the FROM clause if needed */
1718 get_from_clause(query, context);
1720 /* Add the WHERE clause if given */
1721 if (query->jointree->quals != NULL)
1723 appendStringInfo(buf, " WHERE ");
1724 get_rule_expr(query->jointree->quals, context, false);
1727 /* Add the GROUP BY clause if given */
1728 if (query->groupClause != NULL)
1730 appendStringInfo(buf, " GROUP BY ");
1732 foreach(l, query->groupClause)
1734 GroupClause *grp = (GroupClause *) lfirst(l);
1736 appendStringInfo(buf, sep);
1737 get_rule_sortgroupclause(grp, query->targetList,
1743 /* Add the HAVING clause if given */
1744 if (query->havingQual != NULL)
1746 appendStringInfo(buf, " HAVING ");
1747 get_rule_expr(query->havingQual, context, false);
1752 get_setop_query(Node *setOp, Query *query, deparse_context *context,
1753 TupleDesc resultDesc)
1755 StringInfo buf = context->buf;
1757 if (IsA(setOp, RangeTblRef))
1759 RangeTblRef *rtr = (RangeTblRef *) setOp;
1760 RangeTblEntry *rte = rt_fetch(rtr->rtindex, query->rtable);
1761 Query *subquery = rte->subquery;
1763 Assert(subquery != NULL);
1764 get_query_def(subquery, buf, context->namespaces, resultDesc);
1766 else if (IsA(setOp, SetOperationStmt))
1768 SetOperationStmt *op = (SetOperationStmt *) setOp;
1770 appendStringInfo(buf, "((");
1771 get_setop_query(op->larg, query, context, resultDesc);
1775 appendStringInfo(buf, ") UNION ");
1777 case SETOP_INTERSECT:
1778 appendStringInfo(buf, ") INTERSECT ");
1781 appendStringInfo(buf, ") EXCEPT ");
1784 elog(ERROR, "get_setop_query: unexpected set op %d",
1788 appendStringInfo(buf, "ALL (");
1790 appendStringInfo(buf, "(");
1791 get_setop_query(op->rarg, query, context, resultDesc);
1792 appendStringInfo(buf, "))");
1796 elog(ERROR, "get_setop_query: unexpected node %d",
1797 (int) nodeTag(setOp));
1802 * Display a sort/group clause.
1804 * Also returns the expression tree, so caller need not find it again.
1807 get_rule_sortgroupclause(SortClause *srt, List *tlist, bool force_colno,
1808 deparse_context *context)
1810 StringInfo buf = context->buf;
1814 tle = get_sortgroupclause_tle(srt, tlist);
1815 expr = (Node *) tle->expr;
1818 * Use column-number form if requested by caller or if expression is a
1819 * constant --- a constant is ambiguous (and will be misinterpreted by
1820 * findTargetlistEntry()) if we dump it explicitly.
1822 if (force_colno || (expr && IsA(expr, Const)))
1824 Assert(!tle->resdom->resjunk);
1825 appendStringInfo(buf, "%d", tle->resdom->resno);
1828 get_rule_expr(expr, context, true);
1834 * get_insert_query_def - Parse back an INSERT parsetree
1838 get_insert_query_def(Query *query, deparse_context *context)
1840 StringInfo buf = context->buf;
1841 RangeTblEntry *select_rte = NULL;
1847 * If it's an INSERT ... SELECT there will be a single subquery RTE
1850 foreach(l, query->rtable)
1852 rte = (RangeTblEntry *) lfirst(l);
1853 if (rte->rtekind != RTE_SUBQUERY)
1856 elog(ERROR, "get_insert_query_def: too many RTEs in INSERT!");
1861 * Start the query with INSERT INTO relname
1863 rte = rt_fetch(query->resultRelation, query->rtable);
1864 Assert(rte->rtekind == RTE_RELATION);
1865 appendStringInfo(buf, "INSERT INTO %s",
1866 generate_relation_name(rte->relid));
1868 /* Add the insert-column-names list */
1870 foreach(l, query->targetList)
1872 TargetEntry *tle = (TargetEntry *) lfirst(l);
1874 if (tle->resdom->resjunk)
1875 continue; /* ignore junk entries */
1877 appendStringInfo(buf, sep);
1879 appendStringInfo(buf, "%s", quote_identifier(tle->resdom->resname));
1881 appendStringInfo(buf, ") ");
1883 /* Add the VALUES or the SELECT */
1884 if (select_rte == NULL)
1886 appendStringInfo(buf, "VALUES (");
1888 foreach(l, query->targetList)
1890 TargetEntry *tle = (TargetEntry *) lfirst(l);
1892 if (tle->resdom->resjunk)
1893 continue; /* ignore junk entries */
1895 appendStringInfo(buf, sep);
1897 get_rule_expr((Node *) tle->expr, context, false);
1899 appendStringInfoChar(buf, ')');
1902 get_query_def(select_rte->subquery, buf, NIL, NULL);
1907 * get_update_query_def - Parse back an UPDATE parsetree
1911 get_update_query_def(Query *query, deparse_context *context)
1913 StringInfo buf = context->buf;
1919 * Start the query with UPDATE relname SET
1921 rte = rt_fetch(query->resultRelation, query->rtable);
1922 Assert(rte->rtekind == RTE_RELATION);
1923 appendStringInfo(buf, "UPDATE %s%s SET ",
1925 generate_relation_name(rte->relid));
1927 /* Add the comma separated list of 'attname = value' */
1929 foreach(l, query->targetList)
1931 TargetEntry *tle = (TargetEntry *) lfirst(l);
1933 if (tle->resdom->resjunk)
1934 continue; /* ignore junk entries */
1936 appendStringInfo(buf, sep);
1940 * If the update expression is an array assignment, we mustn't put
1941 * out "attname =" here; it will come out of the display of the
1942 * ArrayRef node instead.
1944 if (!tleIsArrayAssign(tle))
1945 appendStringInfo(buf, "%s = ",
1946 quote_identifier(tle->resdom->resname));
1947 get_rule_expr((Node *) tle->expr, context, false);
1950 /* Add the FROM clause if needed */
1951 get_from_clause(query, context);
1953 /* Finally add a WHERE clause if given */
1954 if (query->jointree->quals != NULL)
1956 appendStringInfo(buf, " WHERE ");
1957 get_rule_expr(query->jointree->quals, context, false);
1963 * get_delete_query_def - Parse back a DELETE parsetree
1967 get_delete_query_def(Query *query, deparse_context *context)
1969 StringInfo buf = context->buf;
1973 * Start the query with DELETE FROM relname
1975 rte = rt_fetch(query->resultRelation, query->rtable);
1976 Assert(rte->rtekind == RTE_RELATION);
1977 appendStringInfo(buf, "DELETE FROM %s%s",
1979 generate_relation_name(rte->relid));
1981 /* Add a WHERE clause if given */
1982 if (query->jointree->quals != NULL)
1984 appendStringInfo(buf, " WHERE ");
1985 get_rule_expr(query->jointree->quals, context, false);
1991 * get_utility_query_def - Parse back a UTILITY parsetree
1995 get_utility_query_def(Query *query, deparse_context *context)
1997 StringInfo buf = context->buf;
1999 if (query->utilityStmt && IsA(query->utilityStmt, NotifyStmt))
2001 NotifyStmt *stmt = (NotifyStmt *) query->utilityStmt;
2003 appendStringInfo(buf, "NOTIFY %s",
2004 quote_qualified_identifier(stmt->relation->schemaname,
2005 stmt->relation->relname));
2008 elog(ERROR, "get_utility_query_def: unexpected statement type");
2013 * Get the schemaname, refname and attname for a (possibly nonlocal) Var.
2015 * schemaname is usually returned as NULL. It will be non-null only if
2016 * use of the unqualified refname would find the wrong RTE.
2018 * refname will be returned as NULL if the Var references an unnamed join.
2019 * In this case the Var *must* be displayed without any qualification.
2021 * attname will be returned as NULL if the Var represents a whole tuple
2022 * of the relation. (Typically we'd want to display the Var as "foo.*",
2023 * but it's convenient to return NULL to make it easier for callers to
2024 * distinguish this case.)
2027 get_names_for_var(Var *var, deparse_context *context,
2028 char **schemaname, char **refname, char **attname)
2030 List *nslist = context->namespaces;
2031 int sup = var->varlevelsup;
2032 deparse_namespace *dpns;
2035 /* Find appropriate nesting depth */
2036 while (sup-- > 0 && nslist != NIL)
2037 nslist = lnext(nslist);
2039 elog(ERROR, "get_names_for_var: bogus varlevelsup %d",
2041 dpns = (deparse_namespace *) lfirst(nslist);
2043 /* Find the relevant RTE */
2044 if (var->varno >= 1 && var->varno <= length(dpns->rtable))
2045 rte = rt_fetch(var->varno, dpns->rtable);
2046 else if (var->varno == dpns->outer_varno)
2047 rte = dpns->outer_rte;
2048 else if (var->varno == dpns->inner_varno)
2049 rte = dpns->inner_rte;
2053 elog(ERROR, "get_names_for_var: bogus varno %d",
2057 *schemaname = NULL; /* default assumptions */
2058 *refname = rte->eref->aliasname;
2060 /* Exceptions occur only if the RTE is alias-less */
2061 if (rte->alias == NULL)
2063 if (rte->rtekind == RTE_RELATION)
2066 * It's possible that use of the bare refname would find
2067 * another more-closely-nested RTE, or be ambiguous, in which
2068 * case we need to specify the schemaname to avoid these
2071 if (find_rte_by_refname(rte->eref->aliasname, context) != rte)
2073 get_namespace_name(get_rel_namespace(rte->relid));
2075 else if (rte->rtekind == RTE_JOIN)
2077 /* Unnamed join has neither schemaname nor refname */
2082 if (var->varattno == InvalidAttrNumber)
2085 *attname = get_rte_attribute_name(rte, var->varattno);
2089 * find_rte_by_refname - look up an RTE by refname in a deparse context
2091 * Returns NULL if there is no matching RTE or the refname is ambiguous.
2093 * NOTE: this code is not really correct since it does not take account of
2094 * the fact that not all the RTEs in a rangetable may be visible from the
2095 * point where a Var reference appears. For the purposes we need, however,
2096 * the only consequence of a false match is that we might stick a schema
2097 * qualifier on a Var that doesn't really need it. So it seems close
2100 static RangeTblEntry *
2101 find_rte_by_refname(const char *refname, deparse_context *context)
2103 RangeTblEntry *result = NULL;
2106 foreach(nslist, context->namespaces)
2108 deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
2111 foreach(rtlist, dpns->rtable)
2113 RangeTblEntry *rte = (RangeTblEntry *) lfirst(rtlist);
2115 if (strcmp(rte->eref->aliasname, refname) == 0)
2118 return NULL; /* it's ambiguous */
2122 if (dpns->outer_rte &&
2123 strcmp(dpns->outer_rte->eref->aliasname, refname) == 0)
2126 return NULL; /* it's ambiguous */
2127 result = dpns->outer_rte;
2129 if (dpns->inner_rte &&
2130 strcmp(dpns->inner_rte->eref->aliasname, refname) == 0)
2133 return NULL; /* it's ambiguous */
2134 result = dpns->inner_rte;
2144 * get_rule_expr - Parse back an expression
2146 * Note: showimplicit determines whether we display any implicit cast that
2147 * is present at the top of the expression tree. It is a passed argument,
2148 * not a field of the context struct, because we change the value as we
2149 * recurse down into the expression. In general we suppress implicit casts
2150 * when the result type is known with certainty (eg, the arguments of an
2151 * OR must be boolean). We display implicit casts for arguments of functions
2152 * and operators, since this is needed to be certain that the same function
2153 * or operator will be chosen when the expression is re-parsed.
2157 get_rule_expr(Node *node, deparse_context *context,
2160 StringInfo buf = context->buf;
2166 * Each level of get_rule_expr must emit an indivisible term
2167 * (parenthesized if necessary) to ensure result is reparsed into the
2168 * same expression tree.
2170 * There might be some work left here to support additional node types.
2172 switch (nodeTag(node))
2176 Var *var = (Var *) node;
2181 get_names_for_var(var, context,
2182 &schemaname, &refname, &attname);
2183 if (refname && (context->varprefix || attname == NULL))
2186 appendStringInfo(buf, "%s.",
2187 quote_identifier(schemaname));
2189 if (strcmp(refname, "*NEW*") == 0)
2190 appendStringInfo(buf, "new.");
2191 else if (strcmp(refname, "*OLD*") == 0)
2192 appendStringInfo(buf, "old.");
2194 appendStringInfo(buf, "%s.",
2195 quote_identifier(refname));
2198 appendStringInfo(buf, "%s", quote_identifier(attname));
2200 appendStringInfo(buf, "*");
2205 get_const_expr((Const *) node, context);
2210 Param *param = (Param *) node;
2212 switch (param->paramkind)
2215 appendStringInfo(buf, "$%s", param->paramname);
2219 appendStringInfo(buf, "$%d", param->paramid);
2222 appendStringInfo(buf, "(param)");
2229 get_agg_expr((Aggref *) node, context);
2234 ArrayRef *aref = (ArrayRef *) node;
2235 bool savevarprefix = context->varprefix;
2241 * If we are doing UPDATE array[n] = expr, we need to
2242 * suppress any prefix on the array name. Currently, that
2243 * is the only context in which we will see a non-null
2244 * refassgnexpr --- but someday a smarter test may be
2247 if (aref->refassgnexpr)
2248 context->varprefix = false;
2250 * Parenthesize the argument unless it's a simple Var.
2252 need_parens = (aref->refassgnexpr == NULL) &&
2253 !IsA(aref->refexpr, Var);
2255 appendStringInfoChar(buf, '(');
2256 get_rule_expr((Node *) aref->refexpr, context, showimplicit);
2258 appendStringInfoChar(buf, ')');
2259 context->varprefix = savevarprefix;
2260 lowlist = aref->reflowerindexpr;
2261 foreach(uplist, aref->refupperindexpr)
2263 appendStringInfo(buf, "[");
2266 get_rule_expr((Node *) lfirst(lowlist), context,
2268 appendStringInfo(buf, ":");
2269 lowlist = lnext(lowlist);
2271 get_rule_expr((Node *) lfirst(uplist), context, false);
2272 appendStringInfo(buf, "]");
2274 if (aref->refassgnexpr)
2276 appendStringInfo(buf, " = ");
2277 get_rule_expr((Node *) aref->refassgnexpr, context,
2284 get_func_expr((FuncExpr *) node, context, showimplicit);
2288 get_oper_expr((OpExpr *) node, context);
2291 case T_DistinctExpr:
2293 DistinctExpr *expr = (DistinctExpr *) node;
2294 List *args = expr->args;
2295 Node *arg1 = (Node *) lfirst(args);
2296 Node *arg2 = (Node *) lsecond(args);
2298 appendStringInfoChar(buf, '(');
2299 get_rule_expr(arg1, context, true);
2300 appendStringInfo(buf, " IS DISTINCT FROM ");
2301 get_rule_expr(arg2, context, true);
2302 appendStringInfoChar(buf, ')');
2306 case T_ScalarArrayOpExpr:
2308 ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
2309 List *args = expr->args;
2310 Node *arg1 = (Node *) lfirst(args);
2311 Node *arg2 = (Node *) lsecond(args);
2313 appendStringInfoChar(buf, '(');
2314 get_rule_expr(arg1, context, true);
2315 appendStringInfo(buf, " %s %s (",
2316 generate_operator_name(expr->opno,
2318 get_element_type(exprType(arg2))),
2319 expr->useOr ? "ANY" : "ALL");
2320 get_rule_expr(arg2, context, true);
2321 appendStringInfo(buf, "))");
2327 BoolExpr *expr = (BoolExpr *) node;
2328 List *args = expr->args;
2330 switch (expr->boolop)
2333 appendStringInfoChar(buf, '(');
2334 get_rule_expr((Node *) lfirst(args), context, false);
2335 while ((args = lnext(args)) != NIL)
2337 appendStringInfo(buf, " AND ");
2338 get_rule_expr((Node *) lfirst(args), context,
2341 appendStringInfoChar(buf, ')');
2345 appendStringInfoChar(buf, '(');
2346 get_rule_expr((Node *) lfirst(args), context, false);
2347 while ((args = lnext(args)) != NIL)
2349 appendStringInfo(buf, " OR ");
2350 get_rule_expr((Node *) lfirst(args), context,
2353 appendStringInfoChar(buf, ')');
2357 appendStringInfo(buf, "(NOT ");
2358 get_rule_expr((Node *) lfirst(args), context, false);
2359 appendStringInfoChar(buf, ')');
2363 elog(ERROR, "get_rule_expr: unknown boolop %d",
2364 (int) expr->boolop);
2370 get_sublink_expr((SubLink *) node, context);
2376 * We cannot see an already-planned subplan in
2377 * rule deparsing, only while EXPLAINing a query
2378 * plan. For now, just punt.
2380 if (((SubPlan *) node)->useHashTable)
2381 appendStringInfo(buf, "(hashed subplan)");
2383 appendStringInfo(buf, "(subplan)");
2389 FieldSelect *fselect = (FieldSelect *) node;
2390 Oid argType = exprType((Node *) fselect->arg);
2394 /* lookup arg type and get the field name */
2395 typrelid = get_typ_typrelid(argType);
2396 if (!OidIsValid(typrelid))
2397 elog(ERROR, "Argument type %s of FieldSelect is not a tuple type",
2398 format_type_be(argType));
2399 fieldname = get_relid_attribute_name(typrelid,
2403 * If the argument is simple enough, we could emit
2404 * arg.fieldname, but most cases where FieldSelect is used
2405 * are *not* simple. So, always use parenthesized syntax.
2407 appendStringInfoChar(buf, '(');
2408 get_rule_expr((Node *) fselect->arg, context, true);
2409 appendStringInfo(buf, ").%s", quote_identifier(fieldname));
2415 RelabelType *relabel = (RelabelType *) node;
2416 Node *arg = (Node *) relabel->arg;
2418 if (relabel->relabelformat == COERCE_IMPLICIT_CAST &&
2421 /* don't show the implicit cast */
2422 get_rule_expr(arg, context, showimplicit);
2427 * Strip off any type coercions on the input, so we don't
2428 * print redundancies like x::bpchar::character(8).
2430 * XXX Are there any cases where this is a bad idea?
2432 arg = strip_type_coercion(arg, relabel->resulttype);
2434 appendStringInfoChar(buf, '(');
2435 get_rule_expr(arg, context, showimplicit);
2436 appendStringInfo(buf, ")::%s",
2437 format_type_with_typemod(relabel->resulttype,
2438 relabel->resulttypmod));
2445 CaseExpr *caseexpr = (CaseExpr *) node;
2448 appendStringInfo(buf, "CASE");
2449 foreach(temp, caseexpr->args)
2451 CaseWhen *when = (CaseWhen *) lfirst(temp);
2453 appendStringInfo(buf, " WHEN ");
2454 get_rule_expr((Node *) when->expr, context, false);
2455 appendStringInfo(buf, " THEN ");
2456 get_rule_expr((Node *) when->result, context, true);
2458 appendStringInfo(buf, " ELSE ");
2459 get_rule_expr((Node *) caseexpr->defresult, context, true);
2460 appendStringInfo(buf, " END");
2466 ArrayExpr *arrayexpr = (ArrayExpr *) node;
2470 appendStringInfo(buf, "ARRAY[");
2472 foreach(element, arrayexpr->elements)
2474 Node *e = (Node *) lfirst(element);
2476 appendStringInfo(buf, sep);
2477 get_rule_expr(e, context, true);
2480 appendStringInfo(buf, "]");
2484 case T_CoalesceExpr:
2486 CoalesceExpr *coalesceexpr = (CoalesceExpr *) node;
2490 appendStringInfo(buf, "COALESCE(");
2492 foreach(arg, coalesceexpr->args)
2494 Node *e = (Node *) lfirst(arg);
2496 appendStringInfo(buf, sep);
2497 get_rule_expr(e, context, true);
2500 appendStringInfo(buf, ")");
2506 NullIfExpr *nullifexpr = (NullIfExpr *) node;
2510 appendStringInfo(buf, "NULLIF(");
2512 foreach(arg, nullifexpr->args)
2514 Node *e = (Node *) lfirst(arg);
2516 appendStringInfo(buf, sep);
2517 get_rule_expr(e, context, true);
2520 appendStringInfo(buf, ")");
2526 NullTest *ntest = (NullTest *) node;
2528 appendStringInfo(buf, "(");
2529 get_rule_expr((Node *) ntest->arg, context, true);
2530 switch (ntest->nulltesttype)
2533 appendStringInfo(buf, " IS NULL)");
2536 appendStringInfo(buf, " IS NOT NULL)");
2539 elog(ERROR, "get_rule_expr: unexpected nulltesttype %d",
2540 (int) ntest->nulltesttype);
2547 BooleanTest *btest = (BooleanTest *) node;
2549 appendStringInfo(buf, "(");
2550 get_rule_expr((Node *) btest->arg, context, false);
2551 switch (btest->booltesttype)
2554 appendStringInfo(buf, " IS TRUE)");
2557 appendStringInfo(buf, " IS NOT TRUE)");
2560 appendStringInfo(buf, " IS FALSE)");
2563 appendStringInfo(buf, " IS NOT FALSE)");
2566 appendStringInfo(buf, " IS UNKNOWN)");
2568 case IS_NOT_UNKNOWN:
2569 appendStringInfo(buf, " IS NOT UNKNOWN)");
2572 elog(ERROR, "get_rule_expr: unexpected booltesttype %d",
2573 (int) btest->booltesttype);
2578 case T_CoerceToDomain:
2580 CoerceToDomain *ctest = (CoerceToDomain *) node;
2581 Node *arg = (Node *) ctest->arg;
2584 * Any implicit coercion at the top level of the argument
2585 * is presumably due to the domain's own internal typmod
2586 * coercion, so do not force it to be shown.
2588 if (ctest->coercionformat == COERCE_IMPLICIT_CAST &&
2591 /* don't show the implicit cast */
2592 get_rule_expr(arg, context, false);
2596 appendStringInfoChar(buf, '(');
2597 get_rule_expr(arg, context, false);
2598 appendStringInfo(buf, ")::%s",
2599 format_type_with_typemod(ctest->resulttype,
2600 ctest->resulttypmod));
2605 case T_CoerceToDomainValue:
2606 appendStringInfo(buf, "VALUE");
2609 case T_SetToDefault:
2610 appendStringInfo(buf, "DEFAULT");
2614 elog(ERROR, "get_rule_expr: unknown node type %d", nodeTag(node));
2621 * get_oper_expr - Parse back an OpExpr node
2624 get_oper_expr(OpExpr *expr, deparse_context *context)
2626 StringInfo buf = context->buf;
2627 Oid opno = expr->opno;
2628 List *args = expr->args;
2630 appendStringInfoChar(buf, '(');
2631 if (length(args) == 2)
2633 /* binary operator */
2634 Node *arg1 = (Node *) lfirst(args);
2635 Node *arg2 = (Node *) lsecond(args);
2637 get_rule_expr(arg1, context, true);
2638 appendStringInfo(buf, " %s ",
2639 generate_operator_name(opno,
2642 get_rule_expr(arg2, context, true);
2646 /* unary operator --- but which side? */
2647 Node *arg = (Node *) lfirst(args);
2649 Form_pg_operator optup;
2651 tp = SearchSysCache(OPEROID,
2652 ObjectIdGetDatum(opno),
2654 if (!HeapTupleIsValid(tp))
2655 elog(ERROR, "cache lookup for operator %u failed", opno);
2656 optup = (Form_pg_operator) GETSTRUCT(tp);
2657 switch (optup->oprkind)
2660 appendStringInfo(buf, "%s ",
2661 generate_operator_name(opno,
2664 get_rule_expr(arg, context, true);
2667 get_rule_expr(arg, context, true);
2668 appendStringInfo(buf, " %s",
2669 generate_operator_name(opno,
2674 elog(ERROR, "get_rule_expr: bogus oprkind");
2676 ReleaseSysCache(tp);
2678 appendStringInfoChar(buf, ')');
2682 * get_func_expr - Parse back a FuncExpr node
2685 get_func_expr(FuncExpr *expr, deparse_context *context,
2688 StringInfo buf = context->buf;
2689 Oid funcoid = expr->funcid;
2690 Oid argtypes[FUNC_MAX_ARGS];
2696 * If the function call came from an implicit coercion, then just show
2697 * the first argument --- unless caller wants to see implicit coercions.
2699 if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
2701 get_rule_expr((Node *) lfirst(expr->args), context, showimplicit);
2706 * If the function call came from a cast, then show
2707 * the first argument plus an explicit cast operation.
2709 if (expr->funcformat == COERCE_EXPLICIT_CAST ||
2710 expr->funcformat == COERCE_IMPLICIT_CAST)
2712 Node *arg = lfirst(expr->args);
2713 Oid rettype = expr->funcresulttype;
2714 int32 coercedTypmod;
2716 /* Get the typmod if this is a length-coercion function */
2717 (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod);
2720 * Strip off any type coercions on the input, so we don't print
2721 * redundancies like x::bpchar::character(8).
2723 * XXX Are there any cases where this is a bad idea?
2725 arg = strip_type_coercion(arg, rettype);
2727 appendStringInfoChar(buf, '(');
2728 get_rule_expr(arg, context, showimplicit);
2729 appendStringInfo(buf, ")::%s",
2730 format_type_with_typemod(rettype, coercedTypmod));
2736 * Normal function: display as proname(args). First we need to
2737 * extract the argument datatypes.
2740 foreach(l, expr->args)
2742 Assert(nargs < FUNC_MAX_ARGS);
2743 argtypes[nargs] = exprType((Node *) lfirst(l));
2747 appendStringInfo(buf, "%s(",
2748 generate_function_name(funcoid, nargs, argtypes));
2751 foreach(l, expr->args)
2753 appendStringInfo(buf, sep);
2755 get_rule_expr((Node *) lfirst(l), context, true);
2757 appendStringInfoChar(buf, ')');
2761 * get_agg_expr - Parse back an Aggref node
2764 get_agg_expr(Aggref *aggref, deparse_context *context)
2766 StringInfo buf = context->buf;
2767 Oid argtype = exprType((Node *) aggref->target);
2769 appendStringInfo(buf, "%s(%s",
2770 generate_function_name(aggref->aggfnoid, 1, &argtype),
2771 aggref->aggdistinct ? "DISTINCT " : "");
2772 if (aggref->aggstar)
2773 appendStringInfo(buf, "*");
2775 get_rule_expr((Node *) aggref->target, context, true);
2776 appendStringInfoChar(buf, ')');
2781 * strip_type_coercion
2782 * Strip any type coercion at the top of the given expression tree,
2783 * if it is a coercion to the given datatype.
2785 * We use this to avoid printing two levels of coercion in situations where
2786 * the expression tree has a length-coercion node atop a type-coercion node.
2788 * Note: avoid stripping a length-coercion node, since two successive
2789 * coercions to different lengths aren't a no-op. Also, never strip a
2790 * CoerceToDomain node, even though it might be effectively just RelabelType.
2793 strip_type_coercion(Node *expr, Oid resultType)
2795 if (expr == NULL || exprType(expr) != resultType)
2798 if (IsA(expr, RelabelType) &&
2799 ((RelabelType *) expr)->resulttypmod == -1)
2800 return (Node *) ((RelabelType *) expr)->arg;
2802 if (IsA(expr, FuncExpr))
2804 FuncExpr *func = (FuncExpr *) expr;
2806 if (func->funcformat != COERCE_EXPLICIT_CAST &&
2807 func->funcformat != COERCE_IMPLICIT_CAST)
2808 return expr; /* don't absorb into upper coercion */
2810 if (exprIsLengthCoercion(expr, NULL))
2813 return (Node *) lfirst(func->args);
2823 * Make a string representation of a Const
2827 get_const_expr(Const *constval, deparse_context *context)
2829 StringInfo buf = context->buf;
2831 Form_pg_type typeStruct;
2834 bool isfloat = false;
2837 if (constval->constisnull)
2840 * Always label the type of a NULL constant to prevent
2841 * misdecisions about type when reparsing.
2843 appendStringInfo(buf, "NULL::%s",
2844 format_type_with_typemod(constval->consttype, -1));
2848 typetup = SearchSysCache(TYPEOID,
2849 ObjectIdGetDatum(constval->consttype),
2851 if (!HeapTupleIsValid(typetup))
2852 elog(ERROR, "cache lookup of type %u failed", constval->consttype);
2854 typeStruct = (Form_pg_type) GETSTRUCT(typetup);
2856 extval = DatumGetCString(OidFunctionCall3(typeStruct->typoutput,
2857 constval->constvalue,
2858 ObjectIdGetDatum(typeStruct->typelem),
2859 Int32GetDatum(-1)));
2861 switch (constval->consttype)
2872 * These types are printed without quotes unless they
2873 * contain values that aren't accepted by the scanner
2874 * unquoted (e.g., 'NaN'). Note that strtod() and friends
2875 * might accept NaN, so we can't use that to test.
2877 * In reality we only need to defend against infinity and
2878 * NaN, so we need not get too crazy about pattern
2881 if (strspn(extval, "0123456789+-eE.") == strlen(extval))
2883 appendStringInfoString(buf, extval);
2884 if (strcspn(extval, "eE.") != strlen(extval))
2885 isfloat = true; /* it looks like a float */
2888 appendStringInfo(buf, "'%s'", extval);
2894 appendStringInfo(buf, "B'%s'", extval);
2898 if (strcmp(extval, "t") == 0)
2899 appendStringInfo(buf, "true");
2901 appendStringInfo(buf, "false");
2907 * We must quote any funny characters in the constant's
2908 * representation. XXX Any MULTIBYTE considerations here?
2910 appendStringInfoChar(buf, '\'');
2911 for (valptr = extval; *valptr; valptr++)
2915 if (ch == '\'' || ch == '\\')
2917 appendStringInfoChar(buf, '\\');
2918 appendStringInfoChar(buf, ch);
2920 else if (((unsigned char) ch) < ((unsigned char) ' '))
2921 appendStringInfo(buf, "\\%03o", (int) ch);
2923 appendStringInfoChar(buf, ch);
2925 appendStringInfoChar(buf, '\'');
2932 * Append ::typename unless the constant will be implicitly typed as
2933 * the right type when it is read in. XXX this code has to be kept
2934 * in sync with the behavior of the parser, especially make_const.
2936 switch (constval->consttype)
2941 /* These types can be left unlabeled */
2945 /* Float-looking constants will be typed as numeric */
2946 needlabel = !isfloat;
2953 appendStringInfo(buf, "::%s",
2954 format_type_with_typemod(constval->consttype, -1));
2956 ReleaseSysCache(typetup);
2961 * get_sublink_expr - Parse back a sublink
2965 get_sublink_expr(SubLink *sublink, deparse_context *context)
2967 StringInfo buf = context->buf;
2968 Query *query = (Query *) (sublink->subselect);
2973 if (sublink->subLinkType == ARRAY_SUBLINK)
2974 appendStringInfo(buf, "ARRAY(");
2976 appendStringInfoChar(buf, '(');
2978 if (sublink->lefthand != NIL)
2980 need_paren = (length(sublink->lefthand) > 1);
2982 appendStringInfoChar(buf, '(');
2985 foreach(l, sublink->lefthand)
2987 appendStringInfo(buf, sep);
2989 get_rule_expr((Node *) lfirst(l), context, true);
2993 appendStringInfo(buf, ") ");
2995 appendStringInfoChar(buf, ' ');
3001 * XXX we regurgitate the originally given operator name, with or without
3002 * schema qualification. This is not necessarily 100% right but it's
3003 * the best we can do, since the operators actually used might not all
3004 * be in the same schema.
3006 switch (sublink->subLinkType)
3008 case EXISTS_SUBLINK:
3009 appendStringInfo(buf, "EXISTS ");
3013 if (length(sublink->operName) == 1 &&
3014 strcmp(strVal(lfirst(sublink->operName)), "=") == 0)
3016 /* Represent = ANY as IN */
3017 appendStringInfo(buf, "IN ");
3021 print_operator_name(buf, sublink->operName);
3022 appendStringInfo(buf, " ANY ");
3027 print_operator_name(buf, sublink->operName);
3028 appendStringInfo(buf, " ALL ");
3031 case MULTIEXPR_SUBLINK:
3032 print_operator_name(buf, sublink->operName);
3033 appendStringInfoChar(buf, ' ');
3042 elog(ERROR, "get_sublink_expr: unsupported sublink type %d",
3043 sublink->subLinkType);
3048 appendStringInfoChar(buf, '(');
3050 get_query_def(query, buf, context->namespaces, NULL);
3053 appendStringInfo(buf, "))");
3055 appendStringInfoChar(buf, ')');
3060 * get_from_clause - Parse back a FROM clause
3064 get_from_clause(Query *query, deparse_context *context)
3066 StringInfo buf = context->buf;
3071 * We use the query's jointree as a guide to what to print. However,
3072 * we must ignore auto-added RTEs that are marked not inFromCl. (These
3073 * can only appear at the top level of the jointree, so it's
3074 * sufficient to check here.) Also ignore the rule pseudo-RTEs for NEW
3079 foreach(l, query->jointree->fromlist)
3081 Node *jtnode = (Node *) lfirst(l);
3083 if (IsA(jtnode, RangeTblRef))
3085 int varno = ((RangeTblRef *) jtnode)->rtindex;
3086 RangeTblEntry *rte = rt_fetch(varno, query->rtable);
3090 if (strcmp(rte->eref->aliasname, "*NEW*") == 0)
3092 if (strcmp(rte->eref->aliasname, "*OLD*") == 0)
3096 appendStringInfo(buf, sep);
3097 get_from_clause_item(jtnode, query, context);
3103 get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
3105 StringInfo buf = context->buf;
3107 if (IsA(jtnode, RangeTblRef))
3109 int varno = ((RangeTblRef *) jtnode)->rtindex;
3110 RangeTblEntry *rte = rt_fetch(varno, query->rtable);
3111 List *coldeflist = NIL;
3112 bool gavealias = false;
3114 switch (rte->rtekind)
3117 /* Normal relation RTE */
3118 appendStringInfo(buf, "%s%s",
3120 generate_relation_name(rte->relid));
3124 appendStringInfoChar(buf, '(');
3125 get_query_def(rte->subquery, buf, context->namespaces, NULL);
3126 appendStringInfoChar(buf, ')');
3130 get_rule_expr(rte->funcexpr, context, true);
3131 /* might need to emit column list for RECORD function */
3132 coldeflist = rte->coldeflist;
3135 elog(ERROR, "unexpected rte kind %d", (int) rte->rtekind);
3138 if (rte->alias != NULL)
3140 appendStringInfo(buf, " %s",
3141 quote_identifier(rte->alias->aliasname));
3143 if (rte->alias->colnames != NIL && coldeflist == NIL)
3147 appendStringInfo(buf, "(");
3148 foreach(col, rte->alias->colnames)
3150 if (col != rte->alias->colnames)
3151 appendStringInfo(buf, ", ");
3152 appendStringInfo(buf, "%s",
3153 quote_identifier(strVal(lfirst(col))));
3155 appendStringInfoChar(buf, ')');
3158 else if (rte->rtekind == RTE_RELATION &&
3159 strcmp(rte->eref->aliasname, get_rel_name(rte->relid)) != 0)
3162 * Apparently the rel has been renamed since the rule was
3163 * made. Emit a fake alias clause so that variable references
3164 * will still work. This is not a 100% solution but should
3165 * work in most reasonable situations.
3167 appendStringInfo(buf, " %s",
3168 quote_identifier(rte->eref->aliasname));
3171 if (coldeflist != NIL)
3174 appendStringInfo(buf, " AS ");
3175 get_from_clause_coldeflist(coldeflist, context);
3178 else if (IsA(jtnode, JoinExpr))
3180 JoinExpr *j = (JoinExpr *) jtnode;
3182 appendStringInfoChar(buf, '(');
3183 get_from_clause_item(j->larg, query, context);
3185 appendStringInfo(buf, " NATURAL");
3186 switch (j->jointype)
3190 appendStringInfo(buf, " JOIN ");
3192 appendStringInfo(buf, " CROSS JOIN ");
3195 appendStringInfo(buf, " LEFT JOIN ");
3198 appendStringInfo(buf, " FULL JOIN ");
3201 appendStringInfo(buf, " RIGHT JOIN ");
3204 appendStringInfo(buf, " UNION JOIN ");
3207 elog(ERROR, "get_from_clause_item: unknown join type %d",
3210 get_from_clause_item(j->rarg, query, context);
3217 appendStringInfo(buf, " USING (");
3218 foreach(col, j->using)
3220 if (col != j->using)
3221 appendStringInfo(buf, ", ");
3222 appendStringInfo(buf, "%s",
3223 quote_identifier(strVal(lfirst(col))));
3225 appendStringInfoChar(buf, ')');
3229 appendStringInfo(buf, " ON (");
3230 get_rule_expr(j->quals, context, false);
3231 appendStringInfoChar(buf, ')');
3234 appendStringInfoChar(buf, ')');
3235 /* Yes, it's correct to put alias after the right paren ... */
3236 if (j->alias != NULL)
3238 appendStringInfo(buf, " %s",
3239 quote_identifier(j->alias->aliasname));
3240 if (j->alias->colnames != NIL)
3244 appendStringInfo(buf, "(");
3245 foreach(col, j->alias->colnames)
3247 if (col != j->alias->colnames)
3248 appendStringInfo(buf, ", ");
3249 appendStringInfo(buf, "%s",
3250 quote_identifier(strVal(lfirst(col))));
3252 appendStringInfoChar(buf, ')');
3257 elog(ERROR, "get_from_clause_item: unexpected node type %d",
3262 * get_from_clause_coldeflist - reproduce FROM clause coldeflist
3264 * The coldeflist is appended immediately (no space) to buf. Caller is
3265 * responsible for ensuring that an alias or AS is present before it.
3268 get_from_clause_coldeflist(List *coldeflist, deparse_context *context)
3270 StringInfo buf = context->buf;
3274 appendStringInfoChar(buf, '(');
3276 foreach(col, coldeflist)
3278 ColumnDef *n = lfirst(col);
3283 attname = n->colname;
3284 atttypeid = typenameTypeId(n->typename);
3285 atttypmod = n->typename->typmod;
3288 appendStringInfo(buf, ", ");
3289 appendStringInfo(buf, "%s %s",
3290 quote_identifier(attname),
3291 format_type_with_typemod(atttypeid, atttypmod));
3295 appendStringInfoChar(buf, ')');
3299 * get_opclass_name - fetch name of an index operator class
3301 * The opclass name is appended (after a space) to buf.
3303 * Output is suppressed if the opclass is the default for the given
3304 * actual_datatype. (If you don't want this behavior, just pass
3305 * InvalidOid for actual_datatype.)
3308 get_opclass_name(Oid opclass, Oid actual_datatype,
3312 Form_pg_opclass opcrec;
3316 /* Domains use their base type's default opclass */
3317 if (OidIsValid(actual_datatype))
3318 actual_datatype = getBaseType(actual_datatype);
3320 ht_opc = SearchSysCache(CLAOID,
3321 ObjectIdGetDatum(opclass),
3323 if (!HeapTupleIsValid(ht_opc))
3324 elog(ERROR, "cache lookup failed for opclass %u", opclass);
3325 opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
3326 if (actual_datatype != opcrec->opcintype || !opcrec->opcdefault)
3328 /* Okay, we need the opclass name. Do we need to qualify it? */
3329 opcname = NameStr(opcrec->opcname);
3330 if (OpclassIsVisible(opclass))
3331 appendStringInfo(buf, " %s", quote_identifier(opcname));
3334 nspname = get_namespace_name(opcrec->opcnamespace);
3335 appendStringInfo(buf, " %s.%s",
3336 quote_identifier(nspname),
3337 quote_identifier(opcname));
3340 ReleaseSysCache(ht_opc);
3344 * tleIsArrayAssign - check for array assignment
3347 tleIsArrayAssign(TargetEntry *tle)
3351 if (tle->expr == NULL || !IsA(tle->expr, ArrayRef))
3353 aref = (ArrayRef *) tle->expr;
3354 if (aref->refassgnexpr == NULL)
3358 * Currently, it should only be possible to see non-null refassgnexpr
3359 * if we are indeed looking at an "UPDATE array[n] = expr" situation.
3360 * So aref->refexpr ought to match the tle's target.
3362 if (aref->refexpr == NULL || !IsA(aref->refexpr, Var) ||
3363 ((Var *) aref->refexpr)->varattno != tle->resdom->resno)
3364 elog(WARNING, "tleIsArrayAssign: I'm confused ...");
3369 * quote_identifier - Quote an identifier only if needed
3371 * When quotes are needed, we palloc the required space; slightly
3372 * space-wasteful but well worth it for notational simplicity.
3375 quote_identifier(const char *ident)
3378 * Can avoid quoting if ident starts with a lowercase letter or
3379 * underscore and contains only lowercase letters, digits, and
3380 * underscores, *and* is not any SQL keyword. Otherwise, supply
3390 * would like to use <ctype.h> macros here, but they might yield
3391 * unwanted locale-specific results...
3393 safe = ((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_');
3395 for (ptr = ident; *ptr; ptr++)
3399 if ((ch >= 'a' && ch <= 'z') ||
3400 (ch >= '0' && ch <= '9') ||
3416 * Check for keyword. This test is overly strong, since many of
3417 * the "keywords" known to the parser are usable as column names,
3418 * but the parser doesn't provide any easy way to test for whether
3419 * an identifier is safe or not... so be safe not sorry.
3421 * Note: ScanKeywordLookup() does case-insensitive comparison, but
3422 * that's fine, since we already know we have all-lower-case.
3424 if (ScanKeywordLookup(ident) != NULL)
3429 return ident; /* no change needed */
3431 result = (char *) palloc(strlen(ident) + nquotes + 2 + 1);
3435 for (ptr = ident; *ptr; ptr++)
3450 * quote_qualified_identifier - Quote a possibly-qualified identifier
3452 * Return a name of the form namespace.ident, or just ident if namespace
3453 * is NULL, quoting each component if necessary. The result is palloc'd.
3456 quote_qualified_identifier(const char *namespace,
3461 initStringInfo(&buf);
3463 appendStringInfo(&buf, "%s.", quote_identifier(namespace));
3464 appendStringInfo(&buf, "%s", quote_identifier(ident));
3469 * generate_relation_name
3470 * Compute the name to display for a relation specified by OID
3472 * The result includes all necessary quoting and schema-prefixing.
3475 generate_relation_name(Oid relid)
3478 Form_pg_class reltup;
3482 tp = SearchSysCache(RELOID,
3483 ObjectIdGetDatum(relid),
3485 if (!HeapTupleIsValid(tp))
3486 elog(ERROR, "cache lookup of relation %u failed", relid);
3487 reltup = (Form_pg_class) GETSTRUCT(tp);
3489 /* Qualify the name if not visible in search path */
3490 if (RelationIsVisible(relid))
3493 nspname = get_namespace_name(reltup->relnamespace);
3495 result = quote_qualified_identifier(nspname, NameStr(reltup->relname));
3497 ReleaseSysCache(tp);
3503 * generate_function_name
3504 * Compute the name to display for a function specified by OID,
3505 * given that it is being called with the specified actual arg types.
3506 * (Arg types matter because of ambiguous-function resolution rules.)
3508 * The result includes all necessary quoting and schema-prefixing.
3511 generate_function_name(Oid funcid, int nargs, Oid *argtypes)
3514 Form_pg_proc procform;
3518 FuncDetailCode p_result;
3522 Oid *p_true_typeids;
3524 proctup = SearchSysCache(PROCOID,
3525 ObjectIdGetDatum(funcid),
3527 if (!HeapTupleIsValid(proctup))
3528 elog(ERROR, "cache lookup of function %u failed", funcid);
3529 procform = (Form_pg_proc) GETSTRUCT(proctup);
3530 proname = NameStr(procform->proname);
3531 Assert(nargs == procform->pronargs);
3534 * The idea here is to schema-qualify only if the parser would fail to
3535 * resolve the correct function given the unqualified func name with
3536 * the specified argtypes.
3538 p_result = func_get_detail(makeList1(makeString(proname)),
3539 NIL, nargs, argtypes,
3540 &p_funcid, &p_rettype,
3541 &p_retset, &p_true_typeids);
3542 if ((p_result == FUNCDETAIL_NORMAL || p_result == FUNCDETAIL_AGGREGATE) &&
3546 nspname = get_namespace_name(procform->pronamespace);
3548 result = quote_qualified_identifier(nspname, proname);
3550 ReleaseSysCache(proctup);
3556 * generate_operator_name
3557 * Compute the name to display for an operator specified by OID,
3558 * given that it is being called with the specified actual arg types.
3559 * (Arg types matter because of ambiguous-operator resolution rules.
3560 * Pass InvalidOid for unused arg of a unary operator.)
3562 * The result includes all necessary quoting and schema-prefixing,
3563 * plus the OPERATOR() decoration needed to use a qualified operator name
3567 generate_operator_name(Oid operid, Oid arg1, Oid arg2)
3571 Form_pg_operator operform;
3576 initStringInfo(&buf);
3578 opertup = SearchSysCache(OPEROID,
3579 ObjectIdGetDatum(operid),
3581 if (!HeapTupleIsValid(opertup))
3582 elog(ERROR, "cache lookup of operator %u failed", operid);
3583 operform = (Form_pg_operator) GETSTRUCT(opertup);
3584 oprname = NameStr(operform->oprname);
3587 * The idea here is to schema-qualify only if the parser would fail to
3588 * resolve the correct operator given the unqualified op name with the
3589 * specified argtypes.
3591 switch (operform->oprkind)
3594 p_result = oper(makeList1(makeString(oprname)), arg1, arg2, true);
3597 p_result = left_oper(makeList1(makeString(oprname)), arg2, true);
3600 p_result = right_oper(makeList1(makeString(oprname)), arg1, true);
3603 elog(ERROR, "unexpected oprkind %c for operator %u",
3604 operform->oprkind, operid);
3605 p_result = NULL; /* keep compiler quiet */
3609 if (p_result != NULL && oprid(p_result) == operid)
3613 nspname = get_namespace_name(operform->oprnamespace);
3614 appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname));
3617 appendStringInfo(&buf, "%s", oprname);
3620 appendStringInfoChar(&buf, ')');
3622 if (p_result != NULL)
3623 ReleaseSysCache(p_result);
3625 ReleaseSysCache(opertup);
3631 * Print out a possibly-qualified operator name
3634 print_operator_name(StringInfo buf, List *opname)
3636 int nnames = length(opname);
3639 appendStringInfo(buf, "%s", strVal(lfirst(opname)));
3642 appendStringInfo(buf, "OPERATOR(");
3643 while (nnames-- > 1)
3645 appendStringInfo(buf, "%s.",
3646 quote_identifier(strVal(lfirst(opname))));
3647 opname = lnext(opname);
3649 appendStringInfo(buf, "%s)", strVal(lfirst(opname)));
3654 * get_relid_attribute_name
3655 * Get an attribute name by its relations Oid and its attnum
3657 * Same as underlying syscache routine get_attname(), except that error
3658 * is handled by elog() instead of returning NULL.
3661 get_relid_attribute_name(Oid relid, AttrNumber attnum)
3665 attname = get_attname(relid, attnum);
3666 if (attname == NULL)
3667 elog(ERROR, "cache lookup of attribute %d in relation %u failed",