LCOV - code coverage report
Current view: top level - src/backend/nodes - outfuncs.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 383 457 83.8 %
Date: 2023-11-29 04:11:06 Functions: 23 29 79.3 %
Legend: Lines: hit not hit

          Line data    Source code
       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    36573844 : outToken(StringInfo str, const char *s)
     147             : {
     148    36573844 :     if (s == NULL)
     149             :     {
     150     6064680 :         appendStringInfoString(str, "<>");
     151     6064680 :         return;
     152             :     }
     153    30509164 :     if (*s == '\0')
     154             :     {
     155         156 :         appendStringInfoString(str, "\"\"");
     156         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    30509008 :     if (*s == '<' ||
     166    30438548 :         *s == '"' ||
     167    30434018 :         isdigit((unsigned char) *s) ||
     168    30303944 :         ((*s == '+' || *s == '-') &&
     169       25350 :          (isdigit((unsigned char) s[1]) || s[1] == '.')))
     170      208522 :         appendStringInfoChar(str, '\\');
     171   273550552 :     while (*s)
     172             :     {
     173             :         /* These chars must be backslashed anywhere in the string */
     174   243041544 :         if (*s == ' ' || *s == '\n' || *s == '\t' ||
     175   241926766 :             *s == '(' || *s == ')' || *s == '{' || *s == '}' ||
     176   241729368 :             *s == '\\')
     177     1321788 :             appendStringInfoChar(str, '\\');
     178   243041544 :         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
     187     2086790 : outChar(StringInfo str, char c)
     188             : {
     189             :     char        in[2];
     190             : 
     191             :     /* Traditionally, we've represented \0 as <>, so keep doing that */
     192     2086790 :     if (c == '\0')
     193             :     {
     194      450838 :         appendStringInfoString(str, "<>");
     195      450838 :         return;
     196             :     }
     197             : 
     198     1635952 :     in[0] = c;
     199     1635952 :     in[1] = '\0';
     200             : 
     201     1635952 :     outToken(str, in);
     202             : }
     203             : 
     204             : /*
     205             :  * Convert a double value, attempting to ensure the value is preserved exactly.
     206             :  */
     207             : static void
     208     2907912 : outDouble(StringInfo str, double d)
     209             : {
     210             :     char        buf[DOUBLE_SHORTEST_DECIMAL_LEN];
     211             : 
     212     2907912 :     double_to_shortest_decimal_buf(d, buf);
     213     2907912 :     appendStringInfoString(str, buf);
     214     2907912 : }
     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      363254 : WRITE_SCALAR_ARRAY(writeAttrNumberCols, AttrNumber, " %d",)
     240      456806 : WRITE_SCALAR_ARRAY(writeOidCols, Oid, " %u",)
     241           0 : WRITE_SCALAR_ARRAY(writeIndexCols, Index, " %u",)
     242       20360 : WRITE_SCALAR_ARRAY(writeIntCols, int, " %d",)
     243      148000 : 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           0 : writeNodeArray(StringInfo str, const Node *const *arr, int len)
     253             : {
     254           0 :     if (arr != NULL)
     255             :     {
     256           0 :         appendStringInfoChar(str, '(');
     257           0 :         for (int i = 0; i < len; i++)
     258             :         {
     259           0 :             appendStringInfoChar(str, ' ');
     260           0 :             outNode(str, arr[i]);
     261             :         }
     262           0 :         appendStringInfoChar(str, ')');
     263             :     }
     264             :     else
     265           0 :         appendStringInfoString(str, "<>");
     266           0 : }
     267             : 
     268             : /*
     269             :  * Print a List.
     270             :  */
     271             : static void
     272    14476562 : _outList(StringInfo str, const List *node)
     273             : {
     274             :     const ListCell *lc;
     275             : 
     276    14476562 :     appendStringInfoChar(str, '(');
     277             : 
     278    14476562 :     if (IsA(node, IntList))
     279      386826 :         appendStringInfoChar(str, 'i');
     280    14089736 :     else if (IsA(node, OidList))
     281      564932 :         appendStringInfoChar(str, 'o');
     282    13524804 :     else if (IsA(node, XidList))
     283           0 :         appendStringInfoChar(str, 'x');
     284             : 
     285    61757226 :     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    47280664 :         if (IsA(node, List))
     293             :         {
     294    42668272 :             outNode(str, lfirst(lc));
     295    42668272 :             if (lnext(node, lc))
     296    29143468 :                 appendStringInfoChar(str, ' ');
     297             :         }
     298     4612392 :         else if (IsA(node, IntList))
     299     3518642 :             appendStringInfo(str, " %d", lfirst_int(lc));
     300     1093750 :         else if (IsA(node, OidList))
     301     1093750 :             appendStringInfo(str, " %u", lfirst_oid(lc));
     302           0 :         else if (IsA(node, XidList))
     303           0 :             appendStringInfo(str, " %u", lfirst_xid(lc));
     304             :         else
     305           0 :             elog(ERROR, "unrecognized list node type: %d",
     306             :                  (int) node->type);
     307             :     }
     308             : 
     309    14476562 :     appendStringInfoChar(str, ')');
     310    14476562 : }
     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
     322    14559044 : outBitmapset(StringInfo str, const Bitmapset *bms)
     323             : {
     324             :     int         x;
     325             : 
     326    14559044 :     appendStringInfoChar(str, '(');
     327    14559044 :     appendStringInfoChar(str, 'b');
     328    14559044 :     x = -1;
     329    18514752 :     while ((x = bms_next_member(bms, x)) >= 0)
     330     3955708 :         appendStringInfo(str, " %d", x);
     331    14559044 :     appendStringInfoChar(str, ')');
     332    14559044 : }
     333             : 
     334             : /*
     335             :  * Print the value of a Datum given its type.
     336             :  */
     337             : void
     338     1953160 : outDatum(StringInfo str, Datum value, int typlen, bool typbyval)
     339             : {
     340             :     Size        length,
     341             :                 i;
     342             :     char       *s;
     343             : 
     344     1953160 :     length = datumGetSize(value, typbyval, typlen);
     345             : 
     346     1953160 :     if (typbyval)
     347             :     {
     348     1320578 :         s = (char *) (&value);
     349     1320578 :         appendStringInfo(str, "%u [ ", (unsigned int) length);
     350    11885202 :         for (i = 0; i < (Size) sizeof(Datum); i++)
     351    10564624 :             appendStringInfo(str, "%d ", (int) (s[i]));
     352     1320578 :         appendStringInfoChar(str, ']');
     353             :     }
     354             :     else
     355             :     {
     356      632582 :         s = (char *) DatumGetPointer(value);
     357      632582 :         if (!PointerIsValid(s))
     358           0 :             appendStringInfoString(str, "0 [ ]");
     359             :         else
     360             :         {
     361      632582 :             appendStringInfo(str, "%u [ ", (unsigned int) length);
     362    53540550 :             for (i = 0; i < length; i++)
     363    52907968 :                 appendStringInfo(str, "%d ", (int) (s[i]));
     364      632582 :             appendStringInfoChar(str, ']');
     365             :         }
     366             :     }
     367     1953160 : }
     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
     379     2107494 : _outConst(StringInfo str, const Const *node)
     380             : {
     381     2107494 :     WRITE_NODE_TYPE("CONST");
     382             : 
     383     2107494 :     WRITE_OID_FIELD(consttype);
     384     2107494 :     WRITE_INT_FIELD(consttypmod);
     385     2107494 :     WRITE_OID_FIELD(constcollid);
     386     2107494 :     WRITE_INT_FIELD(constlen);
     387     2107494 :     WRITE_BOOL_FIELD(constbyval);
     388     2107494 :     WRITE_BOOL_FIELD(constisnull);
     389     2107494 :     WRITE_LOCATION_FIELD(location);
     390             : 
     391     2107494 :     appendStringInfoString(str, " :constvalue ");
     392     2107494 :     if (node->constisnull)
     393      154334 :         appendStringInfoString(str, "<>");
     394             :     else
     395     1953160 :         outDatum(str, node->constvalue, node->constlen, node->constbyval);
     396     2107494 : }
     397             : 
     398             : static void
     399      292344 : _outBoolExpr(StringInfo str, const BoolExpr *node)
     400             : {
     401      292344 :     char       *opstr = NULL;
     402             : 
     403      292344 :     WRITE_NODE_TYPE("BOOLEXPR");
     404             : 
     405             :     /* do-it-yourself enum representation */
     406      292344 :     switch (node->boolop)
     407             :     {
     408      223578 :         case AND_EXPR:
     409      223578 :             opstr = "and";
     410      223578 :             break;
     411       34114 :         case OR_EXPR:
     412       34114 :             opstr = "or";
     413       34114 :             break;
     414       34652 :         case NOT_EXPR:
     415       34652 :             opstr = "not";
     416       34652 :             break;
     417             :     }
     418      292344 :     appendStringInfoString(str, " :boolop ");
     419      292344 :     outToken(str, opstr);
     420             : 
     421      292344 :     WRITE_NODE_FIELD(args);
     422      292344 :     WRITE_LOCATION_FIELD(location);
     423      292344 : }
     424             : 
     425             : static void
     426           0 : _outForeignKeyOptInfo(StringInfo str, const ForeignKeyOptInfo *node)
     427             : {
     428             :     int         i;
     429             : 
     430           0 :     WRITE_NODE_TYPE("FOREIGNKEYOPTINFO");
     431             : 
     432           0 :     WRITE_UINT_FIELD(con_relid);
     433           0 :     WRITE_UINT_FIELD(ref_relid);
     434           0 :     WRITE_INT_FIELD(nkeys);
     435           0 :     WRITE_ATTRNUMBER_ARRAY(conkey, node->nkeys);
     436           0 :     WRITE_ATTRNUMBER_ARRAY(confkey, node->nkeys);
     437           0 :     WRITE_OID_ARRAY(conpfeqop, node->nkeys);
     438           0 :     WRITE_INT_FIELD(nmatched_ec);
     439           0 :     WRITE_INT_FIELD(nconst_ec);
     440           0 :     WRITE_INT_FIELD(nmatched_rcols);
     441           0 :     WRITE_INT_FIELD(nmatched_ri);
     442             :     /* for compactness, just print the number of matches per column: */
     443           0 :     appendStringInfoString(str, " :eclass");
     444           0 :     for (i = 0; i < node->nkeys; i++)
     445           0 :         appendStringInfo(str, " %d", (node->eclass[i] != NULL));
     446           0 :     appendStringInfoString(str, " :rinfos");
     447           0 :     for (i = 0; i < node->nkeys; i++)
     448           0 :         appendStringInfo(str, " %d", list_length(node->rinfos[i]));
     449           0 : }
     450             : 
     451             : static void
     452           0 : _outEquivalenceClass(StringInfo str, const EquivalenceClass *node)
     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           0 :     while (node->ec_merged)
     459           0 :         node = node->ec_merged;
     460             : 
     461           0 :     WRITE_NODE_TYPE("EQUIVALENCECLASS");
     462             : 
     463           0 :     WRITE_NODE_FIELD(ec_opfamilies);
     464           0 :     WRITE_OID_FIELD(ec_collation);
     465           0 :     WRITE_NODE_FIELD(ec_members);
     466           0 :     WRITE_NODE_FIELD(ec_sources);
     467           0 :     WRITE_NODE_FIELD(ec_derives);
     468           0 :     WRITE_BITMAPSET_FIELD(ec_relids);
     469           0 :     WRITE_BOOL_FIELD(ec_has_const);
     470           0 :     WRITE_BOOL_FIELD(ec_has_volatile);
     471           0 :     WRITE_BOOL_FIELD(ec_broken);
     472           0 :     WRITE_UINT_FIELD(ec_sortref);
     473           0 :     WRITE_UINT_FIELD(ec_min_security);
     474           0 :     WRITE_UINT_FIELD(ec_max_security);
     475           0 : }
     476             : 
     477             : static void
     478           0 : _outExtensibleNode(StringInfo str, const ExtensibleNode *node)
     479             : {
     480             :     const ExtensibleNodeMethods *methods;
     481             : 
     482           0 :     methods = GetExtensibleNodeMethods(node->extnodename, false);
     483             : 
     484           0 :     WRITE_NODE_TYPE("EXTENSIBLENODE");
     485             : 
     486           0 :     WRITE_STRING_FIELD(extnodename);
     487             : 
     488             :     /* serialize the private fields */
     489           0 :     methods->nodeOut(str, node);
     490           0 : }
     491             : 
     492             : static void
     493     1353236 : _outRangeTblEntry(StringInfo str, const RangeTblEntry *node)
     494             : {
     495     1353236 :     WRITE_NODE_TYPE("RANGETBLENTRY");
     496             : 
     497             :     /* put alias + eref first to make dump more legible */
     498     1353236 :     WRITE_NODE_FIELD(alias);
     499     1353236 :     WRITE_NODE_FIELD(eref);
     500     1353236 :     WRITE_ENUM_FIELD(rtekind, RTEKind);
     501             : 
     502     1353236 :     switch (node->rtekind)
     503             :     {
     504      820542 :         case RTE_RELATION:
     505      820542 :             WRITE_OID_FIELD(relid);
     506      820542 :             WRITE_CHAR_FIELD(relkind);
     507      820542 :             WRITE_INT_FIELD(rellockmode);
     508      820542 :             WRITE_NODE_FIELD(tablesample);
     509      820542 :             WRITE_UINT_FIELD(perminfoindex);
     510      820542 :             break;
     511       96496 :         case RTE_SUBQUERY:
     512       96496 :             WRITE_NODE_FIELD(subquery);
     513       96496 :             WRITE_BOOL_FIELD(security_barrier);
     514             :             /* we re-use these RELATION fields, too: */
     515       96496 :             WRITE_OID_FIELD(relid);
     516       96496 :             WRITE_CHAR_FIELD(relkind);
     517       96496 :             WRITE_INT_FIELD(rellockmode);
     518       96496 :             WRITE_UINT_FIELD(perminfoindex);
     519       96496 :             break;
     520      143862 :         case RTE_JOIN:
     521      143862 :             WRITE_ENUM_FIELD(jointype, JoinType);
     522      143862 :             WRITE_INT_FIELD(joinmergedcols);
     523      143862 :             WRITE_NODE_FIELD(joinaliasvars);
     524      143862 :             WRITE_NODE_FIELD(joinleftcols);
     525      143862 :             WRITE_NODE_FIELD(joinrightcols);
     526      143862 :             WRITE_NODE_FIELD(join_using_alias);
     527      143862 :             break;
     528       79432 :         case RTE_FUNCTION:
     529       79432 :             WRITE_NODE_FIELD(functions);
     530       79432 :             WRITE_BOOL_FIELD(funcordinality);
     531       79432 :             break;
     532         436 :         case RTE_TABLEFUNC:
     533         436 :             WRITE_NODE_FIELD(tablefunc);
     534         436 :             break;
     535       16128 :         case RTE_VALUES:
     536       16128 :             WRITE_NODE_FIELD(values_lists);
     537       16128 :             WRITE_NODE_FIELD(coltypes);
     538       16128 :             WRITE_NODE_FIELD(coltypmods);
     539       16128 :             WRITE_NODE_FIELD(colcollations);
     540       16128 :             break;
     541        8786 :         case RTE_CTE:
     542        8786 :             WRITE_STRING_FIELD(ctename);
     543        8786 :             WRITE_UINT_FIELD(ctelevelsup);
     544        8786 :             WRITE_BOOL_FIELD(self_reference);
     545        8786 :             WRITE_NODE_FIELD(coltypes);
     546        8786 :             WRITE_NODE_FIELD(coltypmods);
     547        8786 :             WRITE_NODE_FIELD(colcollations);
     548        8786 :             break;
     549         884 :         case RTE_NAMEDTUPLESTORE:
     550         884 :             WRITE_STRING_FIELD(enrname);
     551         884 :             WRITE_FLOAT_FIELD(enrtuples);
     552         884 :             WRITE_NODE_FIELD(coltypes);
     553         884 :             WRITE_NODE_FIELD(coltypmods);
     554         884 :             WRITE_NODE_FIELD(colcollations);
     555             :             /* we re-use these RELATION fields, too: */
     556         884 :             WRITE_OID_FIELD(relid);
     557         884 :             break;
     558      186670 :         case RTE_RESULT:
     559             :             /* no extra fields */
     560      186670 :             break;
     561           0 :         default:
     562           0 :             elog(ERROR, "unrecognized RTE kind: %d", (int) node->rtekind);
     563             :             break;
     564             :     }
     565             : 
     566     1353236 :     WRITE_BOOL_FIELD(lateral);
     567     1353236 :     WRITE_BOOL_FIELD(inh);
     568     1353236 :     WRITE_BOOL_FIELD(inFromCl);
     569     1353236 :     WRITE_NODE_FIELD(securityQuals);
     570     1353236 : }
     571             : 
     572             : static void
     573      537510 : _outA_Expr(StringInfo str, const A_Expr *node)
     574             : {
     575      537510 :     WRITE_NODE_TYPE("A_EXPR");
     576             : 
     577      537510 :     switch (node->kind)
     578             :     {
     579      502816 :         case AEXPR_OP:
     580      502816 :             WRITE_NODE_FIELD(name);
     581      502816 :             break;
     582       12418 :         case AEXPR_OP_ANY:
     583       12418 :             appendStringInfoString(str, " ANY");
     584       12418 :             WRITE_NODE_FIELD(name);
     585       12418 :             break;
     586         144 :         case AEXPR_OP_ALL:
     587         144 :             appendStringInfoString(str, " ALL");
     588         144 :             WRITE_NODE_FIELD(name);
     589         144 :             break;
     590         744 :         case AEXPR_DISTINCT:
     591         744 :             appendStringInfoString(str, " DISTINCT");
     592         744 :             WRITE_NODE_FIELD(name);
     593         744 :             break;
     594          68 :         case AEXPR_NOT_DISTINCT:
     595          68 :             appendStringInfoString(str, " NOT_DISTINCT");
     596          68 :             WRITE_NODE_FIELD(name);
     597          68 :             break;
     598         294 :         case AEXPR_NULLIF:
     599         294 :             appendStringInfoString(str, " NULLIF");
     600         294 :             WRITE_NODE_FIELD(name);
     601         294 :             break;
     602       18198 :         case AEXPR_IN:
     603       18198 :             appendStringInfoString(str, " IN");
     604       18198 :             WRITE_NODE_FIELD(name);
     605       18198 :             break;
     606        2050 :         case AEXPR_LIKE:
     607        2050 :             appendStringInfoString(str, " LIKE");
     608        2050 :             WRITE_NODE_FIELD(name);
     609        2050 :             break;
     610         144 :         case AEXPR_ILIKE:
     611         144 :             appendStringInfoString(str, " ILIKE");
     612         144 :             WRITE_NODE_FIELD(name);
     613         144 :             break;
     614          58 :         case AEXPR_SIMILAR:
     615          58 :             appendStringInfoString(str, " SIMILAR");
     616          58 :             WRITE_NODE_FIELD(name);
     617          58 :             break;
     618         540 :         case AEXPR_BETWEEN:
     619         540 :             appendStringInfoString(str, " BETWEEN");
     620         540 :             WRITE_NODE_FIELD(name);
     621         540 :             break;
     622          12 :         case AEXPR_NOT_BETWEEN:
     623          12 :             appendStringInfoString(str, " NOT_BETWEEN");
     624          12 :             WRITE_NODE_FIELD(name);
     625          12 :             break;
     626          12 :         case AEXPR_BETWEEN_SYM:
     627          12 :             appendStringInfoString(str, " BETWEEN_SYM");
     628          12 :             WRITE_NODE_FIELD(name);
     629          12 :             break;
     630          12 :         case AEXPR_NOT_BETWEEN_SYM:
     631          12 :             appendStringInfoString(str, " NOT_BETWEEN_SYM");
     632          12 :             WRITE_NODE_FIELD(name);
     633          12 :             break;
     634           0 :         default:
     635           0 :             elog(ERROR, "unrecognized A_Expr_Kind: %d", (int) node->kind);
     636             :             break;
     637             :     }
     638             : 
     639      537510 :     WRITE_NODE_FIELD(lexpr);
     640      537510 :     WRITE_NODE_FIELD(rexpr);
     641      537510 :     WRITE_LOCATION_FIELD(location);
     642      537510 : }
     643             : 
     644             : static void
     645      450530 : _outInteger(StringInfo str, const Integer *node)
     646             : {
     647      450530 :     appendStringInfo(str, "%d", node->ival);
     648      450530 : }
     649             : 
     650             : static void
     651       10956 : _outFloat(StringInfo str, const Float *node)
     652             : {
     653             :     /*
     654             :      * We assume the value is a valid numeric literal and so does not need
     655             :      * quoting.
     656             :      */
     657       10956 :     appendStringInfoString(str, node->fval);
     658       10956 : }
     659             : 
     660             : static void
     661       77708 : _outBoolean(StringInfo str, const Boolean *node)
     662             : {
     663       77708 :     appendStringInfoString(str, node->boolval ? "true" : "false");
     664       77708 : }
     665             : 
     666             : static void
     667    21871234 : _outString(StringInfo str, const String *node)
     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             :      */
     674    21871234 :     appendStringInfoChar(str, '"');
     675    21871234 :     if (node->sval[0] != '\0')
     676    21845502 :         outToken(str, node->sval);
     677    21871234 :     appendStringInfoChar(str, '"');
     678    21871234 : }
     679             : 
     680             : static void
     681        4044 : _outBitString(StringInfo str, const BitString *node)
     682             : {
     683             :     /* internal representation already has leading 'b' */
     684        4044 :     appendStringInfoString(str, node->bsval);
     685        4044 : }
     686             : 
     687             : static void
     688     1134858 : _outA_Const(StringInfo str, const A_Const *node)
     689             : {
     690     1134858 :     WRITE_NODE_TYPE("A_CONST");
     691             : 
     692     1134858 :     if (node->isnull)
     693       60194 :         appendStringInfoString(str, " NULL");
     694             :     else
     695             :     {
     696     1074664 :         appendStringInfoString(str, " :val ");
     697     1074664 :         outNode(str, &node->val);
     698             :     }
     699     1134858 :     WRITE_LOCATION_FIELD(location);
     700     1134858 : }
     701             : 
     702             : static void
     703       53794 : _outConstraint(StringInfo str, const Constraint *node)
     704             : {
     705       53794 :     WRITE_NODE_TYPE("CONSTRAINT");
     706             : 
     707       53794 :     WRITE_STRING_FIELD(conname);
     708       53794 :     WRITE_BOOL_FIELD(deferrable);
     709       53794 :     WRITE_BOOL_FIELD(initdeferred);
     710       53794 :     WRITE_LOCATION_FIELD(location);
     711             : 
     712       53794 :     appendStringInfoString(str, " :contype ");
     713       53794 :     switch (node->contype)
     714             :     {
     715          48 :         case CONSTR_NULL:
     716          48 :             appendStringInfoString(str, "NULL");
     717          48 :             break;
     718             : 
     719       11604 :         case CONSTR_NOTNULL:
     720       11604 :             appendStringInfoString(str, "NOT_NULL");
     721       11604 :             WRITE_NODE_FIELD(keys);
     722       11604 :             WRITE_INT_FIELD(inhcount);
     723       11604 :             WRITE_BOOL_FIELD(is_no_inherit);
     724       11604 :             WRITE_BOOL_FIELD(skip_validation);
     725       11604 :             WRITE_BOOL_FIELD(initially_valid);
     726       11604 :             break;
     727             : 
     728        3152 :         case CONSTR_DEFAULT:
     729        3152 :             appendStringInfoString(str, "DEFAULT");
     730        3152 :             WRITE_NODE_FIELD(raw_expr);
     731        3152 :             WRITE_STRING_FIELD(cooked_expr);
     732        3152 :             break;
     733             : 
     734         664 :         case CONSTR_IDENTITY:
     735         664 :             appendStringInfoString(str, "IDENTITY");
     736         664 :             WRITE_NODE_FIELD(options);
     737         664 :             WRITE_CHAR_FIELD(generated_when);
     738         664 :             break;
     739             : 
     740        1690 :         case CONSTR_GENERATED:
     741        1690 :             appendStringInfoString(str, "GENERATED");
     742        1690 :             WRITE_NODE_FIELD(raw_expr);
     743        1690 :             WRITE_STRING_FIELD(cooked_expr);
     744        1690 :             WRITE_CHAR_FIELD(generated_when);
     745        1690 :             break;
     746             : 
     747        3688 :         case CONSTR_CHECK:
     748        3688 :             appendStringInfoString(str, "CHECK");
     749        3688 :             WRITE_BOOL_FIELD(is_no_inherit);
     750        3688 :             WRITE_NODE_FIELD(raw_expr);
     751        3688 :             WRITE_STRING_FIELD(cooked_expr);
     752        3688 :             WRITE_BOOL_FIELD(skip_validation);
     753        3688 :             WRITE_BOOL_FIELD(initially_valid);
     754        3688 :             break;
     755             : 
     756       20790 :         case CONSTR_PRIMARY:
     757       20790 :             appendStringInfoString(str, "PRIMARY_KEY");
     758       20790 :             WRITE_NODE_FIELD(keys);
     759       20790 :             WRITE_NODE_FIELD(including);
     760       20790 :             WRITE_NODE_FIELD(options);
     761       20790 :             WRITE_STRING_FIELD(indexname);
     762       20790 :             WRITE_STRING_FIELD(indexspace);
     763       20790 :             WRITE_BOOL_FIELD(reset_default_tblspc);
     764             :             /* access_method and where_clause not currently used */
     765       20790 :             break;
     766             : 
     767        7218 :         case CONSTR_UNIQUE:
     768        7218 :             appendStringInfoString(str, "UNIQUE");
     769        7218 :             WRITE_BOOL_FIELD(nulls_not_distinct);
     770        7218 :             WRITE_NODE_FIELD(keys);
     771        7218 :             WRITE_NODE_FIELD(including);
     772        7218 :             WRITE_NODE_FIELD(options);
     773        7218 :             WRITE_STRING_FIELD(indexname);
     774        7218 :             WRITE_STRING_FIELD(indexspace);
     775        7218 :             WRITE_BOOL_FIELD(reset_default_tblspc);
     776             :             /* access_method and where_clause not currently used */
     777        7218 :             break;
     778             : 
     779         420 :         case CONSTR_EXCLUSION:
     780         420 :             appendStringInfoString(str, "EXCLUSION");
     781         420 :             WRITE_NODE_FIELD(exclusions);
     782         420 :             WRITE_NODE_FIELD(including);
     783         420 :             WRITE_NODE_FIELD(options);
     784         420 :             WRITE_STRING_FIELD(indexname);
     785         420 :             WRITE_STRING_FIELD(indexspace);
     786         420 :             WRITE_BOOL_FIELD(reset_default_tblspc);
     787         420 :             WRITE_STRING_FIELD(access_method);
     788         420 :             WRITE_NODE_FIELD(where_clause);
     789         420 :             break;
     790             : 
     791        4220 :         case CONSTR_FOREIGN:
     792        4220 :             appendStringInfoString(str, "FOREIGN_KEY");
     793        4220 :             WRITE_NODE_FIELD(pktable);
     794        4220 :             WRITE_NODE_FIELD(fk_attrs);
     795        4220 :             WRITE_NODE_FIELD(pk_attrs);
     796        4220 :             WRITE_CHAR_FIELD(fk_matchtype);
     797        4220 :             WRITE_CHAR_FIELD(fk_upd_action);
     798        4220 :             WRITE_CHAR_FIELD(fk_del_action);
     799        4220 :             WRITE_NODE_FIELD(fk_del_set_cols);
     800        4220 :             WRITE_NODE_FIELD(old_conpfeqop);
     801        4220 :             WRITE_OID_FIELD(old_pktable_oid);
     802        4220 :             WRITE_BOOL_FIELD(skip_validation);
     803        4220 :             WRITE_BOOL_FIELD(initially_valid);
     804        4220 :             break;
     805             : 
     806         162 :         case CONSTR_ATTR_DEFERRABLE:
     807         162 :             appendStringInfoString(str, "ATTR_DEFERRABLE");
     808         162 :             break;
     809             : 
     810           0 :         case CONSTR_ATTR_NOT_DEFERRABLE:
     811           0 :             appendStringInfoString(str, "ATTR_NOT_DEFERRABLE");
     812           0 :             break;
     813             : 
     814         126 :         case CONSTR_ATTR_DEFERRED:
     815         126 :             appendStringInfoString(str, "ATTR_DEFERRED");
     816         126 :             break;
     817             : 
     818          12 :         case CONSTR_ATTR_IMMEDIATE:
     819          12 :             appendStringInfoString(str, "ATTR_IMMEDIATE");
     820          12 :             break;
     821             : 
     822           0 :         default:
     823           0 :             elog(ERROR, "unrecognized ConstrType: %d", (int) node->contype);
     824             :             break;
     825             :     }
     826       53794 : }
     827             : 
     828             : 
     829             : /*
     830             :  * outNode -
     831             :  *    converts a Node into ascii string and append it to 'str'
     832             :  */
     833             : void
     834   116636414 : outNode(StringInfo str, const void *obj)
     835             : {
     836             :     /* Guard against stack overflow due to overly complex expressions */
     837   116636414 :     check_stack_depth();
     838             : 
     839   116636414 :     if (obj == NULL)
     840    41554532 :         appendStringInfoString(str, "<>");
     841    75081882 :     else if (IsA(obj, List) || IsA(obj, IntList) || IsA(obj, OidList) ||
     842    60605320 :              IsA(obj, XidList))
     843    14476562 :         _outList(str, obj);
     844             :     /* nodeRead does not want to see { } around these! */
     845    60605320 :     else if (IsA(obj, Integer))
     846      450530 :         _outInteger(str, (Integer *) obj);
     847    60154790 :     else if (IsA(obj, Float))
     848       10956 :         _outFloat(str, (Float *) obj);
     849    60143834 :     else if (IsA(obj, Boolean))
     850       77708 :         _outBoolean(str, (Boolean *) obj);
     851    60066126 :     else if (IsA(obj, String))
     852    21871234 :         _outString(str, (String *) obj);
     853    38194892 :     else if (IsA(obj, BitString))
     854        4044 :         _outBitString(str, (BitString *) obj);
     855    38190848 :     else if (IsA(obj, Bitmapset))
     856           0 :         outBitmapset(str, (Bitmapset *) obj);
     857             :     else
     858             :     {
     859    38190848 :         appendStringInfoChar(str, '{');
     860    38190848 :         switch (nodeTag(obj))
     861             :         {
     862             : #include "outfuncs.switch.c"
     863             : 
     864           0 :             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           0 :                 elog(WARNING, "could not dump unrecognized node type: %d",
     871             :                      (int) nodeTag(obj));
     872           0 :                 break;
     873             :         }
     874    38190848 :         appendStringInfoChar(str, '}');
     875             :     }
     876   116636414 : }
     877             : 
     878             : /*
     879             :  * nodeToString -
     880             :  *     returns the ascii representation of the Node as a palloc'd string
     881             :  */
     882             : char *
     883     1703212 : nodeToString(const void *obj)
     884             : {
     885             :     StringInfoData str;
     886             : 
     887             :     /* see stringinfo.h for an explanation of this maneuver */
     888     1703212 :     initStringInfo(&str);
     889     1703212 :     outNode(&str, obj);
     890     1703212 :     return str.data;
     891             : }
     892             : 
     893             : /*
     894             :  * bmsToString -
     895             :  *     returns the ascii representation of the Bitmapset as a palloc'd string
     896             :  */
     897             : char *
     898           0 : bmsToString(const Bitmapset *bms)
     899             : {
     900             :     StringInfoData str;
     901             : 
     902             :     /* see stringinfo.h for an explanation of this maneuver */
     903           0 :     initStringInfo(&str);
     904           0 :     outBitmapset(&str, bms);
     905           0 :     return str.data;
     906             : }

Generated by: LCOV version 1.14