1 /*-------------------------------------------------------------------------
4 * Output functions for Postgres tree nodes.
6 * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/nodes/outfuncs.c
13 *-------------------------------------------------------------------------
19 #include "access/attnum.h"
20 #include "common/shortest_dec.h"
21 #include "lib/stringinfo.h"
22 #include "miscadmin.h"
23 #include "nodes/bitmapset.h"
24 #include "nodes/nodes.h"
25 #include "nodes/pg_list.h"
26 #include "utils/datum.h"
28 static void outChar(StringInfo str
, char c
);
29 static void outDouble(StringInfo str
, double d
);
33 * Macros to simplify output of different kinds of fields. Use these
34 * wherever possible to reduce the chance for silly typos. Note that these
35 * hard-wire conventions about the names of the local variables in an Out
39 /* Write the label for the node type */
40 #define WRITE_NODE_TYPE(nodelabel) \
41 appendStringInfoString(str, nodelabel)
43 /* Write an integer field (anything written as ":fldname %d") */
44 #define WRITE_INT_FIELD(fldname) \
45 appendStringInfo(str, " :" CppAsString(fldname) " %d", node->fldname)
47 /* Write an unsigned integer field (anything written as ":fldname %u") */
48 #define WRITE_UINT_FIELD(fldname) \
49 appendStringInfo(str, " :" CppAsString(fldname) " %u", node->fldname)
51 /* Write an unsigned integer field (anything written with UINT64_FORMAT) */
52 #define WRITE_UINT64_FIELD(fldname) \
53 appendStringInfo(str, " :" CppAsString(fldname) " " UINT64_FORMAT, \
56 /* Write an OID field (don't hard-wire assumption that OID is same as uint) */
57 #define WRITE_OID_FIELD(fldname) \
58 appendStringInfo(str, " :" CppAsString(fldname) " %u", node->fldname)
60 /* Write a long-integer field */
61 #define WRITE_LONG_FIELD(fldname) \
62 appendStringInfo(str, " :" CppAsString(fldname) " %ld", node->fldname)
64 /* Write a char field (ie, one ascii character) */
65 #define WRITE_CHAR_FIELD(fldname) \
66 (appendStringInfo(str, " :" CppAsString(fldname) " "), \
67 outChar(str, node->fldname))
69 /* Write an enumerated-type field as an integer code */
70 #define WRITE_ENUM_FIELD(fldname, enumtype) \
71 appendStringInfo(str, " :" CppAsString(fldname) " %d", \
74 /* Write a float field (actually, they're double) */
75 #define WRITE_FLOAT_FIELD(fldname) \
76 (appendStringInfo(str, " :" CppAsString(fldname) " "), \
77 outDouble(str, node->fldname))
79 /* Write a boolean field */
80 #define WRITE_BOOL_FIELD(fldname) \
81 appendStringInfo(str, " :" CppAsString(fldname) " %s", \
82 booltostr(node->fldname))
84 /* Write a character-string (possibly NULL) field */
85 #define WRITE_STRING_FIELD(fldname) \
86 (appendStringInfoString(str, " :" CppAsString(fldname) " "), \
87 outToken(str, node->fldname))
89 /* Write a parse location field (actually same as INT case) */
90 #define WRITE_LOCATION_FIELD(fldname) \
91 appendStringInfo(str, " :" CppAsString(fldname) " %d", node->fldname)
93 /* Write a Node field */
94 #define WRITE_NODE_FIELD(fldname) \
95 (appendStringInfoString(str, " :" CppAsString(fldname) " "), \
96 outNode(str, node->fldname))
98 /* Write a bitmapset field */
99 #define WRITE_BITMAPSET_FIELD(fldname) \
100 (appendStringInfoString(str, " :" CppAsString(fldname) " "), \
101 outBitmapset(str, node->fldname))
103 /* Write a variable-length array (not a List) of Node pointers */
104 #define WRITE_NODE_ARRAY(fldname, len) \
105 (appendStringInfoString(str, " :" CppAsString(fldname) " "), \
106 writeNodeArray(str, (const Node * const *) node->fldname, len))
108 /* Write a variable-length array of AttrNumber */
109 #define WRITE_ATTRNUMBER_ARRAY(fldname, len) \
110 (appendStringInfoString(str, " :" CppAsString(fldname) " "), \
111 writeAttrNumberCols(str, node->fldname, len))
113 /* Write a variable-length array of Oid */
114 #define WRITE_OID_ARRAY(fldname, len) \
115 (appendStringInfoString(str, " :" CppAsString(fldname) " "), \
116 writeOidCols(str, node->fldname, len))
118 /* Write a variable-length array of Index */
119 #define WRITE_INDEX_ARRAY(fldname, len) \
120 (appendStringInfoString(str, " :" CppAsString(fldname) " "), \
121 writeIndexCols(str, node->fldname, len))
123 /* Write a variable-length array of int */
124 #define WRITE_INT_ARRAY(fldname, len) \
125 (appendStringInfoString(str, " :" CppAsString(fldname) " "), \
126 writeIntCols(str, node->fldname, len))
128 /* Write a variable-length array of bool */
129 #define WRITE_BOOL_ARRAY(fldname, len) \
130 (appendStringInfoString(str, " :" CppAsString(fldname) " "), \
131 writeBoolCols(str, node->fldname, len))
133 #define booltostr(x) ((x) ? "true" : "false")
138 * Convert an ordinary string (eg, an identifier) into a form that
139 * will be decoded back to a plain token by read.c's functions.
141 * If a null string pointer is given, it is encoded as '<>'.
142 * An empty string is encoded as '""'. To avoid ambiguity, input
143 * strings beginning with '<' or '"' receive a leading backslash.
146 outToken(StringInfo str
, const char *s
)
150 appendStringInfoString(str
, "<>");
155 appendStringInfoString(str
, "\"\"");
160 * Look for characters or patterns that are treated specially by read.c
161 * (either in pg_strtok() or in nodeRead()), and therefore need a
162 * protective backslash.
164 /* These characters only need to be quoted at the start of the string */
167 isdigit((unsigned char) *s
) ||
168 ((*s
== '+' || *s
== '-') &&
169 (isdigit((unsigned char) s
[1]) || s
[1] == '.')))
170 appendStringInfoChar(str
, '\\');
173 /* These chars must be backslashed anywhere in the string */
174 if (*s
== ' ' || *s
== '\n' || *s
== '\t' ||
175 *s
== '(' || *s
== ')' || *s
== '{' || *s
== '}' ||
177 appendStringInfoChar(str
, '\\');
178 appendStringInfoChar(str
, *s
++);
183 * Convert one char. Goes through outToken() so that special characters are
187 outChar(StringInfo str
, char c
)
191 /* Traditionally, we've represented \0 as <>, so keep doing that */
194 appendStringInfoString(str
, "<>");
205 * Convert a double value, attempting to ensure the value is preserved exactly.
208 outDouble(StringInfo str
, double d
)
210 char buf
[DOUBLE_SHORTEST_DECIMAL_LEN
];
212 double_to_shortest_decimal_buf(d
, buf
);
213 appendStringInfoString(str
, buf
);
217 * common implementation for scalar-array-writing functions
219 * The data format is either "<>" for a NULL pointer or "(item item item)".
220 * fmtstr must include a leading space, and the rest of it must produce
221 * something that will be seen as a single simple token by pg_strtok().
222 * convfunc can be empty, or the name of a conversion macro or function.
224 #define WRITE_SCALAR_ARRAY(fnname, datatype, fmtstr, convfunc) \
226 fnname(StringInfo str, const datatype *arr, int len) \
230 appendStringInfoChar(str, '('); \
231 for (int i = 0; i < len; i++) \
232 appendStringInfo(str, fmtstr, convfunc(arr[i])); \
233 appendStringInfoChar(str, ')'); \
236 appendStringInfoString(str, "<>"); \
239 WRITE_SCALAR_ARRAY(writeAttrNumberCols
, AttrNumber
, " %d",)
240 WRITE_SCALAR_ARRAY(writeOidCols
, Oid
, " %u",)
241 WRITE_SCALAR_ARRAY(writeIndexCols
, Index
, " %u",)
242 WRITE_SCALAR_ARRAY(writeIntCols
, int, " %d",)
243 WRITE_SCALAR_ARRAY(writeBoolCols
, bool, " %s", booltostr
)
246 * Print an array (not a List) of Node pointers.
248 * The decoration is identical to that of scalar arrays, but we can't
249 * quite use appendStringInfo() in the loop.
252 writeNodeArray(StringInfo str
, const Node
*const *arr
, int len
)
256 appendStringInfoChar(str
, '(');
257 for (int i
= 0; i
< len
; i
++)
259 appendStringInfoChar(str
, ' ');
260 outNode(str
, arr
[i
]);
262 appendStringInfoChar(str
, ')');
265 appendStringInfoString(str
, "<>");
272 _outList(StringInfo str
, const List
*node
)
276 appendStringInfoChar(str
, '(');
278 if (IsA(node
, IntList
))
279 appendStringInfoChar(str
, 'i');
280 else if (IsA(node
, OidList
))
281 appendStringInfoChar(str
, 'o');
282 else if (IsA(node
, XidList
))
283 appendStringInfoChar(str
, 'x');
288 * For the sake of backward compatibility, we emit a slightly
289 * different whitespace format for lists of nodes vs. other types of
290 * lists. XXX: is this necessary?
294 outNode(str
, lfirst(lc
));
296 appendStringInfoChar(str
, ' ');
298 else if (IsA(node
, IntList
))
299 appendStringInfo(str
, " %d", lfirst_int(lc
));
300 else if (IsA(node
, OidList
))
301 appendStringInfo(str
, " %u", lfirst_oid(lc
));
302 else if (IsA(node
, XidList
))
303 appendStringInfo(str
, " %u", lfirst_xid(lc
));
305 elog(ERROR
, "unrecognized list node type: %d",
309 appendStringInfoChar(str
, ')');
314 * converts a bitmap set of integers
316 * Note: the output format is "(b int int ...)", similar to an integer List.
318 * We export this function for use by extensions that define extensible nodes.
319 * That's somewhat historical, though, because calling outNode() will work.
322 outBitmapset(StringInfo str
, const Bitmapset
*bms
)
326 appendStringInfoChar(str
, '(');
327 appendStringInfoChar(str
, 'b');
329 while ((x
= bms_next_member(bms
, x
)) >= 0)
330 appendStringInfo(str
, " %d", x
);
331 appendStringInfoChar(str
, ')');
335 * Print the value of a Datum given its type.
338 outDatum(StringInfo str
, Datum value
, int typlen
, bool typbyval
)
344 length
= datumGetSize(value
, typbyval
, typlen
);
348 s
= (char *) (&value
);
349 appendStringInfo(str
, "%u [ ", (unsigned int) length
);
350 for (i
= 0; i
< (Size
) sizeof(Datum
); i
++)
351 appendStringInfo(str
, "%d ", (int) (s
[i
]));
352 appendStringInfoChar(str
, ']');
356 s
= (char *) DatumGetPointer(value
);
357 if (!PointerIsValid(s
))
358 appendStringInfoString(str
, "0 [ ]");
361 appendStringInfo(str
, "%u [ ", (unsigned int) length
);
362 for (i
= 0; i
< length
; i
++)
363 appendStringInfo(str
, "%d ", (int) (s
[i
]));
364 appendStringInfoChar(str
, ']');
370 #include "outfuncs.funcs.c"
374 * Support functions for nodes with custom_read_write attribute or
375 * special_read_write attribute
379 _outConst(StringInfo str
, const Const
*node
)
381 WRITE_NODE_TYPE("CONST");
383 WRITE_OID_FIELD(consttype
);
384 WRITE_INT_FIELD(consttypmod
);
385 WRITE_OID_FIELD(constcollid
);
386 WRITE_INT_FIELD(constlen
);
387 WRITE_BOOL_FIELD(constbyval
);
388 WRITE_BOOL_FIELD(constisnull
);
389 WRITE_LOCATION_FIELD(location
);
391 appendStringInfoString(str
, " :constvalue ");
392 if (node
->constisnull
)
393 appendStringInfoString(str
, "<>");
395 outDatum(str
, node
->constvalue
, node
->constlen
, node
->constbyval
);
399 _outBoolExpr(StringInfo str
, const BoolExpr
*node
)
403 WRITE_NODE_TYPE("BOOLEXPR");
405 /* do-it-yourself enum representation */
406 switch (node
->boolop
)
418 appendStringInfoString(str
, " :boolop ");
419 outToken(str
, opstr
);
421 WRITE_NODE_FIELD(args
);
422 WRITE_LOCATION_FIELD(location
);
426 _outForeignKeyOptInfo(StringInfo str
, const ForeignKeyOptInfo
*node
)
430 WRITE_NODE_TYPE("FOREIGNKEYOPTINFO");
432 WRITE_UINT_FIELD(con_relid
);
433 WRITE_UINT_FIELD(ref_relid
);
434 WRITE_INT_FIELD(nkeys
);
435 WRITE_ATTRNUMBER_ARRAY(conkey
, node
->nkeys
);
436 WRITE_ATTRNUMBER_ARRAY(confkey
, node
->nkeys
);
437 WRITE_OID_ARRAY(conpfeqop
, node
->nkeys
);
438 WRITE_INT_FIELD(nmatched_ec
);
439 WRITE_INT_FIELD(nconst_ec
);
440 WRITE_INT_FIELD(nmatched_rcols
);
441 WRITE_INT_FIELD(nmatched_ri
);
442 /* for compactness, just print the number of matches per column: */
443 appendStringInfoString(str
, " :eclass");
444 for (i
= 0; i
< node
->nkeys
; i
++)
445 appendStringInfo(str
, " %d", (node
->eclass
[i
] != NULL
));
446 appendStringInfoString(str
, " :rinfos");
447 for (i
= 0; i
< node
->nkeys
; i
++)
448 appendStringInfo(str
, " %d", list_length(node
->rinfos
[i
]));
452 _outEquivalenceClass(StringInfo str
, const EquivalenceClass
*node
)
455 * To simplify reading, we just chase up to the topmost merged EC and
456 * print that, without bothering to show the merge-ees separately.
458 while (node
->ec_merged
)
459 node
= node
->ec_merged
;
461 WRITE_NODE_TYPE("EQUIVALENCECLASS");
463 WRITE_NODE_FIELD(ec_opfamilies
);
464 WRITE_OID_FIELD(ec_collation
);
465 WRITE_NODE_FIELD(ec_members
);
466 WRITE_NODE_FIELD(ec_sources
);
467 WRITE_NODE_FIELD(ec_derives
);
468 WRITE_BITMAPSET_FIELD(ec_relids
);
469 WRITE_BOOL_FIELD(ec_has_const
);
470 WRITE_BOOL_FIELD(ec_has_volatile
);
471 WRITE_BOOL_FIELD(ec_broken
);
472 WRITE_UINT_FIELD(ec_sortref
);
473 WRITE_UINT_FIELD(ec_min_security
);
474 WRITE_UINT_FIELD(ec_max_security
);
478 _outExtensibleNode(StringInfo str
, const ExtensibleNode
*node
)
480 const ExtensibleNodeMethods
*methods
;
482 methods
= GetExtensibleNodeMethods(node
->extnodename
, false);
484 WRITE_NODE_TYPE("EXTENSIBLENODE");
486 WRITE_STRING_FIELD(extnodename
);
488 /* serialize the private fields */
489 methods
->nodeOut(str
, node
);
493 _outRangeTblEntry(StringInfo str
, const RangeTblEntry
*node
)
495 WRITE_NODE_TYPE("RANGETBLENTRY");
497 /* put alias + eref first to make dump more legible */
498 WRITE_NODE_FIELD(alias
);
499 WRITE_NODE_FIELD(eref
);
500 WRITE_ENUM_FIELD(rtekind
, RTEKind
);
502 switch (node
->rtekind
)
505 WRITE_OID_FIELD(relid
);
506 WRITE_CHAR_FIELD(relkind
);
507 WRITE_INT_FIELD(rellockmode
);
508 WRITE_NODE_FIELD(tablesample
);
509 WRITE_UINT_FIELD(perminfoindex
);
512 WRITE_NODE_FIELD(subquery
);
513 WRITE_BOOL_FIELD(security_barrier
);
514 /* we re-use these RELATION fields, too: */
515 WRITE_OID_FIELD(relid
);
516 WRITE_CHAR_FIELD(relkind
);
517 WRITE_INT_FIELD(rellockmode
);
518 WRITE_UINT_FIELD(perminfoindex
);
521 WRITE_ENUM_FIELD(jointype
, JoinType
);
522 WRITE_INT_FIELD(joinmergedcols
);
523 WRITE_NODE_FIELD(joinaliasvars
);
524 WRITE_NODE_FIELD(joinleftcols
);
525 WRITE_NODE_FIELD(joinrightcols
);
526 WRITE_NODE_FIELD(join_using_alias
);
529 WRITE_NODE_FIELD(functions
);
530 WRITE_BOOL_FIELD(funcordinality
);
533 WRITE_NODE_FIELD(tablefunc
);
536 WRITE_NODE_FIELD(values_lists
);
537 WRITE_NODE_FIELD(coltypes
);
538 WRITE_NODE_FIELD(coltypmods
);
539 WRITE_NODE_FIELD(colcollations
);
542 WRITE_STRING_FIELD(ctename
);
543 WRITE_UINT_FIELD(ctelevelsup
);
544 WRITE_BOOL_FIELD(self_reference
);
545 WRITE_NODE_FIELD(coltypes
);
546 WRITE_NODE_FIELD(coltypmods
);
547 WRITE_NODE_FIELD(colcollations
);
549 case RTE_NAMEDTUPLESTORE
:
550 WRITE_STRING_FIELD(enrname
);
551 WRITE_FLOAT_FIELD(enrtuples
);
552 WRITE_NODE_FIELD(coltypes
);
553 WRITE_NODE_FIELD(coltypmods
);
554 WRITE_NODE_FIELD(colcollations
);
555 /* we re-use these RELATION fields, too: */
556 WRITE_OID_FIELD(relid
);
559 /* no extra fields */
562 elog(ERROR
, "unrecognized RTE kind: %d", (int) node
->rtekind
);
566 WRITE_BOOL_FIELD(lateral
);
567 WRITE_BOOL_FIELD(inh
);
568 WRITE_BOOL_FIELD(inFromCl
);
569 WRITE_NODE_FIELD(securityQuals
);
573 _outA_Expr(StringInfo str
, const A_Expr
*node
)
575 WRITE_NODE_TYPE("A_EXPR");
580 WRITE_NODE_FIELD(name
);
583 appendStringInfoString(str
, " ANY");
584 WRITE_NODE_FIELD(name
);
587 appendStringInfoString(str
, " ALL");
588 WRITE_NODE_FIELD(name
);
591 appendStringInfoString(str
, " DISTINCT");
592 WRITE_NODE_FIELD(name
);
594 case AEXPR_NOT_DISTINCT
:
595 appendStringInfoString(str
, " NOT_DISTINCT");
596 WRITE_NODE_FIELD(name
);
599 appendStringInfoString(str
, " NULLIF");
600 WRITE_NODE_FIELD(name
);
603 appendStringInfoString(str
, " IN");
604 WRITE_NODE_FIELD(name
);
607 appendStringInfoString(str
, " LIKE");
608 WRITE_NODE_FIELD(name
);
611 appendStringInfoString(str
, " ILIKE");
612 WRITE_NODE_FIELD(name
);
615 appendStringInfoString(str
, " SIMILAR");
616 WRITE_NODE_FIELD(name
);
619 appendStringInfoString(str
, " BETWEEN");
620 WRITE_NODE_FIELD(name
);
622 case AEXPR_NOT_BETWEEN
:
623 appendStringInfoString(str
, " NOT_BETWEEN");
624 WRITE_NODE_FIELD(name
);
626 case AEXPR_BETWEEN_SYM
:
627 appendStringInfoString(str
, " BETWEEN_SYM");
628 WRITE_NODE_FIELD(name
);
630 case AEXPR_NOT_BETWEEN_SYM
:
631 appendStringInfoString(str
, " NOT_BETWEEN_SYM");
632 WRITE_NODE_FIELD(name
);
635 elog(ERROR
, "unrecognized A_Expr_Kind: %d", (int) node
->kind
);
639 WRITE_NODE_FIELD(lexpr
);
640 WRITE_NODE_FIELD(rexpr
);
641 WRITE_LOCATION_FIELD(location
);
645 _outInteger(StringInfo str
, const Integer
*node
)
647 appendStringInfo(str
, "%d", node
->ival
);
651 _outFloat(StringInfo str
, const Float
*node
)
654 * We assume the value is a valid numeric literal and so does not need
657 appendStringInfoString(str
, node
->fval
);
661 _outBoolean(StringInfo str
, const Boolean
*node
)
663 appendStringInfoString(str
, node
->boolval
? "true" : "false");
667 _outString(StringInfo str
, const String
*node
)
670 * We use outToken to provide escaping of the string's content, but we
671 * don't want it to convert an empty string to '""', because we're putting
672 * double quotes around the string already.
674 appendStringInfoChar(str
, '"');
675 if (node
->sval
[0] != '\0')
676 outToken(str
, node
->sval
);
677 appendStringInfoChar(str
, '"');
681 _outBitString(StringInfo str
, const BitString
*node
)
684 * The lexer will always produce a string starting with 'b' or 'x'. There
685 * might be characters following that that need escaping, but outToken
686 * won't escape the 'b' or 'x'. This is relied on by nodeTokenType.
688 Assert(node
->bsval
[0] == 'b' || node
->bsval
[0] == 'x');
689 outToken(str
, node
->bsval
);
693 _outA_Const(StringInfo str
, const A_Const
*node
)
695 WRITE_NODE_TYPE("A_CONST");
698 appendStringInfoString(str
, " NULL");
701 appendStringInfoString(str
, " :val ");
702 outNode(str
, &node
->val
);
704 WRITE_LOCATION_FIELD(location
);
708 _outConstraint(StringInfo str
, const Constraint
*node
)
710 WRITE_NODE_TYPE("CONSTRAINT");
712 WRITE_STRING_FIELD(conname
);
713 WRITE_BOOL_FIELD(deferrable
);
714 WRITE_BOOL_FIELD(initdeferred
);
715 WRITE_LOCATION_FIELD(location
);
717 appendStringInfoString(str
, " :contype ");
718 switch (node
->contype
)
721 appendStringInfoString(str
, "NULL");
725 appendStringInfoString(str
, "NOT_NULL");
729 appendStringInfoString(str
, "DEFAULT");
730 WRITE_NODE_FIELD(raw_expr
);
731 WRITE_STRING_FIELD(cooked_expr
);
734 case CONSTR_IDENTITY
:
735 appendStringInfoString(str
, "IDENTITY");
736 WRITE_NODE_FIELD(options
);
737 WRITE_CHAR_FIELD(generated_when
);
740 case CONSTR_GENERATED
:
741 appendStringInfoString(str
, "GENERATED");
742 WRITE_NODE_FIELD(raw_expr
);
743 WRITE_STRING_FIELD(cooked_expr
);
744 WRITE_CHAR_FIELD(generated_when
);
748 appendStringInfoString(str
, "CHECK");
749 WRITE_BOOL_FIELD(is_no_inherit
);
750 WRITE_NODE_FIELD(raw_expr
);
751 WRITE_STRING_FIELD(cooked_expr
);
752 WRITE_BOOL_FIELD(skip_validation
);
753 WRITE_BOOL_FIELD(initially_valid
);
757 appendStringInfoString(str
, "PRIMARY_KEY");
758 WRITE_NODE_FIELD(keys
);
759 WRITE_NODE_FIELD(including
);
760 WRITE_NODE_FIELD(options
);
761 WRITE_STRING_FIELD(indexname
);
762 WRITE_STRING_FIELD(indexspace
);
763 WRITE_BOOL_FIELD(reset_default_tblspc
);
764 /* access_method and where_clause not currently used */
768 appendStringInfoString(str
, "UNIQUE");
769 WRITE_BOOL_FIELD(nulls_not_distinct
);
770 WRITE_NODE_FIELD(keys
);
771 WRITE_NODE_FIELD(including
);
772 WRITE_NODE_FIELD(options
);
773 WRITE_STRING_FIELD(indexname
);
774 WRITE_STRING_FIELD(indexspace
);
775 WRITE_BOOL_FIELD(reset_default_tblspc
);
776 /* access_method and where_clause not currently used */
779 case CONSTR_EXCLUSION
:
780 appendStringInfoString(str
, "EXCLUSION");
781 WRITE_NODE_FIELD(exclusions
);
782 WRITE_NODE_FIELD(including
);
783 WRITE_NODE_FIELD(options
);
784 WRITE_STRING_FIELD(indexname
);
785 WRITE_STRING_FIELD(indexspace
);
786 WRITE_BOOL_FIELD(reset_default_tblspc
);
787 WRITE_STRING_FIELD(access_method
);
788 WRITE_NODE_FIELD(where_clause
);
792 appendStringInfoString(str
, "FOREIGN_KEY");
793 WRITE_NODE_FIELD(pktable
);
794 WRITE_NODE_FIELD(fk_attrs
);
795 WRITE_NODE_FIELD(pk_attrs
);
796 WRITE_CHAR_FIELD(fk_matchtype
);
797 WRITE_CHAR_FIELD(fk_upd_action
);
798 WRITE_CHAR_FIELD(fk_del_action
);
799 WRITE_NODE_FIELD(fk_del_set_cols
);
800 WRITE_NODE_FIELD(old_conpfeqop
);
801 WRITE_OID_FIELD(old_pktable_oid
);
802 WRITE_BOOL_FIELD(skip_validation
);
803 WRITE_BOOL_FIELD(initially_valid
);
806 case CONSTR_ATTR_DEFERRABLE
:
807 appendStringInfoString(str
, "ATTR_DEFERRABLE");
810 case CONSTR_ATTR_NOT_DEFERRABLE
:
811 appendStringInfoString(str
, "ATTR_NOT_DEFERRABLE");
814 case CONSTR_ATTR_DEFERRED
:
815 appendStringInfoString(str
, "ATTR_DEFERRED");
818 case CONSTR_ATTR_IMMEDIATE
:
819 appendStringInfoString(str
, "ATTR_IMMEDIATE");
823 elog(ERROR
, "unrecognized ConstrType: %d", (int) node
->contype
);
831 * converts a Node into ascii string and append it to 'str'
834 outNode(StringInfo str
, const void *obj
)
836 /* Guard against stack overflow due to overly complex expressions */
840 appendStringInfoString(str
, "<>");
841 else if (IsA(obj
, List
) || IsA(obj
, IntList
) || IsA(obj
, OidList
) ||
844 /* nodeRead does not want to see { } around these! */
845 else if (IsA(obj
, Integer
))
846 _outInteger(str
, (Integer
*) obj
);
847 else if (IsA(obj
, Float
))
848 _outFloat(str
, (Float
*) obj
);
849 else if (IsA(obj
, Boolean
))
850 _outBoolean(str
, (Boolean
*) obj
);
851 else if (IsA(obj
, String
))
852 _outString(str
, (String
*) obj
);
853 else if (IsA(obj
, BitString
))
854 _outBitString(str
, (BitString
*) obj
);
855 else if (IsA(obj
, Bitmapset
))
856 outBitmapset(str
, (Bitmapset
*) obj
);
859 appendStringInfoChar(str
, '{');
860 switch (nodeTag(obj
))
862 #include "outfuncs.switch.c"
867 * This should be an ERROR, but it's too useful to be able to
868 * dump structures that outNode only understands part of.
870 elog(WARNING
, "could not dump unrecognized node type: %d",
874 appendStringInfoChar(str
, '}');
880 * returns the ascii representation of the Node as a palloc'd string
883 nodeToString(const void *obj
)
887 /* see stringinfo.h for an explanation of this maneuver */
888 initStringInfo(&str
);
895 * returns the ascii representation of the Bitmapset as a palloc'd string
898 bmsToString(const Bitmapset
*bms
)
902 /* see stringinfo.h for an explanation of this maneuver */
903 initStringInfo(&str
);
904 outBitmapset(&str
, bms
);