LCOV - code coverage report
Current view: top level - src/backend/nodes - readfuncs.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 88.7 % 265 235
Test Date: 2026-07-03 19:57:34 Functions: 86.7 % 15 13
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 54.5 % 312 170

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * readfuncs.c
       4                 :             :  *    Reader functions for Postgres tree nodes.
       5                 :             :  *
       6                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       7                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
       8                 :             :  *
       9                 :             :  *
      10                 :             :  * IDENTIFICATION
      11                 :             :  *    src/backend/nodes/readfuncs.c
      12                 :             :  *
      13                 :             :  * NOTES
      14                 :             :  *    Parse location fields are written out by outfuncs.c, but only for
      15                 :             :  *    debugging use.  When reading a location field, we normally discard
      16                 :             :  *    the stored value and set the location field to -1 (ie, "unknown").
      17                 :             :  *    This is because nodes coming from a stored rule should not be thought
      18                 :             :  *    to have a known location in the current query's text.
      19                 :             :  *
      20                 :             :  *    However, if restore_location_fields is true, we do restore location
      21                 :             :  *    fields from the string.  This is currently intended only for use by the
      22                 :             :  *    debug_write_read_parse_plan_trees test code, which doesn't want to cause
      23                 :             :  *    any change in the node contents.
      24                 :             :  *
      25                 :             :  *-------------------------------------------------------------------------
      26                 :             :  */
      27                 :             : #include "postgres.h"
      28                 :             : 
      29                 :             : #include "miscadmin.h"
      30                 :             : #include "nodes/bitmapset.h"
      31                 :             : #include "nodes/readfuncs.h"
      32                 :             : 
      33                 :             : 
      34                 :             : /*
      35                 :             :  * Macros to simplify reading of different kinds of fields.  Use these
      36                 :             :  * wherever possible to reduce the chance for silly typos.  Note that these
      37                 :             :  * hard-wire conventions about the names of the local variables in a Read
      38                 :             :  * routine.
      39                 :             :  */
      40                 :             : 
      41                 :             : /* Macros for declaring appropriate local variables */
      42                 :             : 
      43                 :             : /* A few guys need only local_node */
      44                 :             : #define READ_LOCALS_NO_FIELDS(nodeTypeName) \
      45                 :             :     nodeTypeName *local_node = makeNode(nodeTypeName)
      46                 :             : 
      47                 :             : /* And a few guys need only the pg_strtok support fields */
      48                 :             : #define READ_TEMP_LOCALS()  \
      49                 :             :     const char *token;      \
      50                 :             :     int         length
      51                 :             : 
      52                 :             : /* ... but most need both */
      53                 :             : #define READ_LOCALS(nodeTypeName)           \
      54                 :             :     READ_LOCALS_NO_FIELDS(nodeTypeName);    \
      55                 :             :     READ_TEMP_LOCALS()
      56                 :             : 
      57                 :             : /* Read an integer field (anything written as ":fldname %d") */
      58                 :             : #define READ_INT_FIELD(fldname) \
      59                 :             :     token = pg_strtok(&length);     /* skip :fldname */ \
      60                 :             :     token = pg_strtok(&length);     /* get field value */ \
      61                 :             :     local_node->fldname = atoi(token)
      62                 :             : 
      63                 :             : /* Read an unsigned integer field (anything written as ":fldname %u") */
      64                 :             : #define READ_UINT_FIELD(fldname) \
      65                 :             :     token = pg_strtok(&length);     /* skip :fldname */ \
      66                 :             :     token = pg_strtok(&length);     /* get field value */ \
      67                 :             :     local_node->fldname = atoui(token)
      68                 :             : 
      69                 :             : /* Read a signed integer field (anything written using INT64_FORMAT) */
      70                 :             : #define READ_INT64_FIELD(fldname) \
      71                 :             :     token = pg_strtok(&length); /* skip :fldname */ \
      72                 :             :     token = pg_strtok(&length); /* get field value */ \
      73                 :             :     local_node->fldname = strtoi64(token, NULL, 10)
      74                 :             : 
      75                 :             : /* Read an unsigned integer field (anything written using UINT64_FORMAT) */
      76                 :             : #define READ_UINT64_FIELD(fldname) \
      77                 :             :     token = pg_strtok(&length);     /* skip :fldname */ \
      78                 :             :     token = pg_strtok(&length);     /* get field value */ \
      79                 :             :     local_node->fldname = strtou64(token, NULL, 10)
      80                 :             : 
      81                 :             : /* Read a long integer field (anything written as ":fldname %ld") */
      82                 :             : #define READ_LONG_FIELD(fldname) \
      83                 :             :     token = pg_strtok(&length);     /* skip :fldname */ \
      84                 :             :     token = pg_strtok(&length);     /* get field value */ \
      85                 :             :     local_node->fldname = atol(token)
      86                 :             : 
      87                 :             : /* Read an OID field (don't hard-wire assumption that OID is same as uint) */
      88                 :             : #define READ_OID_FIELD(fldname) \
      89                 :             :     token = pg_strtok(&length);     /* skip :fldname */ \
      90                 :             :     token = pg_strtok(&length);     /* get field value */ \
      91                 :             :     local_node->fldname = atooid(token)
      92                 :             : 
      93                 :             : /* Read a char field (ie, one ascii character) */
      94                 :             : #define READ_CHAR_FIELD(fldname) \
      95                 :             :     token = pg_strtok(&length);     /* skip :fldname */ \
      96                 :             :     token = pg_strtok(&length);     /* get field value */ \
      97                 :             :     /* avoid overhead of calling debackslash() for one char */ \
      98                 :             :     local_node->fldname = (length == 0) ? '\0' : (token[0] == '\\' ? token[1] : token[0])
      99                 :             : 
     100                 :             : /* Read an enumerated-type field that was written as an integer code */
     101                 :             : #define READ_ENUM_FIELD(fldname, enumtype) \
     102                 :             :     token = pg_strtok(&length);     /* skip :fldname */ \
     103                 :             :     token = pg_strtok(&length);     /* get field value */ \
     104                 :             :     local_node->fldname = (enumtype) atoi(token)
     105                 :             : 
     106                 :             : /* Read a float field */
     107                 :             : #define READ_FLOAT_FIELD(fldname) \
     108                 :             :     token = pg_strtok(&length);     /* skip :fldname */ \
     109                 :             :     token = pg_strtok(&length);     /* get field value */ \
     110                 :             :     local_node->fldname = atof(token)
     111                 :             : 
     112                 :             : /* Read a boolean field */
     113                 :             : #define READ_BOOL_FIELD(fldname) \
     114                 :             :     token = pg_strtok(&length);     /* skip :fldname */ \
     115                 :             :     token = pg_strtok(&length);     /* get field value */ \
     116                 :             :     local_node->fldname = strtobool(token)
     117                 :             : 
     118                 :             : /* Read a character-string field */
     119                 :             : #define READ_STRING_FIELD(fldname) \
     120                 :             :     token = pg_strtok(&length);     /* skip :fldname */ \
     121                 :             :     token = pg_strtok(&length);     /* get field value */ \
     122                 :             :     local_node->fldname = nullable_string(token, length)
     123                 :             : 
     124                 :             : /* Read a parse location field (and possibly throw away the value) */
     125                 :             : #ifdef DEBUG_NODE_TESTS_ENABLED
     126                 :             : #define READ_LOCATION_FIELD(fldname) \
     127                 :             :     token = pg_strtok(&length);     /* skip :fldname */ \
     128                 :             :     token = pg_strtok(&length);     /* get field value */ \
     129                 :             :     local_node->fldname = restore_location_fields ? atoi(token) : -1
     130                 :             : #else
     131                 :             : #define READ_LOCATION_FIELD(fldname) \
     132                 :             :     token = pg_strtok(&length);     /* skip :fldname */ \
     133                 :             :     token = pg_strtok(&length);     /* get field value */ \
     134                 :             :     (void) token;               /* in case not used elsewhere */ \
     135                 :             :     local_node->fldname = -1 /* set field to "unknown" */
     136                 :             : #endif
     137                 :             : 
     138                 :             : /* Read a Node field */
     139                 :             : #define READ_NODE_FIELD(fldname) \
     140                 :             :     token = pg_strtok(&length);     /* skip :fldname */ \
     141                 :             :     (void) token;               /* in case not used elsewhere */ \
     142                 :             :     local_node->fldname = nodeRead(NULL, 0)
     143                 :             : 
     144                 :             : /* Read a bitmapset field */
     145                 :             : #define READ_BITMAPSET_FIELD(fldname) \
     146                 :             :     token = pg_strtok(&length);     /* skip :fldname */ \
     147                 :             :     (void) token;               /* in case not used elsewhere */ \
     148                 :             :     local_node->fldname = _readBitmapset()
     149                 :             : 
     150                 :             : /* Read an attribute number array */
     151                 :             : #define READ_ATTRNUMBER_ARRAY(fldname, len) \
     152                 :             :     token = pg_strtok(&length);     /* skip :fldname */ \
     153                 :             :     local_node->fldname = readAttrNumberCols(len)
     154                 :             : 
     155                 :             : /* Read an oid array */
     156                 :             : #define READ_OID_ARRAY(fldname, len) \
     157                 :             :     token = pg_strtok(&length);     /* skip :fldname */ \
     158                 :             :     local_node->fldname = readOidCols(len)
     159                 :             : 
     160                 :             : /* Read an int array */
     161                 :             : #define READ_INT_ARRAY(fldname, len) \
     162                 :             :     token = pg_strtok(&length);     /* skip :fldname */ \
     163                 :             :     local_node->fldname = readIntCols(len)
     164                 :             : 
     165                 :             : /* Read a bool array */
     166                 :             : #define READ_BOOL_ARRAY(fldname, len) \
     167                 :             :     token = pg_strtok(&length);     /* skip :fldname */ \
     168                 :             :     local_node->fldname = readBoolCols(len)
     169                 :             : 
     170                 :             : /* Routine exit */
     171                 :             : #define READ_DONE() \
     172                 :             :     return local_node
     173                 :             : 
     174                 :             : 
     175                 :             : /*
     176                 :             :  * NOTE: use atoi() to read values written with %d, or atoui() to read
     177                 :             :  * values written with %u in outfuncs.c.  An exception is OID values,
     178                 :             :  * for which use atooid().  (As of 7.1, outfuncs.c writes OIDs as %u,
     179                 :             :  * but this will probably change in the future.)
     180                 :             :  */
     181                 :             : #define atoui(x)  ((unsigned int) strtoul((x), NULL, 10))
     182                 :             : 
     183                 :             : #define strtobool(x)  ((*(x) == 't') ? true : false)
     184                 :             : 
     185                 :             : static char *
     186                 :    12908471 : nullable_string(const char *token, int length)
     187                 :             : {
     188                 :             :     /* outToken emits <> for NULL, and pg_strtok makes that an empty string */
     189         [ +  + ]:    12908471 :     if (length == 0)
     190                 :     6710564 :         return NULL;
     191                 :             :     /* outToken emits "" for empty string */
     192   [ +  +  +  +  :     6197907 :     if (length == 2 && token[0] == '"' && token[1] == '"')
                   +  - ]
     193                 :         124 :         return pstrdup("");
     194                 :             :     /* otherwise, we must remove protective backslashes added by outToken */
     195                 :     6197783 :     return debackslash(token, length);
     196                 :             : }
     197                 :             : 
     198                 :             : 
     199                 :             : /*
     200                 :             :  * _readBitmapset
     201                 :             :  *
     202                 :             :  * Note: this code is used in contexts where we know that a Bitmapset
     203                 :             :  * is expected.  There is equivalent code in nodeRead() that can read a
     204                 :             :  * Bitmapset when we come across one in other contexts.
     205                 :             :  */
     206                 :             : static Bitmapset *
     207                 :    14178662 : _readBitmapset(void)
     208                 :             : {
     209                 :    14178662 :     Bitmapset  *result = NULL;
     210                 :             : 
     211                 :             :     READ_TEMP_LOCALS();
     212                 :             : 
     213                 :    14178662 :     token = pg_strtok(&length);
     214         [ -  + ]:    14178662 :     if (token == NULL)
     215         [ #  # ]:           0 :         elog(ERROR, "incomplete Bitmapset structure");
     216   [ +  -  -  + ]:    14178662 :     if (length != 1 || token[0] != '(')
     217         [ #  # ]:           0 :         elog(ERROR, "unrecognized token: \"%.*s\"", length, token);
     218                 :             : 
     219                 :    14178662 :     token = pg_strtok(&length);
     220         [ -  + ]:    14178662 :     if (token == NULL)
     221         [ #  # ]:           0 :         elog(ERROR, "incomplete Bitmapset structure");
     222   [ +  -  -  + ]:    14178662 :     if (length != 1 || token[0] != 'b')
     223         [ #  # ]:           0 :         elog(ERROR, "unrecognized token: \"%.*s\"", length, token);
     224                 :             : 
     225                 :             :     for (;;)
     226                 :     3948166 :     {
     227                 :             :         int         val;
     228                 :             :         char       *endptr;
     229                 :             : 
     230                 :    18126828 :         token = pg_strtok(&length);
     231         [ -  + ]:    18126828 :         if (token == NULL)
     232         [ #  # ]:           0 :             elog(ERROR, "unterminated Bitmapset structure");
     233   [ +  +  +  + ]:    18126828 :         if (length == 1 && token[0] == ')')
     234                 :    14178662 :             break;
     235                 :     3948166 :         val = (int) strtol(token, &endptr, 10);
     236         [ -  + ]:     3948166 :         if (endptr != token + length)
     237         [ #  # ]:           0 :             elog(ERROR, "unrecognized integer: \"%.*s\"", length, token);
     238                 :     3948166 :         result = bms_add_member(result, val);
     239                 :             :     }
     240                 :             : 
     241                 :    14178662 :     return result;
     242                 :             : }
     243                 :             : 
     244                 :             : /*
     245                 :             :  * We export this function for use by extensions that define extensible nodes.
     246                 :             :  * That's somewhat historical, though, because calling nodeRead() will work.
     247                 :             :  */
     248                 :             : Bitmapset *
     249                 :           0 : readBitmapset(void)
     250                 :             : {
     251                 :           0 :     return _readBitmapset();
     252                 :             : }
     253                 :             : 
     254                 :             : #include "readfuncs.funcs.c"
     255                 :             : 
     256                 :             : 
     257                 :             : /*
     258                 :             :  * Support functions for nodes with custom_read_write attribute or
     259                 :             :  * special_read_write attribute
     260                 :             :  */
     261                 :             : 
     262                 :             : static Const *
     263                 :     2121991 : _readConst(void)
     264                 :             : {
     265                 :     2121991 :     READ_LOCALS(Const);
     266                 :             : 
     267                 :     2121991 :     READ_OID_FIELD(consttype);
     268                 :     2121991 :     READ_INT_FIELD(consttypmod);
     269                 :     2121991 :     READ_OID_FIELD(constcollid);
     270                 :     2121991 :     READ_INT_FIELD(constlen);
     271                 :     2121991 :     READ_BOOL_FIELD(constbyval);
     272                 :     2121991 :     READ_BOOL_FIELD(constisnull);
     273         [ +  + ]:     2121991 :     READ_LOCATION_FIELD(location);
     274                 :             : 
     275                 :     2121991 :     token = pg_strtok(&length); /* skip :constvalue */
     276         [ +  + ]:     2121991 :     if (local_node->constisnull)
     277                 :      192616 :         token = pg_strtok(&length); /* skip "<>" */
     278                 :             :     else
     279                 :     1929375 :         local_node->constvalue = readDatum(local_node->constbyval);
     280                 :             : 
     281                 :     2121991 :     READ_DONE();
     282                 :             : }
     283                 :             : 
     284                 :             : static BoolExpr *
     285                 :      289016 : _readBoolExpr(void)
     286                 :             : {
     287                 :      289016 :     READ_LOCALS(BoolExpr);
     288                 :             : 
     289                 :             :     /* do-it-yourself enum representation */
     290                 :      289016 :     token = pg_strtok(&length); /* skip :boolop */
     291                 :      289016 :     token = pg_strtok(&length); /* get field value */
     292   [ +  +  +  + ]:      289016 :     if (length == 3 && strncmp(token, "and", 3) == 0)
     293                 :      203664 :         local_node->boolop = AND_EXPR;
     294   [ +  +  +  - ]:       85352 :     else if (length == 2 && strncmp(token, "or", 2) == 0)
     295                 :       39835 :         local_node->boolop = OR_EXPR;
     296   [ +  -  +  - ]:       45517 :     else if (length == 3 && strncmp(token, "not", 3) == 0)
     297                 :       45517 :         local_node->boolop = NOT_EXPR;
     298                 :             :     else
     299         [ #  # ]:           0 :         elog(ERROR, "unrecognized boolop \"%.*s\"", length, token);
     300                 :             : 
     301                 :      289016 :     READ_NODE_FIELD(args);
     302         [ +  + ]:      289016 :     READ_LOCATION_FIELD(location);
     303                 :             : 
     304                 :      289016 :     READ_DONE();
     305                 :             : }
     306                 :             : 
     307                 :             : static A_Const *
     308                 :      941799 : _readA_Const(void)
     309                 :             : {
     310                 :      941799 :     READ_LOCALS(A_Const);
     311                 :             : 
     312                 :             :     /* We expect either NULL or :val here */
     313                 :      941799 :     token = pg_strtok(&length);
     314   [ +  -  +  + ]:      941799 :     if (length == 4 && strncmp(token, "NULL", 4) == 0)
     315                 :       55133 :         local_node->isnull = true;
     316                 :             :     else
     317                 :             :     {
     318                 :      886666 :         union ValUnion *tmp = nodeRead(NULL, 0);
     319                 :             : 
     320                 :             :         /* To forestall valgrind complaints, copy only the valid data */
     321   [ +  +  +  +  :      886666 :         switch (nodeTag(tmp))
                   +  - ]
     322                 :             :         {
     323                 :      292159 :             case T_Integer:
     324                 :      292159 :                 memcpy(&local_node->val, tmp, sizeof(Integer));
     325                 :      292159 :                 break;
     326                 :        8056 :             case T_Float:
     327                 :        8056 :                 memcpy(&local_node->val, tmp, sizeof(Float));
     328                 :        8056 :                 break;
     329                 :       39854 :             case T_Boolean:
     330                 :       39854 :                 memcpy(&local_node->val, tmp, sizeof(Boolean));
     331                 :       39854 :                 break;
     332                 :      543870 :             case T_String:
     333                 :      543870 :                 memcpy(&local_node->val, tmp, sizeof(String));
     334                 :      543870 :                 break;
     335                 :        2727 :             case T_BitString:
     336                 :        2727 :                 memcpy(&local_node->val, tmp, sizeof(BitString));
     337                 :        2727 :                 break;
     338                 :           0 :             default:
     339         [ #  # ]:           0 :                 elog(ERROR, "unrecognized node type: %d",
     340                 :             :                      (int) nodeTag(tmp));
     341                 :             :                 break;
     342                 :             :         }
     343                 :             :     }
     344                 :             : 
     345         [ +  - ]:      941799 :     READ_LOCATION_FIELD(location);
     346                 :             : 
     347                 :      941799 :     READ_DONE();
     348                 :             : }
     349                 :             : 
     350                 :             : static RangeTblEntry *
     351                 :     1202033 : _readRangeTblEntry(void)
     352                 :             : {
     353                 :     1202033 :     READ_LOCALS(RangeTblEntry);
     354                 :             : 
     355                 :     1202033 :     READ_NODE_FIELD(alias);
     356                 :     1202033 :     READ_NODE_FIELD(eref);
     357                 :     1202033 :     READ_ENUM_FIELD(rtekind, RTEKind);
     358                 :             : 
     359   [ +  +  +  +  :     1202033 :     switch (local_node->rtekind)
          +  +  +  +  +  
                +  +  - ]
     360                 :             :     {
     361                 :      716141 :         case RTE_RELATION:
     362                 :      716141 :             READ_OID_FIELD(relid);
     363                 :      716141 :             READ_BOOL_FIELD(inh);
     364   [ +  -  -  + ]:      716141 :             READ_CHAR_FIELD(relkind);
     365                 :      716141 :             READ_INT_FIELD(rellockmode);
     366                 :      716141 :             READ_UINT_FIELD(perminfoindex);
     367                 :      716141 :             READ_NODE_FIELD(tablesample);
     368                 :      716141 :             break;
     369                 :      115838 :         case RTE_SUBQUERY:
     370                 :      115838 :             READ_NODE_FIELD(subquery);
     371                 :      115838 :             READ_BOOL_FIELD(security_barrier);
     372                 :             :             /* we re-use these RELATION fields, too: */
     373                 :      115838 :             READ_OID_FIELD(relid);
     374                 :      115838 :             READ_BOOL_FIELD(inh);
     375   [ +  +  -  + ]:      115838 :             READ_CHAR_FIELD(relkind);
     376                 :      115838 :             READ_INT_FIELD(rellockmode);
     377                 :      115838 :             READ_UINT_FIELD(perminfoindex);
     378                 :      115838 :             break;
     379                 :      143637 :         case RTE_JOIN:
     380                 :      143637 :             READ_ENUM_FIELD(jointype, JoinType);
     381                 :      143637 :             READ_INT_FIELD(joinmergedcols);
     382                 :      143637 :             READ_NODE_FIELD(joinaliasvars);
     383                 :      143637 :             READ_NODE_FIELD(joinleftcols);
     384                 :      143637 :             READ_NODE_FIELD(joinrightcols);
     385                 :      143637 :             READ_NODE_FIELD(join_using_alias);
     386                 :      143637 :             break;
     387                 :       69421 :         case RTE_FUNCTION:
     388                 :       69421 :             READ_NODE_FIELD(functions);
     389                 :       69421 :             READ_BOOL_FIELD(funcordinality);
     390                 :       69421 :             break;
     391                 :         982 :         case RTE_TABLEFUNC:
     392                 :         982 :             READ_NODE_FIELD(tablefunc);
     393                 :             :             /* The RTE must have a copy of the column type info, if any */
     394         [ +  + ]:         982 :             if (local_node->tablefunc)
     395                 :             :             {
     396                 :         566 :                 TableFunc  *tf = local_node->tablefunc;
     397                 :             : 
     398                 :         566 :                 local_node->coltypes = tf->coltypes;
     399                 :         566 :                 local_node->coltypmods = tf->coltypmods;
     400                 :         566 :                 local_node->colcollations = tf->colcollations;
     401                 :             :             }
     402                 :         982 :             break;
     403                 :       15629 :         case RTE_VALUES:
     404                 :       15629 :             READ_NODE_FIELD(values_lists);
     405                 :       15629 :             READ_NODE_FIELD(coltypes);
     406                 :       15629 :             READ_NODE_FIELD(coltypmods);
     407                 :       15629 :             READ_NODE_FIELD(colcollations);
     408                 :       15629 :             break;
     409                 :        7786 :         case RTE_CTE:
     410                 :        7786 :             READ_STRING_FIELD(ctename);
     411                 :        7786 :             READ_UINT_FIELD(ctelevelsup);
     412                 :        7786 :             READ_BOOL_FIELD(self_reference);
     413                 :        7786 :             READ_NODE_FIELD(coltypes);
     414                 :        7786 :             READ_NODE_FIELD(coltypmods);
     415                 :        7786 :             READ_NODE_FIELD(colcollations);
     416                 :        7786 :             break;
     417                 :         692 :         case RTE_NAMEDTUPLESTORE:
     418                 :         692 :             READ_STRING_FIELD(enrname);
     419                 :         692 :             READ_FLOAT_FIELD(enrtuples);
     420                 :         692 :             READ_NODE_FIELD(coltypes);
     421                 :         692 :             READ_NODE_FIELD(coltypmods);
     422                 :         692 :             READ_NODE_FIELD(colcollations);
     423                 :             :             /* we re-use these RELATION fields, too: */
     424                 :         692 :             READ_OID_FIELD(relid);
     425                 :         692 :             break;
     426                 :          85 :         case RTE_GRAPH_TABLE:
     427                 :          85 :             READ_NODE_FIELD(graph_pattern);
     428                 :          85 :             READ_NODE_FIELD(graph_table_columns);
     429                 :             :             /* we re-use these RELATION fields, too: */
     430                 :          85 :             READ_OID_FIELD(relid);
     431   [ +  -  -  + ]:          85 :             READ_CHAR_FIELD(relkind);
     432                 :          85 :             READ_INT_FIELD(rellockmode);
     433                 :          85 :             READ_UINT_FIELD(perminfoindex);
     434                 :          85 :             break;
     435                 :      123631 :         case RTE_RESULT:
     436                 :             :             /* no extra fields */
     437                 :      123631 :             break;
     438                 :        8191 :         case RTE_GROUP:
     439                 :        8191 :             READ_NODE_FIELD(groupexprs);
     440                 :        8191 :             break;
     441                 :           0 :         default:
     442         [ #  # ]:           0 :             elog(ERROR, "unrecognized RTE kind: %d",
     443                 :             :                  (int) local_node->rtekind);
     444                 :             :             break;
     445                 :             :     }
     446                 :             : 
     447                 :     1202033 :     READ_BOOL_FIELD(lateral);
     448                 :     1202033 :     READ_BOOL_FIELD(inFromCl);
     449                 :     1202033 :     READ_NODE_FIELD(securityQuals);
     450                 :             : 
     451                 :     1202033 :     READ_DONE();
     452                 :             : }
     453                 :             : 
     454                 :             : static A_Expr *
     455                 :      426466 : _readA_Expr(void)
     456                 :             : {
     457                 :      426466 :     READ_LOCALS(A_Expr);
     458                 :             : 
     459                 :      426466 :     token = pg_strtok(&length);
     460                 :             : 
     461   [ +  +  +  + ]:      426466 :     if (length == 3 && strncmp(token, "ANY", 3) == 0)
     462                 :             :     {
     463                 :       10782 :         local_node->kind = AEXPR_OP_ANY;
     464                 :       10782 :         READ_NODE_FIELD(name);
     465                 :             :     }
     466   [ +  +  +  - ]:      415684 :     else if (length == 3 && strncmp(token, "ALL", 3) == 0)
     467                 :             :     {
     468                 :          96 :         local_node->kind = AEXPR_OP_ALL;
     469                 :          96 :         READ_NODE_FIELD(name);
     470                 :             :     }
     471   [ +  +  +  - ]:      415588 :     else if (length == 8 && strncmp(token, "DISTINCT", 8) == 0)
     472                 :             :     {
     473                 :         646 :         local_node->kind = AEXPR_DISTINCT;
     474                 :         646 :         READ_NODE_FIELD(name);
     475                 :             :     }
     476   [ +  +  +  - ]:      414942 :     else if (length == 12 && strncmp(token, "NOT_DISTINCT", 12) == 0)
     477                 :             :     {
     478                 :          88 :         local_node->kind = AEXPR_NOT_DISTINCT;
     479                 :          88 :         READ_NODE_FIELD(name);
     480                 :             :     }
     481   [ +  +  +  - ]:      414854 :     else if (length == 6 && strncmp(token, "NULLIF", 6) == 0)
     482                 :             :     {
     483                 :         589 :         local_node->kind = AEXPR_NULLIF;
     484                 :         589 :         READ_NODE_FIELD(name);
     485                 :             :     }
     486   [ +  +  +  - ]:      414265 :     else if (length == 2 && strncmp(token, "IN", 2) == 0)
     487                 :             :     {
     488                 :       16368 :         local_node->kind = AEXPR_IN;
     489                 :       16368 :         READ_NODE_FIELD(name);
     490                 :             :     }
     491   [ +  +  +  - ]:      397897 :     else if (length == 4 && strncmp(token, "LIKE", 4) == 0)
     492                 :             :     {
     493                 :        1545 :         local_node->kind = AEXPR_LIKE;
     494                 :        1545 :         READ_NODE_FIELD(name);
     495                 :             :     }
     496   [ +  +  +  + ]:      396352 :     else if (length == 5 && strncmp(token, "ILIKE", 5) == 0)
     497                 :             :     {
     498                 :         132 :         local_node->kind = AEXPR_ILIKE;
     499                 :         132 :         READ_NODE_FIELD(name);
     500                 :             :     }
     501   [ +  +  +  + ]:      396220 :     else if (length == 7 && strncmp(token, "SIMILAR", 7) == 0)
     502                 :             :     {
     503                 :          82 :         local_node->kind = AEXPR_SIMILAR;
     504                 :          82 :         READ_NODE_FIELD(name);
     505                 :             :     }
     506   [ +  +  +  - ]:      396138 :     else if (length == 7 && strncmp(token, "BETWEEN", 7) == 0)
     507                 :             :     {
     508                 :         368 :         local_node->kind = AEXPR_BETWEEN;
     509                 :         368 :         READ_NODE_FIELD(name);
     510                 :             :     }
     511   [ +  +  +  + ]:      395770 :     else if (length == 11 && strncmp(token, "NOT_BETWEEN", 11) == 0)
     512                 :             :     {
     513                 :           8 :         local_node->kind = AEXPR_NOT_BETWEEN;
     514                 :           8 :         READ_NODE_FIELD(name);
     515                 :             :     }
     516   [ +  +  +  - ]:      395762 :     else if (length == 11 && strncmp(token, "BETWEEN_SYM", 11) == 0)
     517                 :             :     {
     518                 :           8 :         local_node->kind = AEXPR_BETWEEN_SYM;
     519                 :           8 :         READ_NODE_FIELD(name);
     520                 :             :     }
     521   [ +  +  +  - ]:      395754 :     else if (length == 15 && strncmp(token, "NOT_BETWEEN_SYM", 15) == 0)
     522                 :             :     {
     523                 :           8 :         local_node->kind = AEXPR_NOT_BETWEEN_SYM;
     524                 :           8 :         READ_NODE_FIELD(name);
     525                 :             :     }
     526   [ +  -  +  - ]:      395746 :     else if (length == 5 && strncmp(token, ":name", 5) == 0)
     527                 :             :     {
     528                 :      395746 :         local_node->kind = AEXPR_OP;
     529                 :      395746 :         local_node->name = nodeRead(NULL, 0);
     530                 :             :     }
     531                 :             :     else
     532         [ #  # ]:           0 :         elog(ERROR, "unrecognized A_Expr kind: \"%.*s\"", length, token);
     533                 :             : 
     534                 :      426466 :     READ_NODE_FIELD(lexpr);
     535                 :      426466 :     READ_NODE_FIELD(rexpr);
     536         [ +  - ]:      426466 :     READ_LOCATION_FIELD(rexpr_list_start);
     537         [ +  - ]:      426466 :     READ_LOCATION_FIELD(rexpr_list_end);
     538         [ +  - ]:      426466 :     READ_LOCATION_FIELD(location);
     539                 :             : 
     540                 :      426466 :     READ_DONE();
     541                 :             : }
     542                 :             : 
     543                 :             : static ExtensibleNode *
     544                 :           0 : _readExtensibleNode(void)
     545                 :             : {
     546                 :             :     const ExtensibleNodeMethods *methods;
     547                 :             :     ExtensibleNode *local_node;
     548                 :             :     const char *extnodename;
     549                 :             : 
     550                 :             :     READ_TEMP_LOCALS();
     551                 :             : 
     552                 :           0 :     token = pg_strtok(&length); /* skip :extnodename */
     553                 :           0 :     token = pg_strtok(&length); /* get extnodename */
     554                 :             : 
     555                 :           0 :     extnodename = nullable_string(token, length);
     556         [ #  # ]:           0 :     if (!extnodename)
     557         [ #  # ]:           0 :         elog(ERROR, "extnodename has to be supplied");
     558                 :           0 :     methods = GetExtensibleNodeMethods(extnodename, false);
     559                 :             : 
     560                 :           0 :     local_node = (ExtensibleNode *) newNode(methods->node_size,
     561                 :             :                                             T_ExtensibleNode);
     562                 :           0 :     local_node->extnodename = extnodename;
     563                 :             : 
     564                 :             :     /* deserialize the private fields */
     565                 :           0 :     methods->nodeRead(local_node);
     566                 :             : 
     567                 :           0 :     READ_DONE();
     568                 :             : }
     569                 :             : 
     570                 :             : 
     571                 :             : /*
     572                 :             :  * parseNodeString
     573                 :             :  *
     574                 :             :  * Given a character string representing a node tree, parseNodeString creates
     575                 :             :  * the internal node structure.
     576                 :             :  *
     577                 :             :  * The string to be read must already have been loaded into pg_strtok().
     578                 :             :  */
     579                 :             : Node *
     580                 :    34099627 : parseNodeString(void)
     581                 :             : {
     582                 :             :     READ_TEMP_LOCALS();
     583                 :             : 
     584                 :             :     /* Guard against stack overflow due to overly complex expressions */
     585                 :    34099627 :     check_stack_depth();
     586                 :             : 
     587                 :    34099627 :     token = pg_strtok(&length);
     588                 :             : 
     589                 :             : #define MATCH(tokname, namelen) \
     590                 :             :     (length == namelen && memcmp(token, tokname, namelen) == 0)
     591                 :             : 
     592                 :             : #include "readfuncs.switch.c"
     593                 :             : 
     594         [ #  # ]:           0 :     elog(ERROR, "badly formatted node string \"%.32s\"...", token);
     595                 :             :     return NULL;                /* keep compiler quiet */
     596                 :             : }
     597                 :             : 
     598                 :             : 
     599                 :             : /*
     600                 :             :  * readDatum
     601                 :             :  *
     602                 :             :  * Given a string representation of a constant, recreate the appropriate
     603                 :             :  * Datum.  The string representation embeds length info, but not byValue,
     604                 :             :  * so we must be told that.
     605                 :             :  */
     606                 :             : Datum
     607                 :     1929375 : readDatum(bool typbyval)
     608                 :             : {
     609                 :             :     Size        length;
     610                 :             :     int         tokenLength;
     611                 :             :     const char *token;
     612                 :             :     Datum       res;
     613                 :             :     char       *s;
     614                 :             : 
     615                 :             :     /*
     616                 :             :      * read the actual length of the value
     617                 :             :      */
     618                 :     1929375 :     token = pg_strtok(&tokenLength);
     619                 :     1929375 :     length = atoui(token);
     620                 :             : 
     621                 :     1929375 :     token = pg_strtok(&tokenLength);    /* read the '[' */
     622   [ +  -  -  + ]:     1929375 :     if (token == NULL || token[0] != '[')
     623   [ #  #  #  # ]:           0 :         elog(ERROR, "expected \"[\" to start datum, but got \"%s\"; length = %zu",
     624                 :             :              token ? token : "[NULL]", length);
     625                 :             : 
     626         [ +  + ]:     1929375 :     if (typbyval)
     627                 :             :     {
     628         [ -  + ]:     1288479 :         if (length > (Size) sizeof(Datum))
     629         [ #  # ]:           0 :             elog(ERROR, "byval datum but length = %zu", length);
     630                 :     1288479 :         res = (Datum) 0;
     631                 :     1288479 :         s = (char *) (&res);
     632         [ +  + ]:    11596311 :         for (Size i = 0; i < (Size) sizeof(Datum); i++)
     633                 :             :         {
     634                 :    10307832 :             token = pg_strtok(&tokenLength);
     635                 :    10307832 :             s[i] = (char) atoi(token);
     636                 :             :         }
     637                 :             :     }
     638         [ -  + ]:      640896 :     else if (length <= 0)
     639                 :           0 :         res = (Datum) 0;
     640                 :             :     else
     641                 :             :     {
     642                 :      640896 :         s = (char *) palloc(length);
     643         [ +  + ]:    79964480 :         for (Size i = 0; i < length; i++)
     644                 :             :         {
     645                 :    79323584 :             token = pg_strtok(&tokenLength);
     646                 :    79323584 :             s[i] = (char) atoi(token);
     647                 :             :         }
     648                 :      640896 :         res = PointerGetDatum(s);
     649                 :             :     }
     650                 :             : 
     651                 :     1929375 :     token = pg_strtok(&tokenLength);    /* read the ']' */
     652   [ +  -  -  + ]:     1929375 :     if (token == NULL || token[0] != ']')
     653   [ #  #  #  # ]:           0 :         elog(ERROR, "expected \"]\" to end datum, but got \"%s\"; length = %zu",
     654                 :             :              token ? token : "[NULL]", length);
     655                 :             : 
     656                 :     1929375 :     return res;
     657                 :             : }
     658                 :             : 
     659                 :             : /*
     660                 :             :  * common implementation for scalar-array-reading functions
     661                 :             :  *
     662                 :             :  * The data format is either "<>" for a NULL pointer (in which case numCols
     663                 :             :  * is ignored) or "(item item item)" where the number of items must equal
     664                 :             :  * numCols.  The convfunc must be okay with stopping at whitespace or a
     665                 :             :  * right parenthesis, since pg_strtok won't null-terminate the token.
     666                 :             :  */
     667                 :             : #define READ_SCALAR_ARRAY(fnname, datatype, convfunc) \
     668                 :             : datatype * \
     669                 :             : fnname(int numCols) \
     670                 :             : { \
     671                 :             :     datatype   *vals; \
     672                 :             :     READ_TEMP_LOCALS(); \
     673                 :             :     token = pg_strtok(&length); \
     674                 :             :     if (token == NULL) \
     675                 :             :         elog(ERROR, "incomplete scalar array"); \
     676                 :             :     if (length == 0) \
     677                 :             :         return NULL;            /* it was "<>", so return NULL pointer */ \
     678                 :             :     if (length != 1 || token[0] != '(') \
     679                 :             :         elog(ERROR, "unrecognized token: \"%.*s\"", length, token); \
     680                 :             :     vals = (datatype *) palloc(numCols * sizeof(datatype)); \
     681                 :             :     for (int i = 0; i < numCols; i++) \
     682                 :             :     { \
     683                 :             :         token = pg_strtok(&length); \
     684                 :             :         if (token == NULL || token[0] == ')') \
     685                 :             :             elog(ERROR, "incomplete scalar array"); \
     686                 :             :         vals[i] = convfunc(token); \
     687                 :             :     } \
     688                 :             :     token = pg_strtok(&length); \
     689                 :             :     if (token == NULL || length != 1 || token[0] != ')') \
     690                 :             :         elog(ERROR, "incomplete scalar array"); \
     691                 :             :     return vals; \
     692                 :             : }
     693                 :             : 
     694                 :             : /*
     695                 :             :  * Note: these functions are exported in nodes.h for possible use by
     696                 :             :  * extensions, so don't mess too much with their names or API.
     697                 :             :  */
     698   [ -  +  -  -  :      359623 : READ_SCALAR_ARRAY(readAttrNumberCols, int16, atoi)
          +  +  +  -  -  
          +  -  -  +  -  
          -  +  -  -  +  
          +  +  -  +  -  
             -  +  -  - ]
     699   [ -  +  -  -  :      443307 : READ_SCALAR_ARRAY(readOidCols, Oid, atooid)
          +  +  +  -  -  
          +  -  -  +  -  
          -  +  -  -  +  
          +  +  -  +  -  
             -  +  -  - ]
     700                 :             : /* outfuncs.c has writeIndexCols, but we don't yet need that here */
     701                 :             : /* READ_SCALAR_ARRAY(readIndexCols, Index, atoui) */
     702   [ -  +  -  -  :       10905 : READ_SCALAR_ARRAY(readIntCols, int, atoi)
          -  +  +  -  -  
          +  -  -  +  -  
          -  +  -  -  +  
          +  +  -  +  -  
             -  +  -  - ]
     703   [ -  +  -  -  :      161990 : READ_SCALAR_ARRAY(readBoolCols, bool, strtobool)
          +  +  +  -  -  
          +  -  -  +  -  
          -  +  -  -  +  
          +  +  -  +  -  
             -  +  -  - ]
        

Generated by: LCOV version 2.0-1