LCOV - differential code coverage report
Current view: top level - src/backend/nodes - outfuncs.c (source / functions) Coverage Total Hit UNC LBC UIC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 40.9 % 455 186 40 1 228 8 144 19 15 9 26 252 144
Current Date: 2023-04-08 15:15:32 Functions: 55.2 % 29 16 2 11 11 5 2 8 11 8
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  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 ECB             : #define WRITE_BOOL_ARRAY(fldname, len) \
     130                 :     (appendStringInfoString(str, " :" CppAsString(fldname) " "), \
     131                 :      writeBoolCols(str, node->fldname, len))
     132 EUB             : 
     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 ECB             :  */
     145                 : void
     146 CBC     5872388 : outToken(StringInfo str, const char *s)
     147 ECB             : {
     148 GNC     5872388 :     if (s == NULL)
     149 ECB             :     {
     150 CBC       27325 :         appendStringInfoString(str, "<>");
     151 GIC       27325 :         return;
     152                 :     }
     153 GNC     5845063 :     if (*s == '\0')
     154                 :     {
     155 UNC           0 :         appendStringInfoString(str, "\"\"");
     156               0 :         return;
     157                 :     }
     158 ECB             : 
     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 GIC     5845063 :     if (*s == '<' ||
     166         5845057 :         *s == '"' ||
     167         5845057 :         isdigit((unsigned char) *s) ||
     168         5845057 :         ((*s == '+' || *s == '-') &&
     169 UIC           0 :          (isdigit((unsigned char) s[1]) || s[1] == '.')))
     170 GIC           6 :         appendStringInfoChar(str, '\\');
     171 CBC    59393099 :     while (*s)
     172                 :     {
     173                 :         /* These chars must be backslashed anywhere in the string */
     174 GIC    53548036 :         if (*s == ' ' || *s == '\n' || *s == '\t' ||
     175        53513191 :             *s == '(' || *s == ')' || *s == '{' || *s == '}' ||
     176 CBC    53513191 :             *s == '\\')
     177 GIC       34845 :             appendStringInfoChar(str, '\\');
     178 GBC    53548036 :         appendStringInfoChar(str, *s++);
     179 EUB             :     }
     180                 : }
     181                 : 
     182 ECB             : /*
     183                 :  * Convert one char.  Goes through outToken() so that special characters are
     184                 :  * escaped.
     185                 :  */
     186                 : static void
     187 GIC      152249 : outChar(StringInfo str, char c)
     188                 : {
     189                 :     char        in[2];
     190                 : 
     191                 :     /* Traditionally, we've represented \0 as <>, so keep doing that */
     192 GNC      152249 :     if (c == '\0')
     193                 :     {
     194 UNC           0 :         appendStringInfoString(str, "<>");
     195               0 :         return;
     196                 :     }
     197                 : 
     198 GIC      152249 :     in[0] = c;
     199 CBC      152249 :     in[1] = '\0';
     200                 : 
     201 GIC      152249 :     outToken(str, in);
     202                 : }
     203 ECB             : 
     204                 : /*
     205                 :  * Convert a double value, attempting to ensure the value is preserved exactly.
     206                 :  */
     207                 : static void
     208 GNC        4566 : outDouble(StringInfo str, double d)
     209                 : {
     210                 :     char        buf[DOUBLE_SHORTEST_DECIMAL_LEN];
     211                 : 
     212            4566 :     double_to_shortest_decimal_buf(d, buf);
     213            4566 :     appendStringInfoString(str, buf);
     214            4566 : }
     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             584 : WRITE_SCALAR_ARRAY(writeAttrNumberCols, AttrNumber, " %d",)
     240            1717 : WRITE_SCALAR_ARRAY(writeOidCols, Oid, " %u",)
     241 UNC           0 : WRITE_SCALAR_ARRAY(writeIndexCols, Index, " %u",)
     242 GNC        1056 : WRITE_SCALAR_ARRAY(writeIntCols, int, " %d",)
     243             161 : 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 UNC           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 ECB             : static void
     272 CBC     1460578 : _outList(StringInfo str, const List *node)
     273                 : {
     274                 :     const ListCell *lc;
     275                 : 
     276 GIC     1460578 :     appendStringInfoChar(str, '(');
     277                 : 
     278         1460578 :     if (IsA(node, IntList))
     279          100385 :         appendStringInfoChar(str, 'i');
     280         1360193 :     else if (IsA(node, OidList))
     281           29841 :         appendStringInfoChar(str, 'o');
     282 GNC     1330352 :     else if (IsA(node, XidList))
     283 UNC           0 :         appendStringInfoChar(str, 'x');
     284                 : 
     285 GIC    13223340 :     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        11762762 :         if (IsA(node, List))
     293                 :         {
     294         9348408 :             outNode(str, lfirst(lc));
     295         9348408 :             if (lnext(node, lc))
     296         8018056 :                 appendStringInfoChar(str, ' ');
     297                 :         }
     298         2414354 :         else if (IsA(node, IntList))
     299 CBC     2272495 :             appendStringInfo(str, " %d", lfirst_int(lc));
     300          141859 :         else if (IsA(node, OidList))
     301 GBC      141859 :             appendStringInfo(str, " %u", lfirst_oid(lc));
     302 UNC           0 :         else if (IsA(node, XidList))
     303               0 :             appendStringInfo(str, " %u", lfirst_xid(lc));
     304 ECB             :         else
     305 LBC           0 :             elog(ERROR, "unrecognized list node type: %d",
     306                 :                  (int) node->type);
     307                 :     }
     308                 : 
     309 GIC     1460578 :     appendStringInfoChar(str, ')');
     310         1460578 : }
     311                 : 
     312                 : /*
     313                 :  * outBitmapset -
     314 EUB             :  *     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 GBC     3573485 : outBitmapset(StringInfo str, const Bitmapset *bms)
     323                 : {
     324 EUB             :     int         x;
     325                 : 
     326 GIC     3573485 :     appendStringInfoChar(str, '(');
     327 GBC     3573485 :     appendStringInfoChar(str, 'b');
     328 GIC     3573485 :     x = -1;
     329         4489977 :     while ((x = bms_next_member(bms, x)) >= 0)
     330 GBC      916492 :         appendStringInfo(str, " %d", x);
     331         3573485 :     appendStringInfoChar(str, ')');
     332 GIC     3573485 : }
     333                 : 
     334                 : /*
     335                 :  * Print the value of a Datum given its type.
     336                 :  */
     337 ECB             : void
     338 GIC      390985 : outDatum(StringInfo str, Datum value, int typlen, bool typbyval)
     339                 : {
     340                 :     Size        length,
     341 ECB             :                 i;
     342                 :     char       *s;
     343                 : 
     344 CBC      390985 :     length = datumGetSize(value, typbyval, typlen);
     345 ECB             : 
     346 CBC      390985 :     if (typbyval)
     347 ECB             :     {
     348 GBC      235742 :         s = (char *) (&value);
     349 GIC      235742 :         appendStringInfo(str, "%u [ ", (unsigned int) length);
     350 CBC     2121678 :         for (i = 0; i < (Size) sizeof(Datum); i++)
     351 GIC     1885936 :             appendStringInfo(str, "%d ", (int) (s[i]));
     352          235742 :         appendStringInfoChar(str, ']');
     353                 :     }
     354                 :     else
     355                 :     {
     356          155243 :         s = (char *) DatumGetPointer(value);
     357 CBC      155243 :         if (!PointerIsValid(s))
     358 UIC           0 :             appendStringInfoString(str, "0 [ ]");
     359 ECB             :         else
     360                 :         {
     361 CBC      155243 :             appendStringInfo(str, "%u [ ", (unsigned int) length);
     362 GIC     3218451 :             for (i = 0; i < length; i++)
     363 CBC     3063208 :                 appendStringInfo(str, "%d ", (int) (s[i]));
     364          155243 :             appendStringInfoChar(str, ']');
     365 ECB             :         }
     366                 :     }
     367 GBC      390985 : }
     368 EUB             : 
     369                 : 
     370                 : #include "outfuncs.funcs.c"
     371                 : 
     372                 : 
     373 ECB             : /*
     374                 :  * Support functions for nodes with custom_read_write attribute or
     375                 :  * special_read_write attribute
     376                 :  */
     377                 : 
     378                 : static void
     379 GIC      467276 : _outConst(StringInfo str, const Const *node)
     380                 : {
     381          467276 :     WRITE_NODE_TYPE("CONST");
     382                 : 
     383          467276 :     WRITE_OID_FIELD(consttype);
     384          467276 :     WRITE_INT_FIELD(consttypmod);
     385          467276 :     WRITE_OID_FIELD(constcollid);
     386          467276 :     WRITE_INT_FIELD(constlen);
     387          467276 :     WRITE_BOOL_FIELD(constbyval);
     388          467276 :     WRITE_BOOL_FIELD(constisnull);
     389          467276 :     WRITE_LOCATION_FIELD(location);
     390                 : 
     391          467276 :     appendStringInfoString(str, " :constvalue ");
     392          467276 :     if (node->constisnull)
     393           76291 :         appendStringInfoString(str, "<>");
     394                 :     else
     395          390985 :         outDatum(str, node->constvalue, node->constlen, node->constbyval);
     396          467276 : }
     397                 : 
     398                 : static void
     399           70533 : _outBoolExpr(StringInfo str, const BoolExpr *node)
     400                 : {
     401           70533 :     char       *opstr = NULL;
     402                 : 
     403           70533 :     WRITE_NODE_TYPE("BOOLEXPR");
     404                 : 
     405                 :     /* do-it-yourself enum representation */
     406           70533 :     switch (node->boolop)
     407                 :     {
     408           41660 :         case AND_EXPR:
     409           41660 :             opstr = "and";
     410           41660 :             break;
     411           19135 :         case OR_EXPR:
     412           19135 :             opstr = "or";
     413           19135 :             break;
     414            9738 :         case NOT_EXPR:
     415            9738 :             opstr = "not";
     416            9738 :             break;
     417                 :     }
     418           70533 :     appendStringInfoString(str, " :boolop ");
     419           70533 :     outToken(str, opstr);
     420                 : 
     421           70533 :     WRITE_NODE_FIELD(args);
     422           70533 :     WRITE_LOCATION_FIELD(location);
     423           70533 : }
     424                 : 
     425                 : static void
     426 UIC           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 GIC      229315 : _outRangeTblEntry(StringInfo str, const RangeTblEntry *node)
     494                 : {
     495          229315 :     WRITE_NODE_TYPE("RANGETBLENTRY");
     496                 : 
     497                 :     /* put alias + eref first to make dump more legible */
     498          229315 :     WRITE_NODE_FIELD(alias);
     499          229315 :     WRITE_NODE_FIELD(eref);
     500          229315 :     WRITE_ENUM_FIELD(rtekind, RTEKind);
     501                 : 
     502          229315 :     switch (node->rtekind)
     503                 :     {
     504          142736 :         case RTE_RELATION:
     505          142736 :             WRITE_OID_FIELD(relid);
     506          142736 :             WRITE_CHAR_FIELD(relkind);
     507          142736 :             WRITE_INT_FIELD(rellockmode);
     508          142736 :             WRITE_NODE_FIELD(tablesample);
     509 GNC      142736 :             WRITE_UINT_FIELD(perminfoindex);
     510 GIC      142736 :             break;
     511           27954 :         case RTE_SUBQUERY:
     512           27954 :             WRITE_NODE_FIELD(subquery);
     513           27954 :             WRITE_BOOL_FIELD(security_barrier);
     514                 :             /* we re-use these RELATION fields, too: */
     515 GNC       27954 :             WRITE_OID_FIELD(relid);
     516           27954 :             WRITE_INT_FIELD(rellockmode);
     517           27954 :             WRITE_UINT_FIELD(perminfoindex);
     518 GIC       27954 :             break;
     519           44248 :         case RTE_JOIN:
     520           44248 :             WRITE_ENUM_FIELD(jointype, JoinType);
     521           44248 :             WRITE_INT_FIELD(joinmergedcols);
     522           44248 :             WRITE_NODE_FIELD(joinaliasvars);
     523           44248 :             WRITE_NODE_FIELD(joinleftcols);
     524           44248 :             WRITE_NODE_FIELD(joinrightcols);
     525           44248 :             WRITE_NODE_FIELD(join_using_alias);
     526           44248 :             break;
     527           13850 :         case RTE_FUNCTION:
     528           13850 :             WRITE_NODE_FIELD(functions);
     529           13850 :             WRITE_BOOL_FIELD(funcordinality);
     530           13850 :             break;
     531               8 :         case RTE_TABLEFUNC:
     532               8 :             WRITE_NODE_FIELD(tablefunc);
     533               8 :             break;
     534             426 :         case RTE_VALUES:
     535             426 :             WRITE_NODE_FIELD(values_lists);
     536             426 :             WRITE_NODE_FIELD(coltypes);
     537             426 :             WRITE_NODE_FIELD(coltypmods);
     538             426 :             WRITE_NODE_FIELD(colcollations);
     539             426 :             break;
     540              69 :         case RTE_CTE:
     541              69 :             WRITE_STRING_FIELD(ctename);
     542              69 :             WRITE_UINT_FIELD(ctelevelsup);
     543              69 :             WRITE_BOOL_FIELD(self_reference);
     544              69 :             WRITE_NODE_FIELD(coltypes);
     545              69 :             WRITE_NODE_FIELD(coltypmods);
     546              69 :             WRITE_NODE_FIELD(colcollations);
     547              69 :             break;
     548 UIC           0 :         case RTE_NAMEDTUPLESTORE:
     549               0 :             WRITE_STRING_FIELD(enrname);
     550 UNC           0 :             WRITE_FLOAT_FIELD(enrtuples);
     551 UIC           0 :             WRITE_NODE_FIELD(coltypes);
     552               0 :             WRITE_NODE_FIELD(coltypmods);
     553               0 :             WRITE_NODE_FIELD(colcollations);
     554                 :             /* we re-use these RELATION fields, too: */
     555 UNC           0 :             WRITE_OID_FIELD(relid);
     556 UIC           0 :             break;
     557 GIC          24 :         case RTE_RESULT:
     558                 :             /* no extra fields */
     559              24 :             break;
     560 UIC           0 :         default:
     561               0 :             elog(ERROR, "unrecognized RTE kind: %d", (int) node->rtekind);
     562                 :             break;
     563                 :     }
     564                 : 
     565 GIC      229315 :     WRITE_BOOL_FIELD(lateral);
     566          229315 :     WRITE_BOOL_FIELD(inh);
     567          229315 :     WRITE_BOOL_FIELD(inFromCl);
     568          229315 :     WRITE_NODE_FIELD(securityQuals);
     569          229315 : }
     570                 : 
     571                 : static void
     572 UIC           0 : _outA_Expr(StringInfo str, const A_Expr *node)
     573                 : {
     574 UNC           0 :     WRITE_NODE_TYPE("A_EXPR");
     575                 : 
     576 UIC           0 :     switch (node->kind)
     577                 :     {
     578               0 :         case AEXPR_OP:
     579               0 :             WRITE_NODE_FIELD(name);
     580               0 :             break;
     581               0 :         case AEXPR_OP_ANY:
     582 UNC           0 :             appendStringInfoString(str, " ANY");
     583 UIC           0 :             WRITE_NODE_FIELD(name);
     584               0 :             break;
     585               0 :         case AEXPR_OP_ALL:
     586 UNC           0 :             appendStringInfoString(str, " ALL");
     587 UIC           0 :             WRITE_NODE_FIELD(name);
     588               0 :             break;
     589               0 :         case AEXPR_DISTINCT:
     590 UNC           0 :             appendStringInfoString(str, " DISTINCT");
     591 UIC           0 :             WRITE_NODE_FIELD(name);
     592               0 :             break;
     593               0 :         case AEXPR_NOT_DISTINCT:
     594 UNC           0 :             appendStringInfoString(str, " NOT_DISTINCT");
     595 UIC           0 :             WRITE_NODE_FIELD(name);
     596               0 :             break;
     597               0 :         case AEXPR_NULLIF:
     598 UNC           0 :             appendStringInfoString(str, " NULLIF");
     599 UIC           0 :             WRITE_NODE_FIELD(name);
     600               0 :             break;
     601               0 :         case AEXPR_IN:
     602 UNC           0 :             appendStringInfoString(str, " IN");
     603 UIC           0 :             WRITE_NODE_FIELD(name);
     604               0 :             break;
     605               0 :         case AEXPR_LIKE:
     606 UNC           0 :             appendStringInfoString(str, " LIKE");
     607 UIC           0 :             WRITE_NODE_FIELD(name);
     608               0 :             break;
     609               0 :         case AEXPR_ILIKE:
     610 UNC           0 :             appendStringInfoString(str, " ILIKE");
     611 UIC           0 :             WRITE_NODE_FIELD(name);
     612               0 :             break;
     613               0 :         case AEXPR_SIMILAR:
     614 UNC           0 :             appendStringInfoString(str, " SIMILAR");
     615 UIC           0 :             WRITE_NODE_FIELD(name);
     616               0 :             break;
     617               0 :         case AEXPR_BETWEEN:
     618 UNC           0 :             appendStringInfoString(str, " BETWEEN");
     619 UIC           0 :             WRITE_NODE_FIELD(name);
     620               0 :             break;
     621               0 :         case AEXPR_NOT_BETWEEN:
     622 UNC           0 :             appendStringInfoString(str, " NOT_BETWEEN");
     623 UIC           0 :             WRITE_NODE_FIELD(name);
     624               0 :             break;
     625               0 :         case AEXPR_BETWEEN_SYM:
     626 UNC           0 :             appendStringInfoString(str, " BETWEEN_SYM");
     627 UIC           0 :             WRITE_NODE_FIELD(name);
     628               0 :             break;
     629               0 :         case AEXPR_NOT_BETWEEN_SYM:
     630 UNC           0 :             appendStringInfoString(str, " NOT_BETWEEN_SYM");
     631 UIC           0 :             WRITE_NODE_FIELD(name);
     632               0 :             break;
     633               0 :         default:
     634 UNC           0 :             elog(ERROR, "unrecognized A_Expr_Kind: %d", (int) node->kind);
     635                 :             break;
     636                 :     }
     637                 : 
     638 UIC           0 :     WRITE_NODE_FIELD(lexpr);
     639               0 :     WRITE_NODE_FIELD(rexpr);
     640               0 :     WRITE_LOCATION_FIELD(location);
     641               0 : }
     642                 : 
     643                 : static void
     644               0 : _outInteger(StringInfo str, const Integer *node)
     645                 : {
     646               0 :     appendStringInfo(str, "%d", node->ival);
     647               0 : }
     648                 : 
     649                 : static void
     650               0 : _outFloat(StringInfo str, const Float *node)
     651                 : {
     652                 :     /*
     653                 :      * We assume the value is a valid numeric literal and so does not need
     654                 :      * quoting.
     655                 :      */
     656               0 :     appendStringInfoString(str, node->fval);
     657               0 : }
     658                 : 
     659                 : static void
     660               0 : _outBoolean(StringInfo str, const Boolean *node)
     661                 : {
     662               0 :     appendStringInfoString(str, node->boolval ? "true" : "false");
     663               0 : }
     664                 : 
     665                 : static void
     666 GIC     4641538 : _outString(StringInfo str, const String *node)
     667                 : {
     668                 :     /*
     669                 :      * We use outToken to provide escaping of the string's content, but we
     670                 :      * don't want it to convert an empty string to '""', because we're putting
     671                 :      * double quotes around the string already.
     672                 :      */
     673         4641538 :     appendStringInfoChar(str, '"');
     674         4641538 :     if (node->sval[0] != '\0')
     675         4641484 :         outToken(str, node->sval);
     676         4641538 :     appendStringInfoChar(str, '"');
     677         4641538 : }
     678                 : 
     679                 : static void
     680 UIC           0 : _outBitString(StringInfo str, const BitString *node)
     681                 : {
     682                 :     /* internal representation already has leading 'b' */
     683               0 :     appendStringInfoString(str, node->bsval);
     684               0 : }
     685                 : 
     686                 : static void
     687               0 : _outA_Const(StringInfo str, const A_Const *node)
     688                 : {
     689               0 :     WRITE_NODE_TYPE("A_CONST");
     690                 : 
     691               0 :     if (node->isnull)
     692               0 :         appendStringInfoString(str, " NULL");
     693                 :     else
     694                 :     {
     695               0 :         appendStringInfoString(str, " :val ");
     696               0 :         outNode(str, &node->val);
     697                 :     }
     698               0 :     WRITE_LOCATION_FIELD(location);
     699               0 : }
     700                 : 
     701                 : static void
     702               0 : _outConstraint(StringInfo str, const Constraint *node)
     703                 : {
     704               0 :     WRITE_NODE_TYPE("CONSTRAINT");
     705                 : 
     706               0 :     WRITE_STRING_FIELD(conname);
     707               0 :     WRITE_BOOL_FIELD(deferrable);
     708               0 :     WRITE_BOOL_FIELD(initdeferred);
     709               0 :     WRITE_LOCATION_FIELD(location);
     710                 : 
     711               0 :     appendStringInfoString(str, " :contype ");
     712               0 :     switch (node->contype)
     713                 :     {
     714               0 :         case CONSTR_NULL:
     715               0 :             appendStringInfoString(str, "NULL");
     716               0 :             break;
     717                 : 
     718               0 :         case CONSTR_NOTNULL:
     719               0 :             appendStringInfoString(str, "NOT_NULL");
     720 UNC           0 :             WRITE_BOOL_FIELD(is_no_inherit);
     721               0 :             WRITE_STRING_FIELD(colname);
     722               0 :             WRITE_BOOL_FIELD(skip_validation);
     723               0 :             WRITE_BOOL_FIELD(initially_valid);
     724 UIC           0 :             break;
     725                 : 
     726               0 :         case CONSTR_DEFAULT:
     727               0 :             appendStringInfoString(str, "DEFAULT");
     728               0 :             WRITE_NODE_FIELD(raw_expr);
     729               0 :             WRITE_STRING_FIELD(cooked_expr);
     730               0 :             break;
     731                 : 
     732               0 :         case CONSTR_IDENTITY:
     733               0 :             appendStringInfoString(str, "IDENTITY");
     734               0 :             WRITE_NODE_FIELD(options);
     735               0 :             WRITE_CHAR_FIELD(generated_when);
     736               0 :             break;
     737                 : 
     738               0 :         case CONSTR_GENERATED:
     739               0 :             appendStringInfoString(str, "GENERATED");
     740               0 :             WRITE_NODE_FIELD(raw_expr);
     741               0 :             WRITE_STRING_FIELD(cooked_expr);
     742               0 :             WRITE_CHAR_FIELD(generated_when);
     743               0 :             break;
     744                 : 
     745               0 :         case CONSTR_CHECK:
     746               0 :             appendStringInfoString(str, "CHECK");
     747               0 :             WRITE_BOOL_FIELD(is_no_inherit);
     748               0 :             WRITE_NODE_FIELD(raw_expr);
     749               0 :             WRITE_STRING_FIELD(cooked_expr);
     750               0 :             WRITE_BOOL_FIELD(skip_validation);
     751               0 :             WRITE_BOOL_FIELD(initially_valid);
     752               0 :             break;
     753                 : 
     754               0 :         case CONSTR_PRIMARY:
     755               0 :             appendStringInfoString(str, "PRIMARY_KEY");
     756               0 :             WRITE_NODE_FIELD(keys);
     757               0 :             WRITE_NODE_FIELD(including);
     758               0 :             WRITE_NODE_FIELD(options);
     759               0 :             WRITE_STRING_FIELD(indexname);
     760               0 :             WRITE_STRING_FIELD(indexspace);
     761               0 :             WRITE_BOOL_FIELD(reset_default_tblspc);
     762                 :             /* access_method and where_clause not currently used */
     763               0 :             break;
     764                 : 
     765               0 :         case CONSTR_UNIQUE:
     766               0 :             appendStringInfoString(str, "UNIQUE");
     767               0 :             WRITE_BOOL_FIELD(nulls_not_distinct);
     768               0 :             WRITE_NODE_FIELD(keys);
     769               0 :             WRITE_NODE_FIELD(including);
     770               0 :             WRITE_NODE_FIELD(options);
     771               0 :             WRITE_STRING_FIELD(indexname);
     772               0 :             WRITE_STRING_FIELD(indexspace);
     773               0 :             WRITE_BOOL_FIELD(reset_default_tblspc);
     774                 :             /* access_method and where_clause not currently used */
     775               0 :             break;
     776                 : 
     777               0 :         case CONSTR_EXCLUSION:
     778               0 :             appendStringInfoString(str, "EXCLUSION");
     779               0 :             WRITE_NODE_FIELD(exclusions);
     780               0 :             WRITE_NODE_FIELD(including);
     781               0 :             WRITE_NODE_FIELD(options);
     782               0 :             WRITE_STRING_FIELD(indexname);
     783               0 :             WRITE_STRING_FIELD(indexspace);
     784               0 :             WRITE_BOOL_FIELD(reset_default_tblspc);
     785               0 :             WRITE_STRING_FIELD(access_method);
     786               0 :             WRITE_NODE_FIELD(where_clause);
     787               0 :             break;
     788                 : 
     789               0 :         case CONSTR_FOREIGN:
     790               0 :             appendStringInfoString(str, "FOREIGN_KEY");
     791               0 :             WRITE_NODE_FIELD(pktable);
     792               0 :             WRITE_NODE_FIELD(fk_attrs);
     793               0 :             WRITE_NODE_FIELD(pk_attrs);
     794               0 :             WRITE_CHAR_FIELD(fk_matchtype);
     795               0 :             WRITE_CHAR_FIELD(fk_upd_action);
     796               0 :             WRITE_CHAR_FIELD(fk_del_action);
     797               0 :             WRITE_NODE_FIELD(fk_del_set_cols);
     798               0 :             WRITE_NODE_FIELD(old_conpfeqop);
     799               0 :             WRITE_OID_FIELD(old_pktable_oid);
     800               0 :             WRITE_BOOL_FIELD(skip_validation);
     801               0 :             WRITE_BOOL_FIELD(initially_valid);
     802               0 :             break;
     803                 : 
     804               0 :         case CONSTR_ATTR_DEFERRABLE:
     805               0 :             appendStringInfoString(str, "ATTR_DEFERRABLE");
     806               0 :             break;
     807                 : 
     808               0 :         case CONSTR_ATTR_NOT_DEFERRABLE:
     809               0 :             appendStringInfoString(str, "ATTR_NOT_DEFERRABLE");
     810               0 :             break;
     811                 : 
     812               0 :         case CONSTR_ATTR_DEFERRED:
     813               0 :             appendStringInfoString(str, "ATTR_DEFERRED");
     814               0 :             break;
     815                 : 
     816               0 :         case CONSTR_ATTR_IMMEDIATE:
     817               0 :             appendStringInfoString(str, "ATTR_IMMEDIATE");
     818               0 :             break;
     819                 : 
     820               0 :         default:
     821 UNC           0 :             elog(ERROR, "unrecognized ConstrType: %d", (int) node->contype);
     822                 :             break;
     823                 :     }
     824 UIC           0 : }
     825                 : 
     826                 : 
     827                 : /*
     828                 :  * outNode -
     829                 :  *    converts a Node into ascii string and append it to 'str'
     830                 :  */
     831                 : void
     832 GIC    15586109 : outNode(StringInfo str, const void *obj)
     833                 : {
     834                 :     /* Guard against stack overflow due to overly complex expressions */
     835        15586109 :     check_stack_depth();
     836                 : 
     837        15586109 :     if (obj == NULL)
     838         2860774 :         appendStringInfoString(str, "<>");
     839 GNC    12725335 :     else if (IsA(obj, List) || IsA(obj, IntList) || IsA(obj, OidList) ||
     840        11264757 :              IsA(obj, XidList))
     841 GIC     1460578 :         _outList(str, obj);
     842                 :     /* nodeRead does not want to see { } around these! */
     843        11264757 :     else if (IsA(obj, Integer))
     844 UIC           0 :         _outInteger(str, (Integer *) obj);
     845 GIC    11264757 :     else if (IsA(obj, Float))
     846 UIC           0 :         _outFloat(str, (Float *) obj);
     847 GIC    11264757 :     else if (IsA(obj, Boolean))
     848 UIC           0 :         _outBoolean(str, (Boolean *) obj);
     849 GIC    11264757 :     else if (IsA(obj, String))
     850         4641538 :         _outString(str, (String *) obj);
     851         6623219 :     else if (IsA(obj, BitString))
     852 UIC           0 :         _outBitString(str, (BitString *) obj);
     853 GNC     6623219 :     else if (IsA(obj, Bitmapset))
     854 UNC           0 :         outBitmapset(str, (Bitmapset *) obj);
     855                 :     else
     856                 :     {
     857 GIC     6623219 :         appendStringInfoChar(str, '{');
     858         6623219 :         switch (nodeTag(obj))
     859                 :         {
     860                 : #include "outfuncs.switch.c"
     861                 : 
     862 UIC           0 :             default:
     863                 : 
     864                 :                 /*
     865                 :                  * This should be an ERROR, but it's too useful to be able to
     866                 :                  * dump structures that outNode only understands part of.
     867                 :                  */
     868               0 :                 elog(WARNING, "could not dump unrecognized node type: %d",
     869                 :                      (int) nodeTag(obj));
     870               0 :                 break;
     871                 :         }
     872 GIC     6623219 :         appendStringInfoChar(str, '}');
     873                 :     }
     874        15586109 : }
     875                 : 
     876                 : /*
     877                 :  * nodeToString -
     878                 :  *     returns the ascii representation of the Node as a palloc'd string
     879                 :  */
     880                 : char *
     881          127923 : nodeToString(const void *obj)
     882                 : {
     883                 :     StringInfoData str;
     884                 : 
     885                 :     /* see stringinfo.h for an explanation of this maneuver */
     886          127923 :     initStringInfo(&str);
     887          127923 :     outNode(&str, obj);
     888          127923 :     return str.data;
     889                 : }
     890                 : 
     891                 : /*
     892                 :  * bmsToString -
     893                 :  *     returns the ascii representation of the Bitmapset as a palloc'd string
     894                 :  */
     895                 : char *
     896 UIC           0 : bmsToString(const Bitmapset *bms)
     897                 : {
     898                 :     StringInfoData str;
     899                 : 
     900                 :     /* see stringinfo.h for an explanation of this maneuver */
     901               0 :     initStringInfo(&str);
     902               0 :     outBitmapset(&str, bms);
     903               0 :     return str.data;
     904                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a