PostgreSQL Source Code  git master
outfuncs.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * outfuncs.c
4  * Output functions for Postgres tree nodes.
5  *
6  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/nodes/outfuncs.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16 
17 #include <ctype.h>
18 
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"
27 
28 static void outChar(StringInfo str, char c);
29 static void outDouble(StringInfo str, double d);
30 
31 
32 /*
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
36  * routine.
37  */
38 
39 /* Write the label for the node type */
40 #define WRITE_NODE_TYPE(nodelabel) \
41  appendStringInfoString(str, nodelabel)
42 
43 /* Write an integer field (anything written as ":fldname %d") */
44 #define WRITE_INT_FIELD(fldname) \
45  appendStringInfo(str, " :" CppAsString(fldname) " %d", node->fldname)
46 
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)
50 
51 /* Write an unsigned integer field (anything written with UINT64_FORMAT) */
52 #define WRITE_UINT64_FIELD(fldname) \
53  appendStringInfo(str, " :" CppAsString(fldname) " " UINT64_FORMAT, \
54  node->fldname)
55 
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)
59 
60 /* Write a long-integer field */
61 #define WRITE_LONG_FIELD(fldname) \
62  appendStringInfo(str, " :" CppAsString(fldname) " %ld", node->fldname)
63 
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))
68 
69 /* Write an enumerated-type field as an integer code */
70 #define WRITE_ENUM_FIELD(fldname, enumtype) \
71  appendStringInfo(str, " :" CppAsString(fldname) " %d", \
72  (int) node->fldname)
73 
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))
78 
79 /* Write a boolean field */
80 #define WRITE_BOOL_FIELD(fldname) \
81  appendStringInfo(str, " :" CppAsString(fldname) " %s", \
82  booltostr(node->fldname))
83 
84 /* Write a character-string (possibly NULL) field */
85 #define WRITE_STRING_FIELD(fldname) \
86  (appendStringInfoString(str, " :" CppAsString(fldname) " "), \
87  outToken(str, node->fldname))
88 
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)
92 
93 /* Write a Node field */
94 #define WRITE_NODE_FIELD(fldname) \
95  (appendStringInfoString(str, " :" CppAsString(fldname) " "), \
96  outNode(str, node->fldname))
97 
98 /* Write a bitmapset field */
99 #define WRITE_BITMAPSET_FIELD(fldname) \
100  (appendStringInfoString(str, " :" CppAsString(fldname) " "), \
101  outBitmapset(str, node->fldname))
102 
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))
107 
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))
112 
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))
117 
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))
122 
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))
127 
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))
132 
133 #define booltostr(x) ((x) ? "true" : "false")
134 
135 
136 /*
137  * outToken
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.
140  *
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.
144  */
145 void
146 outToken(StringInfo str, const char *s)
147 {
148  if (s == NULL)
149  {
151  return;
152  }
153  if (*s == '\0')
154  {
155  appendStringInfoString(str, "\"\"");
156  return;
157  }
158 
159  /*
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.
163  */
164  /* These characters only need to be quoted at the start of the string */
165  if (*s == '<' ||
166  *s == '"' ||
167  isdigit((unsigned char) *s) ||
168  ((*s == '+' || *s == '-') &&
169  (isdigit((unsigned char) s[1]) || s[1] == '.')))
170  appendStringInfoChar(str, '\\');
171  while (*s)
172  {
173  /* These chars must be backslashed anywhere in the string */
174  if (*s == ' ' || *s == '\n' || *s == '\t' ||
175  *s == '(' || *s == ')' || *s == '{' || *s == '}' ||
176  *s == '\\')
177  appendStringInfoChar(str, '\\');
178  appendStringInfoChar(str, *s++);
179  }
180 }
181 
182 /*
183  * Convert one char. Goes through outToken() so that special characters are
184  * escaped.
185  */
186 static void
188 {
189  char in[2];
190 
191  /* Traditionally, we've represented \0 as <>, so keep doing that */
192  if (c == '\0')
193  {
195  return;
196  }
197 
198  in[0] = c;
199  in[1] = '\0';
200 
201  outToken(str, in);
202 }
203 
204 /*
205  * Convert a double value, attempting to ensure the value is preserved exactly.
206  */
207 static void
209 {
211 
214 }
215 
216 /*
217  * common implementation for scalar-array-writing functions
218  *
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.
223  */
224 #define WRITE_SCALAR_ARRAY(fnname, datatype, fmtstr, convfunc) \
225 static void \
226 fnname(StringInfo str, const datatype *arr, int len) \
227 { \
228  if (arr != NULL) \
229  { \
230  appendStringInfoChar(str, '('); \
231  for (int i = 0; i < len; i++) \
232  appendStringInfo(str, fmtstr, convfunc(arr[i])); \
233  appendStringInfoChar(str, ')'); \
234  } \
235  else \
236  appendStringInfoString(str, "<>"); \
237 }
238 
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)
244 
245 /*
246  * Print an array (not a List) of Node pointers.
247  *
248  * The decoration is identical to that of scalar arrays, but we can't
249  * quite use appendStringInfo() in the loop.
250  */
251 static void
252 writeNodeArray(StringInfo str, const Node *const *arr, int len)
253 {
254  if (arr != NULL)
255  {
257  for (int i = 0; i < len; i++)
258  {
260  outNode(str, arr[i]);
261  }
263  }
264  else
266 }
267 
268 /*
269  * Print a List.
270  */
271 static void
273 {
274  const ListCell *lc;
275 
277 
278  if (IsA(node, IntList))
280  else if (IsA(node, OidList))
282  else if (IsA(node, XidList))
284 
285  foreach(lc, node)
286  {
287  /*
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?
291  */
292  if (IsA(node, List))
293  {
294  outNode(str, lfirst(lc));
295  if (lnext(node, lc))
297  }
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));
304  else
305  elog(ERROR, "unrecognized list node type: %d",
306  (int) node->type);
307  }
308 
310 }
311 
312 /*
313  * outBitmapset -
314  * converts a bitmap set of integers
315  *
316  * Note: the output format is "(b int int ...)", similar to an integer List.
317  *
318  * We export this function for use by extensions that define extensible nodes.
319  * That's somewhat historical, though, because calling outNode() will work.
320  */
321 void
323 {
324  int x;
325 
328  x = -1;
329  while ((x = bms_next_member(bms, x)) >= 0)
330  appendStringInfo(str, " %d", x);
332 }
333 
334 /*
335  * Print the value of a Datum given its type.
336  */
337 void
338 outDatum(StringInfo str, Datum value, int typlen, bool typbyval)
339 {
340  Size length,
341  i;
342  char *s;
343 
344  length = datumGetSize(value, typbyval, typlen);
345 
346  if (typbyval)
347  {
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]));
353  }
354  else
355  {
356  s = (char *) DatumGetPointer(value);
357  if (!PointerIsValid(s))
358  appendStringInfoString(str, "0 [ ]");
359  else
360  {
361  appendStringInfo(str, "%u [ ", (unsigned int) length);
362  for (i = 0; i < length; i++)
363  appendStringInfo(str, "%d ", (int) (s[i]));
365  }
366  }
367 }
368 
369 
370 #include "outfuncs.funcs.c"
371 
372 
373 /*
374  * Support functions for nodes with custom_read_write attribute or
375  * special_read_write attribute
376  */
377 
378 static void
380 {
381  WRITE_NODE_TYPE("CONST");
382 
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);
390 
391  appendStringInfoString(str, " :constvalue ");
392  if (node->constisnull)
394  else
395  outDatum(str, node->constvalue, node->constlen, node->constbyval);
396 }
397 
398 static void
400 {
401  char *opstr = NULL;
402 
403  WRITE_NODE_TYPE("BOOLEXPR");
404 
405  /* do-it-yourself enum representation */
406  switch (node->boolop)
407  {
408  case AND_EXPR:
409  opstr = "and";
410  break;
411  case OR_EXPR:
412  opstr = "or";
413  break;
414  case NOT_EXPR:
415  opstr = "not";
416  break;
417  }
418  appendStringInfoString(str, " :boolop ");
419  outToken(str, opstr);
420 
422  WRITE_LOCATION_FIELD(location);
423 }
424 
425 static void
427 {
428  int i;
429 
430  WRITE_NODE_TYPE("FOREIGNKEYOPTINFO");
431 
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]));
449 }
450 
451 static void
453 {
454  /*
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.
457  */
458  while (node->ec_merged)
459  node = node->ec_merged;
460 
461  WRITE_NODE_TYPE("EQUIVALENCECLASS");
462 
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);
475 }
476 
477 static void
479 {
480  const ExtensibleNodeMethods *methods;
481 
482  methods = GetExtensibleNodeMethods(node->extnodename, false);
483 
484  WRITE_NODE_TYPE("EXTENSIBLENODE");
485 
486  WRITE_STRING_FIELD(extnodename);
487 
488  /* serialize the private fields */
489  methods->nodeOut(str, node);
490 }
491 
492 static void
494 {
495  WRITE_NODE_TYPE("RANGETBLENTRY");
496 
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);
501 
502  switch (node->rtekind)
503  {
504  case RTE_RELATION:
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);
510  break;
511  case RTE_SUBQUERY:
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);
519  break;
520  case RTE_JOIN:
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);
527  break;
528  case RTE_FUNCTION:
530  WRITE_BOOL_FIELD(funcordinality);
531  break;
532  case RTE_TABLEFUNC:
533  WRITE_NODE_FIELD(tablefunc);
534  break;
535  case RTE_VALUES:
536  WRITE_NODE_FIELD(values_lists);
537  WRITE_NODE_FIELD(coltypes);
538  WRITE_NODE_FIELD(coltypmods);
539  WRITE_NODE_FIELD(colcollations);
540  break;
541  case RTE_CTE:
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);
548  break;
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);
557  break;
558  case RTE_RESULT:
559  /* no extra fields */
560  break;
561  default:
562  elog(ERROR, "unrecognized RTE kind: %d", (int) node->rtekind);
563  break;
564  }
565 
566  WRITE_BOOL_FIELD(lateral);
567  WRITE_BOOL_FIELD(inh);
568  WRITE_BOOL_FIELD(inFromCl);
569  WRITE_NODE_FIELD(securityQuals);
570 }
571 
572 static void
574 {
575  WRITE_NODE_TYPE("A_EXPR");
576 
577  switch (node->kind)
578  {
579  case AEXPR_OP:
581  break;
582  case AEXPR_OP_ANY:
583  appendStringInfoString(str, " ANY");
585  break;
586  case AEXPR_OP_ALL:
587  appendStringInfoString(str, " ALL");
589  break;
590  case AEXPR_DISTINCT:
591  appendStringInfoString(str, " DISTINCT");
593  break;
594  case AEXPR_NOT_DISTINCT:
595  appendStringInfoString(str, " NOT_DISTINCT");
597  break;
598  case AEXPR_NULLIF:
599  appendStringInfoString(str, " NULLIF");
601  break;
602  case AEXPR_IN:
603  appendStringInfoString(str, " IN");
605  break;
606  case AEXPR_LIKE:
607  appendStringInfoString(str, " LIKE");
609  break;
610  case AEXPR_ILIKE:
611  appendStringInfoString(str, " ILIKE");
613  break;
614  case AEXPR_SIMILAR:
615  appendStringInfoString(str, " SIMILAR");
617  break;
618  case AEXPR_BETWEEN:
619  appendStringInfoString(str, " BETWEEN");
621  break;
622  case AEXPR_NOT_BETWEEN:
623  appendStringInfoString(str, " NOT_BETWEEN");
625  break;
626  case AEXPR_BETWEEN_SYM:
627  appendStringInfoString(str, " BETWEEN_SYM");
629  break;
631  appendStringInfoString(str, " NOT_BETWEEN_SYM");
633  break;
634  default:
635  elog(ERROR, "unrecognized A_Expr_Kind: %d", (int) node->kind);
636  break;
637  }
638 
639  WRITE_NODE_FIELD(lexpr);
640  WRITE_NODE_FIELD(rexpr);
641  WRITE_LOCATION_FIELD(location);
642 }
643 
644 static void
646 {
647  appendStringInfo(str, "%d", node->ival);
648 }
649 
650 static void
652 {
653  /*
654  * We assume the value is a valid numeric literal and so does not need
655  * quoting.
656  */
658 }
659 
660 static void
662 {
663  appendStringInfoString(str, node->boolval ? "true" : "false");
664 }
665 
666 static void
668 {
669  /*
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.
673  */
675  if (node->sval[0] != '\0')
676  outToken(str, node->sval);
678 }
679 
680 static void
682 {
683  /* internal representation already has leading 'b' */
685 }
686 
687 static void
689 {
690  WRITE_NODE_TYPE("A_CONST");
691 
692  if (node->isnull)
693  appendStringInfoString(str, " NULL");
694  else
695  {
696  appendStringInfoString(str, " :val ");
697  outNode(str, &node->val);
698  }
699  WRITE_LOCATION_FIELD(location);
700 }
701 
702 static void
704 {
705  WRITE_NODE_TYPE("CONSTRAINT");
706 
707  WRITE_STRING_FIELD(conname);
708  WRITE_BOOL_FIELD(deferrable);
709  WRITE_BOOL_FIELD(initdeferred);
710  WRITE_LOCATION_FIELD(location);
711 
712  appendStringInfoString(str, " :contype ");
713  switch (node->contype)
714  {
715  case CONSTR_NULL:
716  appendStringInfoString(str, "NULL");
717  break;
718 
719  case CONSTR_NOTNULL:
720  appendStringInfoString(str, "NOT_NULL");
721  WRITE_NODE_FIELD(keys);
722  WRITE_INT_FIELD(inhcount);
723  WRITE_BOOL_FIELD(is_no_inherit);
724  WRITE_BOOL_FIELD(skip_validation);
725  WRITE_BOOL_FIELD(initially_valid);
726  break;
727 
728  case CONSTR_DEFAULT:
729  appendStringInfoString(str, "DEFAULT");
730  WRITE_NODE_FIELD(raw_expr);
731  WRITE_STRING_FIELD(cooked_expr);
732  break;
733 
734  case CONSTR_IDENTITY:
735  appendStringInfoString(str, "IDENTITY");
737  WRITE_CHAR_FIELD(generated_when);
738  break;
739 
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);
745  break;
746 
747  case CONSTR_CHECK:
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);
754  break;
755 
756  case CONSTR_PRIMARY:
757  appendStringInfoString(str, "PRIMARY_KEY");
758  WRITE_NODE_FIELD(keys);
759  WRITE_NODE_FIELD(including);
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 */
765  break;
766 
767  case CONSTR_UNIQUE:
768  appendStringInfoString(str, "UNIQUE");
769  WRITE_BOOL_FIELD(nulls_not_distinct);
770  WRITE_NODE_FIELD(keys);
771  WRITE_NODE_FIELD(including);
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 */
777  break;
778 
779  case CONSTR_EXCLUSION:
780  appendStringInfoString(str, "EXCLUSION");
781  WRITE_NODE_FIELD(exclusions);
782  WRITE_NODE_FIELD(including);
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);
789  break;
790 
791  case CONSTR_FOREIGN:
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);
804  break;
805 
807  appendStringInfoString(str, "ATTR_DEFERRABLE");
808  break;
809 
811  appendStringInfoString(str, "ATTR_NOT_DEFERRABLE");
812  break;
813 
815  appendStringInfoString(str, "ATTR_DEFERRED");
816  break;
817 
819  appendStringInfoString(str, "ATTR_IMMEDIATE");
820  break;
821 
822  default:
823  elog(ERROR, "unrecognized ConstrType: %d", (int) node->contype);
824  break;
825  }
826 }
827 
828 
829 /*
830  * outNode -
831  * converts a Node into ascii string and append it to 'str'
832  */
833 void
834 outNode(StringInfo str, const void *obj)
835 {
836  /* Guard against stack overflow due to overly complex expressions */
838 
839  if (obj == NULL)
841  else if (IsA(obj, List) || IsA(obj, IntList) || IsA(obj, OidList) ||
842  IsA(obj, XidList))
843  _outList(str, obj);
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);
857  else
858  {
860  switch (nodeTag(obj))
861  {
862 #include "outfuncs.switch.c"
863 
864  default:
865 
866  /*
867  * This should be an ERROR, but it's too useful to be able to
868  * dump structures that outNode only understands part of.
869  */
870  elog(WARNING, "could not dump unrecognized node type: %d",
871  (int) nodeTag(obj));
872  break;
873  }
875  }
876 }
877 
878 /*
879  * nodeToString -
880  * returns the ascii representation of the Node as a palloc'd string
881  */
882 char *
883 nodeToString(const void *obj)
884 {
886 
887  /* see stringinfo.h for an explanation of this maneuver */
889  outNode(&str, obj);
890  return str.data;
891 }
892 
893 /*
894  * bmsToString -
895  * returns the ascii representation of the Bitmapset as a palloc'd string
896  */
897 char *
899 {
901 
902  /* see stringinfo.h for an explanation of this maneuver */
904  outBitmapset(&str, bms);
905  return str.data;
906 }
int16 AttrNumber
Definition: attnum.h:21
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1106
#define PointerIsValid(pointer)
Definition: c.h:752
unsigned int Index
Definition: c.h:603
size_t Size
Definition: c.h:594
int double_to_shortest_decimal_buf(double f, char *result)
Definition: d2s.c:1053
Size datumGetSize(Datum value, bool typByVal, int typLen)
Definition: datum.c:65
#define WARNING
Definition: elog.h:36
#define ERROR
Definition: elog.h:39
const ExtensibleNodeMethods * GetExtensibleNodeMethods(const char *extnodename, bool missing_ok)
Definition: extensible.c:125
static struct @148 value
int x
Definition: isn.c:71
int i
Definition: isn.c:73
#define IsA(nodeptr, _type_)
Definition: nodes.h:179
#define nodeTag(nodeptr)
Definition: nodes.h:133
JoinType
Definition: nodes.h:299
static void _outString(StringInfo str, const String *node)
Definition: outfuncs.c:667
#define WRITE_OID_FIELD(fldname)
Definition: outfuncs.c:57
#define WRITE_BITMAPSET_FIELD(fldname)
Definition: outfuncs.c:99
void outDatum(StringInfo str, Datum value, int typlen, bool typbyval)
Definition: outfuncs.c:338
#define booltostr(x)
Definition: outfuncs.c:133
static void outChar(StringInfo str, char c)
Definition: outfuncs.c:187
static void _outExtensibleNode(StringInfo str, const ExtensibleNode *node)
Definition: outfuncs.c:478
static void _outA_Const(StringInfo str, const A_Const *node)
Definition: outfuncs.c:688
static void _outBoolExpr(StringInfo str, const BoolExpr *node)
Definition: outfuncs.c:399
#define WRITE_ENUM_FIELD(fldname, enumtype)
Definition: outfuncs.c:70
static void _outForeignKeyOptInfo(StringInfo str, const ForeignKeyOptInfo *node)
Definition: outfuncs.c:426
static void outDouble(StringInfo str, double d)
Definition: outfuncs.c:208
#define WRITE_ATTRNUMBER_ARRAY(fldname, len)
Definition: outfuncs.c:109
#define WRITE_FLOAT_FIELD(fldname)
Definition: outfuncs.c:75
#define WRITE_NODE_FIELD(fldname)
Definition: outfuncs.c:94
#define WRITE_SCALAR_ARRAY(fnname, datatype, fmtstr, convfunc)
Definition: outfuncs.c:224
#define WRITE_NODE_TYPE(nodelabel)
Definition: outfuncs.c:40
static void _outRangeTblEntry(StringInfo str, const RangeTblEntry *node)
Definition: outfuncs.c:493
static void _outConst(StringInfo str, const Const *node)
Definition: outfuncs.c:379
#define WRITE_BOOL_FIELD(fldname)
Definition: outfuncs.c:80
void outToken(StringInfo str, const char *s)
Definition: outfuncs.c:146
static void _outInteger(StringInfo str, const Integer *node)
Definition: outfuncs.c:645
#define WRITE_UINT_FIELD(fldname)
Definition: outfuncs.c:48
#define WRITE_OID_ARRAY(fldname, len)
Definition: outfuncs.c:114
static void _outA_Expr(StringInfo str, const A_Expr *node)
Definition: outfuncs.c:573
static void _outList(StringInfo str, const List *node)
Definition: outfuncs.c:272
static void _outConstraint(StringInfo str, const Constraint *node)
Definition: outfuncs.c:703
#define WRITE_CHAR_FIELD(fldname)
Definition: outfuncs.c:65
void outNode(StringInfo str, const void *obj)
Definition: outfuncs.c:834
#define WRITE_LOCATION_FIELD(fldname)
Definition: outfuncs.c:90
static void _outFloat(StringInfo str, const Float *node)
Definition: outfuncs.c:651
char * bmsToString(const Bitmapset *bms)
Definition: outfuncs.c:898
#define WRITE_STRING_FIELD(fldname)
Definition: outfuncs.c:85
#define WRITE_INT_FIELD(fldname)
Definition: outfuncs.c:44
static void _outBitString(StringInfo str, const BitString *node)
Definition: outfuncs.c:681
static void _outBoolean(StringInfo str, const Boolean *node)
Definition: outfuncs.c:661
static void writeNodeArray(StringInfo str, const Node *const *arr, int len)
Definition: outfuncs.c:252
char * nodeToString(const void *obj)
Definition: outfuncs.c:883
static void _outEquivalenceClass(StringInfo str, const EquivalenceClass *node)
Definition: outfuncs.c:452
void outBitmapset(StringInfo str, const Bitmapset *bms)
Definition: outfuncs.c:322
@ AEXPR_BETWEEN
Definition: parsenodes.h:313
@ AEXPR_NULLIF
Definition: parsenodes.h:308
@ AEXPR_NOT_DISTINCT
Definition: parsenodes.h:307
@ AEXPR_BETWEEN_SYM
Definition: parsenodes.h:315
@ AEXPR_NOT_BETWEEN_SYM
Definition: parsenodes.h:316
@ AEXPR_ILIKE
Definition: parsenodes.h:311
@ AEXPR_IN
Definition: parsenodes.h:309
@ AEXPR_NOT_BETWEEN
Definition: parsenodes.h:314
@ AEXPR_DISTINCT
Definition: parsenodes.h:306
@ AEXPR_SIMILAR
Definition: parsenodes.h:312
@ AEXPR_LIKE
Definition: parsenodes.h:310
@ AEXPR_OP
Definition: parsenodes.h:303
@ AEXPR_OP_ANY
Definition: parsenodes.h:304
@ AEXPR_OP_ALL
Definition: parsenodes.h:305
RTEKind
Definition: parsenodes.h:1005
@ RTE_JOIN
Definition: parsenodes.h:1008
@ RTE_CTE
Definition: parsenodes.h:1012
@ RTE_NAMEDTUPLESTORE
Definition: parsenodes.h:1013
@ RTE_VALUES
Definition: parsenodes.h:1011
@ RTE_SUBQUERY
Definition: parsenodes.h:1007
@ RTE_RESULT
Definition: parsenodes.h:1014
@ RTE_FUNCTION
Definition: parsenodes.h:1009
@ RTE_TABLEFUNC
Definition: parsenodes.h:1010
@ RTE_RELATION
Definition: parsenodes.h:1006
@ CONSTR_FOREIGN
Definition: parsenodes.h:2547
@ CONSTR_ATTR_DEFERRED
Definition: parsenodes.h:2550
@ CONSTR_IDENTITY
Definition: parsenodes.h:2541
@ CONSTR_UNIQUE
Definition: parsenodes.h:2545
@ CONSTR_ATTR_NOT_DEFERRABLE
Definition: parsenodes.h:2549
@ CONSTR_DEFAULT
Definition: parsenodes.h:2540
@ CONSTR_NOTNULL
Definition: parsenodes.h:2539
@ CONSTR_ATTR_IMMEDIATE
Definition: parsenodes.h:2551
@ CONSTR_CHECK
Definition: parsenodes.h:2543
@ CONSTR_NULL
Definition: parsenodes.h:2537
@ CONSTR_GENERATED
Definition: parsenodes.h:2542
@ CONSTR_EXCLUSION
Definition: parsenodes.h:2546
@ CONSTR_ATTR_DEFERRABLE
Definition: parsenodes.h:2548
@ CONSTR_PRIMARY
Definition: parsenodes.h:2544
const void size_t len
#define lfirst(lc)
Definition: pg_list.h:172
static int list_length(const List *l)
Definition: pg_list.h:152
#define lfirst_int(lc)
Definition: pg_list.h:173
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:343
#define lfirst_oid(lc)
Definition: pg_list.h:174
#define lfirst_xid(lc)
Definition: pg_list.h:175
static char * buf
Definition: pg_test_fsync.c:73
void check_stack_depth(void)
Definition: postgres.c:3520
uintptr_t Datum
Definition: postgres.h:64
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
unsigned int Oid
Definition: postgres_ext.h:31
char * c
@ AND_EXPR
Definition: primnodes.h:866
@ OR_EXPR
Definition: primnodes.h:866
@ NOT_EXPR
Definition: primnodes.h:866
static const struct fns functions
Definition: regcomp.c:356
#define DOUBLE_SHORTEST_DECIMAL_LEN
Definition: shortest_dec.h:44
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:97
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:182
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:194
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
bool isnull
Definition: parsenodes.h:353
union ValUnion val
Definition: parsenodes.h:352
A_Expr_Kind kind
Definition: parsenodes.h:324
char * bsval
Definition: value.h:76
BoolExprType boolop
Definition: primnodes.h:874
Definition: value.h:56
bool boolval
Definition: value.h:60
ConstrType contype
Definition: parsenodes.h:2571
struct EquivalenceClass * ec_merged
Definition: pathnodes.h:1381
void(* nodeOut)(struct StringInfoData *str, const struct ExtensibleNode *node)
Definition: extensible.h:70
const char * extnodename
Definition: extensible.h:37
Definition: value.h:48
char * fval
Definition: value.h:52
struct EquivalenceClass * eclass[INDEX_MAX_KEYS]
Definition: pathnodes.h:1235
List * rinfos[INDEX_MAX_KEYS]
Definition: pathnodes.h:1239
Definition: value.h:29
int ival
Definition: value.h:33
Definition: pg_list.h:54
NodeTag type
Definition: pg_list.h:55
Definition: nodes.h:129
RTEKind rtekind
Definition: parsenodes.h:1025
Definition: value.h:64
char * sval
Definition: value.h:68
const char * name