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-2024, 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 /* State flag that determines how nodeToStringInternal() should treat location fields */
29 static bool write_location_fields = false;
30 
31 static void outChar(StringInfo str, char c);
32 static void outDouble(StringInfo str, double d);
33 
34 
35 /*
36  * Macros to simplify output of different kinds of fields. Use these
37  * wherever possible to reduce the chance for silly typos. Note that these
38  * hard-wire conventions about the names of the local variables in an Out
39  * routine.
40  */
41 
42 /* Write the label for the node type */
43 #define WRITE_NODE_TYPE(nodelabel) \
44  appendStringInfoString(str, nodelabel)
45 
46 /* Write an integer field (anything written as ":fldname %d") */
47 #define WRITE_INT_FIELD(fldname) \
48  appendStringInfo(str, " :" CppAsString(fldname) " %d", node->fldname)
49 
50 /* Write an unsigned integer field (anything written as ":fldname %u") */
51 #define WRITE_UINT_FIELD(fldname) \
52  appendStringInfo(str, " :" CppAsString(fldname) " %u", node->fldname)
53 
54 /* Write an unsigned integer field (anything written with UINT64_FORMAT) */
55 #define WRITE_UINT64_FIELD(fldname) \
56  appendStringInfo(str, " :" CppAsString(fldname) " " UINT64_FORMAT, \
57  node->fldname)
58 
59 /* Write an OID field (don't hard-wire assumption that OID is same as uint) */
60 #define WRITE_OID_FIELD(fldname) \
61  appendStringInfo(str, " :" CppAsString(fldname) " %u", node->fldname)
62 
63 /* Write a long-integer field */
64 #define WRITE_LONG_FIELD(fldname) \
65  appendStringInfo(str, " :" CppAsString(fldname) " %ld", node->fldname)
66 
67 /* Write a char field (ie, one ascii character) */
68 #define WRITE_CHAR_FIELD(fldname) \
69  (appendStringInfo(str, " :" CppAsString(fldname) " "), \
70  outChar(str, node->fldname))
71 
72 /* Write an enumerated-type field as an integer code */
73 #define WRITE_ENUM_FIELD(fldname, enumtype) \
74  appendStringInfo(str, " :" CppAsString(fldname) " %d", \
75  (int) node->fldname)
76 
77 /* Write a float field (actually, they're double) */
78 #define WRITE_FLOAT_FIELD(fldname) \
79  (appendStringInfo(str, " :" CppAsString(fldname) " "), \
80  outDouble(str, node->fldname))
81 
82 /* Write a boolean field */
83 #define WRITE_BOOL_FIELD(fldname) \
84  appendStringInfo(str, " :" CppAsString(fldname) " %s", \
85  booltostr(node->fldname))
86 
87 /* Write a character-string (possibly NULL) field */
88 #define WRITE_STRING_FIELD(fldname) \
89  (appendStringInfoString(str, " :" CppAsString(fldname) " "), \
90  outToken(str, node->fldname))
91 
92 /* Write a parse location field (actually same as INT case) */
93 #define WRITE_LOCATION_FIELD(fldname) \
94  appendStringInfo(str, " :" CppAsString(fldname) " %d", write_location_fields ? node->fldname : -1)
95 
96 /* Write a Node field */
97 #define WRITE_NODE_FIELD(fldname) \
98  (appendStringInfoString(str, " :" CppAsString(fldname) " "), \
99  outNode(str, node->fldname))
100 
101 /* Write a bitmapset field */
102 #define WRITE_BITMAPSET_FIELD(fldname) \
103  (appendStringInfoString(str, " :" CppAsString(fldname) " "), \
104  outBitmapset(str, node->fldname))
105 
106 /* Write a variable-length array (not a List) of Node pointers */
107 #define WRITE_NODE_ARRAY(fldname, len) \
108  (appendStringInfoString(str, " :" CppAsString(fldname) " "), \
109  writeNodeArray(str, (const Node * const *) node->fldname, len))
110 
111 /* Write a variable-length array of AttrNumber */
112 #define WRITE_ATTRNUMBER_ARRAY(fldname, len) \
113  (appendStringInfoString(str, " :" CppAsString(fldname) " "), \
114  writeAttrNumberCols(str, node->fldname, len))
115 
116 /* Write a variable-length array of Oid */
117 #define WRITE_OID_ARRAY(fldname, len) \
118  (appendStringInfoString(str, " :" CppAsString(fldname) " "), \
119  writeOidCols(str, node->fldname, len))
120 
121 /* Write a variable-length array of Index */
122 #define WRITE_INDEX_ARRAY(fldname, len) \
123  (appendStringInfoString(str, " :" CppAsString(fldname) " "), \
124  writeIndexCols(str, node->fldname, len))
125 
126 /* Write a variable-length array of int */
127 #define WRITE_INT_ARRAY(fldname, len) \
128  (appendStringInfoString(str, " :" CppAsString(fldname) " "), \
129  writeIntCols(str, node->fldname, len))
130 
131 /* Write a variable-length array of bool */
132 #define WRITE_BOOL_ARRAY(fldname, len) \
133  (appendStringInfoString(str, " :" CppAsString(fldname) " "), \
134  writeBoolCols(str, node->fldname, len))
135 
136 #define booltostr(x) ((x) ? "true" : "false")
137 
138 
139 /*
140  * outToken
141  * Convert an ordinary string (eg, an identifier) into a form that
142  * will be decoded back to a plain token by read.c's functions.
143  *
144  * If a null string pointer is given, it is encoded as '<>'.
145  * An empty string is encoded as '""'. To avoid ambiguity, input
146  * strings beginning with '<' or '"' receive a leading backslash.
147  */
148 void
149 outToken(StringInfo str, const char *s)
150 {
151  if (s == NULL)
152  {
154  return;
155  }
156  if (*s == '\0')
157  {
158  appendStringInfoString(str, "\"\"");
159  return;
160  }
161 
162  /*
163  * Look for characters or patterns that are treated specially by read.c
164  * (either in pg_strtok() or in nodeRead()), and therefore need a
165  * protective backslash.
166  */
167  /* These characters only need to be quoted at the start of the string */
168  if (*s == '<' ||
169  *s == '"' ||
170  isdigit((unsigned char) *s) ||
171  ((*s == '+' || *s == '-') &&
172  (isdigit((unsigned char) s[1]) || s[1] == '.')))
173  appendStringInfoChar(str, '\\');
174  while (*s)
175  {
176  /* These chars must be backslashed anywhere in the string */
177  if (*s == ' ' || *s == '\n' || *s == '\t' ||
178  *s == '(' || *s == ')' || *s == '{' || *s == '}' ||
179  *s == '\\')
180  appendStringInfoChar(str, '\\');
181  appendStringInfoChar(str, *s++);
182  }
183 }
184 
185 /*
186  * Convert one char. Goes through outToken() so that special characters are
187  * escaped.
188  */
189 static void
191 {
192  char in[2];
193 
194  /* Traditionally, we've represented \0 as <>, so keep doing that */
195  if (c == '\0')
196  {
198  return;
199  }
200 
201  in[0] = c;
202  in[1] = '\0';
203 
204  outToken(str, in);
205 }
206 
207 /*
208  * Convert a double value, attempting to ensure the value is preserved exactly.
209  */
210 static void
212 {
214 
217 }
218 
219 /*
220  * common implementation for scalar-array-writing functions
221  *
222  * The data format is either "<>" for a NULL pointer or "(item item item)".
223  * fmtstr must include a leading space, and the rest of it must produce
224  * something that will be seen as a single simple token by pg_strtok().
225  * convfunc can be empty, or the name of a conversion macro or function.
226  */
227 #define WRITE_SCALAR_ARRAY(fnname, datatype, fmtstr, convfunc) \
228 static void \
229 fnname(StringInfo str, const datatype *arr, int len) \
230 { \
231  if (arr != NULL) \
232  { \
233  appendStringInfoChar(str, '('); \
234  for (int i = 0; i < len; i++) \
235  appendStringInfo(str, fmtstr, convfunc(arr[i])); \
236  appendStringInfoChar(str, ')'); \
237  } \
238  else \
239  appendStringInfoString(str, "<>"); \
240 }
241 
242 WRITE_SCALAR_ARRAY(writeAttrNumberCols, AttrNumber, " %d",)
243 WRITE_SCALAR_ARRAY(writeOidCols, Oid, " %u",)
244 WRITE_SCALAR_ARRAY(writeIndexCols, Index, " %u",)
245 WRITE_SCALAR_ARRAY(writeIntCols, int, " %d",)
246 WRITE_SCALAR_ARRAY(writeBoolCols, bool, " %s", booltostr)
247 
248 /*
249  * Print an array (not a List) of Node pointers.
250  *
251  * The decoration is identical to that of scalar arrays, but we can't
252  * quite use appendStringInfo() in the loop.
253  */
254 static void
255 writeNodeArray(StringInfo str, const Node *const *arr, int len)
256 {
257  if (arr != NULL)
258  {
260  for (int i = 0; i < len; i++)
261  {
263  outNode(str, arr[i]);
264  }
266  }
267  else
269 }
270 
271 /*
272  * Print a List.
273  */
274 static void
276 {
277  const ListCell *lc;
278 
280 
281  if (IsA(node, IntList))
283  else if (IsA(node, OidList))
285  else if (IsA(node, XidList))
287 
288  foreach(lc, node)
289  {
290  /*
291  * For the sake of backward compatibility, we emit a slightly
292  * different whitespace format for lists of nodes vs. other types of
293  * lists. XXX: is this necessary?
294  */
295  if (IsA(node, List))
296  {
297  outNode(str, lfirst(lc));
298  if (lnext(node, lc))
300  }
301  else if (IsA(node, IntList))
302  appendStringInfo(str, " %d", lfirst_int(lc));
303  else if (IsA(node, OidList))
304  appendStringInfo(str, " %u", lfirst_oid(lc));
305  else if (IsA(node, XidList))
306  appendStringInfo(str, " %u", lfirst_xid(lc));
307  else
308  elog(ERROR, "unrecognized list node type: %d",
309  (int) node->type);
310  }
311 
313 }
314 
315 /*
316  * outBitmapset -
317  * converts a bitmap set of integers
318  *
319  * Note: the output format is "(b int int ...)", similar to an integer List.
320  *
321  * We export this function for use by extensions that define extensible nodes.
322  * That's somewhat historical, though, because calling outNode() will work.
323  */
324 void
326 {
327  int x;
328 
331  x = -1;
332  while ((x = bms_next_member(bms, x)) >= 0)
333  appendStringInfo(str, " %d", x);
335 }
336 
337 /*
338  * Print the value of a Datum given its type.
339  */
340 void
341 outDatum(StringInfo str, Datum value, int typlen, bool typbyval)
342 {
343  Size length,
344  i;
345  char *s;
346 
347  length = datumGetSize(value, typbyval, typlen);
348 
349  if (typbyval)
350  {
351  s = (char *) (&value);
352  appendStringInfo(str, "%u [ ", (unsigned int) length);
353  for (i = 0; i < (Size) sizeof(Datum); i++)
354  appendStringInfo(str, "%d ", (int) (s[i]));
356  }
357  else
358  {
359  s = (char *) DatumGetPointer(value);
360  if (!PointerIsValid(s))
361  appendStringInfoString(str, "0 [ ]");
362  else
363  {
364  appendStringInfo(str, "%u [ ", (unsigned int) length);
365  for (i = 0; i < length; i++)
366  appendStringInfo(str, "%d ", (int) (s[i]));
368  }
369  }
370 }
371 
372 
373 #include "outfuncs.funcs.c"
374 
375 
376 /*
377  * Support functions for nodes with custom_read_write attribute or
378  * special_read_write attribute
379  */
380 
381 static void
383 {
384  WRITE_NODE_TYPE("CONST");
385 
386  WRITE_OID_FIELD(consttype);
387  WRITE_INT_FIELD(consttypmod);
388  WRITE_OID_FIELD(constcollid);
389  WRITE_INT_FIELD(constlen);
390  WRITE_BOOL_FIELD(constbyval);
391  WRITE_BOOL_FIELD(constisnull);
392  WRITE_LOCATION_FIELD(location);
393 
394  appendStringInfoString(str, " :constvalue ");
395  if (node->constisnull)
397  else
398  outDatum(str, node->constvalue, node->constlen, node->constbyval);
399 }
400 
401 static void
403 {
404  char *opstr = NULL;
405 
406  WRITE_NODE_TYPE("BOOLEXPR");
407 
408  /* do-it-yourself enum representation */
409  switch (node->boolop)
410  {
411  case AND_EXPR:
412  opstr = "and";
413  break;
414  case OR_EXPR:
415  opstr = "or";
416  break;
417  case NOT_EXPR:
418  opstr = "not";
419  break;
420  }
421  appendStringInfoString(str, " :boolop ");
422  outToken(str, opstr);
423 
425  WRITE_LOCATION_FIELD(location);
426 }
427 
428 static void
430 {
431  int i;
432 
433  WRITE_NODE_TYPE("FOREIGNKEYOPTINFO");
434 
435  WRITE_UINT_FIELD(con_relid);
436  WRITE_UINT_FIELD(ref_relid);
437  WRITE_INT_FIELD(nkeys);
438  WRITE_ATTRNUMBER_ARRAY(conkey, node->nkeys);
439  WRITE_ATTRNUMBER_ARRAY(confkey, node->nkeys);
440  WRITE_OID_ARRAY(conpfeqop, node->nkeys);
441  WRITE_INT_FIELD(nmatched_ec);
442  WRITE_INT_FIELD(nconst_ec);
443  WRITE_INT_FIELD(nmatched_rcols);
444  WRITE_INT_FIELD(nmatched_ri);
445  /* for compactness, just print the number of matches per column: */
446  appendStringInfoString(str, " :eclass");
447  for (i = 0; i < node->nkeys; i++)
448  appendStringInfo(str, " %d", (node->eclass[i] != NULL));
449  appendStringInfoString(str, " :rinfos");
450  for (i = 0; i < node->nkeys; i++)
451  appendStringInfo(str, " %d", list_length(node->rinfos[i]));
452 }
453 
454 static void
456 {
457  /*
458  * To simplify reading, we just chase up to the topmost merged EC and
459  * print that, without bothering to show the merge-ees separately.
460  */
461  while (node->ec_merged)
462  node = node->ec_merged;
463 
464  WRITE_NODE_TYPE("EQUIVALENCECLASS");
465 
466  WRITE_NODE_FIELD(ec_opfamilies);
467  WRITE_OID_FIELD(ec_collation);
468  WRITE_NODE_FIELD(ec_members);
469  WRITE_NODE_FIELD(ec_sources);
470  WRITE_NODE_FIELD(ec_derives);
471  WRITE_BITMAPSET_FIELD(ec_relids);
472  WRITE_BOOL_FIELD(ec_has_const);
473  WRITE_BOOL_FIELD(ec_has_volatile);
474  WRITE_BOOL_FIELD(ec_broken);
475  WRITE_UINT_FIELD(ec_sortref);
476  WRITE_UINT_FIELD(ec_min_security);
477  WRITE_UINT_FIELD(ec_max_security);
478 }
479 
480 static void
482 {
483  const ExtensibleNodeMethods *methods;
484 
485  methods = GetExtensibleNodeMethods(node->extnodename, false);
486 
487  WRITE_NODE_TYPE("EXTENSIBLENODE");
488 
489  WRITE_STRING_FIELD(extnodename);
490 
491  /* serialize the private fields */
492  methods->nodeOut(str, node);
493 }
494 
495 static void
497 {
498  WRITE_NODE_TYPE("RANGETBLENTRY");
499 
500  WRITE_NODE_FIELD(alias);
501  WRITE_NODE_FIELD(eref);
502  WRITE_ENUM_FIELD(rtekind, RTEKind);
503 
504  switch (node->rtekind)
505  {
506  case RTE_RELATION:
507  WRITE_OID_FIELD(relid);
508  WRITE_BOOL_FIELD(inh);
509  WRITE_CHAR_FIELD(relkind);
510  WRITE_INT_FIELD(rellockmode);
511  WRITE_UINT_FIELD(perminfoindex);
512  WRITE_NODE_FIELD(tablesample);
513  break;
514  case RTE_SUBQUERY:
515  WRITE_NODE_FIELD(subquery);
516  WRITE_BOOL_FIELD(security_barrier);
517  /* we re-use these RELATION fields, too: */
518  WRITE_OID_FIELD(relid);
519  WRITE_BOOL_FIELD(inh);
520  WRITE_CHAR_FIELD(relkind);
521  WRITE_INT_FIELD(rellockmode);
522  WRITE_UINT_FIELD(perminfoindex);
523  break;
524  case RTE_JOIN:
525  WRITE_ENUM_FIELD(jointype, JoinType);
526  WRITE_INT_FIELD(joinmergedcols);
527  WRITE_NODE_FIELD(joinaliasvars);
528  WRITE_NODE_FIELD(joinleftcols);
529  WRITE_NODE_FIELD(joinrightcols);
530  WRITE_NODE_FIELD(join_using_alias);
531  break;
532  case RTE_FUNCTION:
534  WRITE_BOOL_FIELD(funcordinality);
535  break;
536  case RTE_TABLEFUNC:
537  WRITE_NODE_FIELD(tablefunc);
538  break;
539  case RTE_VALUES:
540  WRITE_NODE_FIELD(values_lists);
541  WRITE_NODE_FIELD(coltypes);
542  WRITE_NODE_FIELD(coltypmods);
543  WRITE_NODE_FIELD(colcollations);
544  break;
545  case RTE_CTE:
546  WRITE_STRING_FIELD(ctename);
547  WRITE_UINT_FIELD(ctelevelsup);
548  WRITE_BOOL_FIELD(self_reference);
549  WRITE_NODE_FIELD(coltypes);
550  WRITE_NODE_FIELD(coltypmods);
551  WRITE_NODE_FIELD(colcollations);
552  break;
553  case RTE_NAMEDTUPLESTORE:
554  WRITE_STRING_FIELD(enrname);
555  WRITE_FLOAT_FIELD(enrtuples);
556  WRITE_NODE_FIELD(coltypes);
557  WRITE_NODE_FIELD(coltypmods);
558  WRITE_NODE_FIELD(colcollations);
559  /* we re-use these RELATION fields, too: */
560  WRITE_OID_FIELD(relid);
561  break;
562  case RTE_RESULT:
563  /* no extra fields */
564  break;
565  case RTE_GROUP:
566  WRITE_NODE_FIELD(groupexprs);
567  break;
568  default:
569  elog(ERROR, "unrecognized RTE kind: %d", (int) node->rtekind);
570  break;
571  }
572 
573  WRITE_BOOL_FIELD(lateral);
574  WRITE_BOOL_FIELD(inFromCl);
575  WRITE_NODE_FIELD(securityQuals);
576 }
577 
578 static void
580 {
581  WRITE_NODE_TYPE("A_EXPR");
582 
583  switch (node->kind)
584  {
585  case AEXPR_OP:
587  break;
588  case AEXPR_OP_ANY:
589  appendStringInfoString(str, " ANY");
591  break;
592  case AEXPR_OP_ALL:
593  appendStringInfoString(str, " ALL");
595  break;
596  case AEXPR_DISTINCT:
597  appendStringInfoString(str, " DISTINCT");
599  break;
600  case AEXPR_NOT_DISTINCT:
601  appendStringInfoString(str, " NOT_DISTINCT");
603  break;
604  case AEXPR_NULLIF:
605  appendStringInfoString(str, " NULLIF");
607  break;
608  case AEXPR_IN:
609  appendStringInfoString(str, " IN");
611  break;
612  case AEXPR_LIKE:
613  appendStringInfoString(str, " LIKE");
615  break;
616  case AEXPR_ILIKE:
617  appendStringInfoString(str, " ILIKE");
619  break;
620  case AEXPR_SIMILAR:
621  appendStringInfoString(str, " SIMILAR");
623  break;
624  case AEXPR_BETWEEN:
625  appendStringInfoString(str, " BETWEEN");
627  break;
628  case AEXPR_NOT_BETWEEN:
629  appendStringInfoString(str, " NOT_BETWEEN");
631  break;
632  case AEXPR_BETWEEN_SYM:
633  appendStringInfoString(str, " BETWEEN_SYM");
635  break;
637  appendStringInfoString(str, " NOT_BETWEEN_SYM");
639  break;
640  default:
641  elog(ERROR, "unrecognized A_Expr_Kind: %d", (int) node->kind);
642  break;
643  }
644 
645  WRITE_NODE_FIELD(lexpr);
646  WRITE_NODE_FIELD(rexpr);
647  WRITE_LOCATION_FIELD(location);
648 }
649 
650 static void
652 {
653  appendStringInfo(str, "%d", node->ival);
654 }
655 
656 static void
658 {
659  /*
660  * We assume the value is a valid numeric literal and so does not need
661  * quoting.
662  */
664 }
665 
666 static void
668 {
669  appendStringInfoString(str, node->boolval ? "true" : "false");
670 }
671 
672 static void
674 {
675  /*
676  * We use outToken to provide escaping of the string's content, but we
677  * don't want it to convert an empty string to '""', because we're putting
678  * double quotes around the string already.
679  */
681  if (node->sval[0] != '\0')
682  outToken(str, node->sval);
684 }
685 
686 static void
688 {
689  /*
690  * The lexer will always produce a string starting with 'b' or 'x'. There
691  * might be characters following that that need escaping, but outToken
692  * won't escape the 'b' or 'x'. This is relied on by nodeTokenType.
693  */
694  Assert(node->bsval[0] == 'b' || node->bsval[0] == 'x');
695  outToken(str, node->bsval);
696 }
697 
698 static void
700 {
701  WRITE_NODE_TYPE("A_CONST");
702 
703  if (node->isnull)
704  appendStringInfoString(str, " NULL");
705  else
706  {
707  appendStringInfoString(str, " :val ");
708  outNode(str, &node->val);
709  }
710  WRITE_LOCATION_FIELD(location);
711 }
712 
713 
714 /*
715  * outNode -
716  * converts a Node into ascii string and append it to 'str'
717  */
718 void
719 outNode(StringInfo str, const void *obj)
720 {
721  /* Guard against stack overflow due to overly complex expressions */
723 
724  if (obj == NULL)
726  else if (IsA(obj, List) || IsA(obj, IntList) || IsA(obj, OidList) ||
727  IsA(obj, XidList))
728  _outList(str, obj);
729  /* nodeRead does not want to see { } around these! */
730  else if (IsA(obj, Integer))
731  _outInteger(str, (Integer *) obj);
732  else if (IsA(obj, Float))
733  _outFloat(str, (Float *) obj);
734  else if (IsA(obj, Boolean))
735  _outBoolean(str, (Boolean *) obj);
736  else if (IsA(obj, String))
737  _outString(str, (String *) obj);
738  else if (IsA(obj, BitString))
739  _outBitString(str, (BitString *) obj);
740  else if (IsA(obj, Bitmapset))
741  outBitmapset(str, (Bitmapset *) obj);
742  else
743  {
745  switch (nodeTag(obj))
746  {
747 #include "outfuncs.switch.c"
748 
749  default:
750 
751  /*
752  * This should be an ERROR, but it's too useful to be able to
753  * dump structures that outNode only understands part of.
754  */
755  elog(WARNING, "could not dump unrecognized node type: %d",
756  (int) nodeTag(obj));
757  break;
758  }
760  }
761 }
762 
763 /*
764  * nodeToString -
765  * returns the ascii representation of the Node as a palloc'd string
766  *
767  * write_loc_fields determines whether location fields are output with their
768  * actual value rather than -1. The actual value can be useful for debugging,
769  * but for most uses, the actual value is not useful, since the original query
770  * string is no longer available.
771  */
772 static char *
773 nodeToStringInternal(const void *obj, bool write_loc_fields)
774 {
776  bool save_write_location_fields;
777 
778  save_write_location_fields = write_location_fields;
779  write_location_fields = write_loc_fields;
780 
781  /* see stringinfo.h for an explanation of this maneuver */
783  outNode(&str, obj);
784 
785  write_location_fields = save_write_location_fields;
786 
787  return str.data;
788 }
789 
790 /*
791  * Externally visible entry points
792  */
793 char *
794 nodeToString(const void *obj)
795 {
796  return nodeToStringInternal(obj, false);
797 }
798 
799 char *
801 {
802  return nodeToStringInternal(obj, true);
803 }
804 
805 
806 /*
807  * bmsToString -
808  * returns the ascii representation of the Bitmapset as a palloc'd string
809  */
810 char *
812 {
814 
815  /* see stringinfo.h for an explanation of this maneuver */
817  outBitmapset(&str, bms);
818  return str.data;
819 }
int16 AttrNumber
Definition: attnum.h:21
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1306
#define Assert(condition)
Definition: c.h:858
#define PointerIsValid(pointer)
Definition: c.h:763
unsigned int Index
Definition: c.h:614
size_t Size
Definition: c.h:605
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
#define elog(elevel,...)
Definition: elog.h:225
const ExtensibleNodeMethods * GetExtensibleNodeMethods(const char *extnodename, bool missing_ok)
Definition: extensible.c:125
const char * str
static struct @157 value
int x
Definition: isn.c:71
int i
Definition: isn.c:73
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
#define nodeTag(nodeptr)
Definition: nodes.h:133
JoinType
Definition: nodes.h:288
static void _outString(StringInfo str, const String *node)
Definition: outfuncs.c:673
#define WRITE_OID_FIELD(fldname)
Definition: outfuncs.c:60
#define WRITE_BITMAPSET_FIELD(fldname)
Definition: outfuncs.c:102
void outDatum(StringInfo str, Datum value, int typlen, bool typbyval)
Definition: outfuncs.c:341
#define booltostr(x)
Definition: outfuncs.c:136
static void outChar(StringInfo str, char c)
Definition: outfuncs.c:190
static void _outExtensibleNode(StringInfo str, const ExtensibleNode *node)
Definition: outfuncs.c:481
static void _outA_Const(StringInfo str, const A_Const *node)
Definition: outfuncs.c:699
static void _outBoolExpr(StringInfo str, const BoolExpr *node)
Definition: outfuncs.c:402
#define WRITE_ENUM_FIELD(fldname, enumtype)
Definition: outfuncs.c:73
static void _outForeignKeyOptInfo(StringInfo str, const ForeignKeyOptInfo *node)
Definition: outfuncs.c:429
static void outDouble(StringInfo str, double d)
Definition: outfuncs.c:211
#define WRITE_ATTRNUMBER_ARRAY(fldname, len)
Definition: outfuncs.c:112
#define WRITE_FLOAT_FIELD(fldname)
Definition: outfuncs.c:78
#define WRITE_NODE_FIELD(fldname)
Definition: outfuncs.c:97
#define WRITE_SCALAR_ARRAY(fnname, datatype, fmtstr, convfunc)
Definition: outfuncs.c:227
static char * nodeToStringInternal(const void *obj, bool write_loc_fields)
Definition: outfuncs.c:773
#define WRITE_NODE_TYPE(nodelabel)
Definition: outfuncs.c:43
static void _outRangeTblEntry(StringInfo str, const RangeTblEntry *node)
Definition: outfuncs.c:496
static void _outConst(StringInfo str, const Const *node)
Definition: outfuncs.c:382
#define WRITE_BOOL_FIELD(fldname)
Definition: outfuncs.c:83
void outToken(StringInfo str, const char *s)
Definition: outfuncs.c:149
static void _outInteger(StringInfo str, const Integer *node)
Definition: outfuncs.c:651
#define WRITE_UINT_FIELD(fldname)
Definition: outfuncs.c:51
#define WRITE_OID_ARRAY(fldname, len)
Definition: outfuncs.c:117
static void _outA_Expr(StringInfo str, const A_Expr *node)
Definition: outfuncs.c:579
static void _outList(StringInfo str, const List *node)
Definition: outfuncs.c:275
#define WRITE_CHAR_FIELD(fldname)
Definition: outfuncs.c:68
static bool write_location_fields
Definition: outfuncs.c:29
void outNode(StringInfo str, const void *obj)
Definition: outfuncs.c:719
#define WRITE_LOCATION_FIELD(fldname)
Definition: outfuncs.c:93
static void _outFloat(StringInfo str, const Float *node)
Definition: outfuncs.c:657
char * bmsToString(const Bitmapset *bms)
Definition: outfuncs.c:811
#define WRITE_STRING_FIELD(fldname)
Definition: outfuncs.c:88
#define WRITE_INT_FIELD(fldname)
Definition: outfuncs.c:47
static void _outBitString(StringInfo str, const BitString *node)
Definition: outfuncs.c:687
static void _outBoolean(StringInfo str, const Boolean *node)
Definition: outfuncs.c:667
static void writeNodeArray(StringInfo str, const Node *const *arr, int len)
Definition: outfuncs.c:255
char * nodeToString(const void *obj)
Definition: outfuncs.c:794
static void _outEquivalenceClass(StringInfo str, const EquivalenceClass *node)
Definition: outfuncs.c:455
void outBitmapset(StringInfo str, const Bitmapset *bms)
Definition: outfuncs.c:325
char * nodeToStringWithLocations(const void *obj)
Definition: outfuncs.c:800
@ AEXPR_BETWEEN
Definition: parsenodes.h:325
@ AEXPR_NULLIF
Definition: parsenodes.h:320
@ AEXPR_NOT_DISTINCT
Definition: parsenodes.h:319
@ AEXPR_BETWEEN_SYM
Definition: parsenodes.h:327
@ AEXPR_NOT_BETWEEN_SYM
Definition: parsenodes.h:328
@ AEXPR_ILIKE
Definition: parsenodes.h:323
@ AEXPR_IN
Definition: parsenodes.h:321
@ AEXPR_NOT_BETWEEN
Definition: parsenodes.h:326
@ AEXPR_DISTINCT
Definition: parsenodes.h:318
@ AEXPR_SIMILAR
Definition: parsenodes.h:324
@ AEXPR_LIKE
Definition: parsenodes.h:322
@ AEXPR_OP
Definition: parsenodes.h:315
@ AEXPR_OP_ANY
Definition: parsenodes.h:316
@ AEXPR_OP_ALL
Definition: parsenodes.h:317
RTEKind
Definition: parsenodes.h:1016
@ RTE_JOIN
Definition: parsenodes.h:1019
@ RTE_CTE
Definition: parsenodes.h:1023
@ RTE_NAMEDTUPLESTORE
Definition: parsenodes.h:1024
@ RTE_VALUES
Definition: parsenodes.h:1022
@ RTE_SUBQUERY
Definition: parsenodes.h:1018
@ RTE_RESULT
Definition: parsenodes.h:1025
@ RTE_FUNCTION
Definition: parsenodes.h:1020
@ RTE_TABLEFUNC
Definition: parsenodes.h:1021
@ RTE_GROUP
Definition: parsenodes.h:1028
@ RTE_RELATION
Definition: parsenodes.h:1017
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:3564
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:931
@ OR_EXPR
Definition: primnodes.h:931
@ NOT_EXPR
Definition: primnodes.h:931
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:365
union ValUnion val
Definition: parsenodes.h:364
A_Expr_Kind kind
Definition: parsenodes.h:336
char * bsval
Definition: value.h:76
BoolExprType boolop
Definition: primnodes.h:939
Definition: value.h:56
bool boolval
Definition: value.h:60
struct EquivalenceClass * ec_merged
Definition: pathnodes.h:1402
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:1256
List * rinfos[INDEX_MAX_KEYS]
Definition: pathnodes.h:1260
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:1047
Definition: value.h:64
char * sval
Definition: value.h:68
const char * name