LCOV - code coverage report
Current view: top level - src/backend/nodes - readfuncs.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 329 362 90.9 %
Date: 2023-11-29 05:10:53 Functions: 14 16 87.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * readfuncs.c
       4             :  *    Reader 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/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             :  *    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 <math.h>
      30             : 
      31             : #include "miscadmin.h"
      32             : #include "nodes/bitmapset.h"
      33             : #include "nodes/readfuncs.h"
      34             : 
      35             : 
      36             : /*
      37             :  * Macros to simplify reading of different kinds of fields.  Use these
      38             :  * wherever possible to reduce the chance for silly typos.  Note that these
      39             :  * hard-wire conventions about the names of the local variables in a Read
      40             :  * routine.
      41             :  */
      42             : 
      43             : /* Macros for declaring appropriate local variables */
      44             : 
      45             : /* A few guys need only local_node */
      46             : #define READ_LOCALS_NO_FIELDS(nodeTypeName) \
      47             :     nodeTypeName *local_node = makeNode(nodeTypeName)
      48             : 
      49             : /* And a few guys need only the pg_strtok support fields */
      50             : #define READ_TEMP_LOCALS()  \
      51             :     const char *token;      \
      52             :     int         length
      53             : 
      54             : /* ... but most need both */
      55             : #define READ_LOCALS(nodeTypeName)           \
      56             :     READ_LOCALS_NO_FIELDS(nodeTypeName);    \
      57             :     READ_TEMP_LOCALS()
      58             : 
      59             : /* Read an integer field (anything written as ":fldname %d") */
      60             : #define READ_INT_FIELD(fldname) \
      61             :     token = pg_strtok(&length);     /* skip :fldname */ \
      62             :     token = pg_strtok(&length);     /* get field value */ \
      63             :     local_node->fldname = atoi(token)
      64             : 
      65             : /* Read an unsigned integer field (anything written as ":fldname %u") */
      66             : #define READ_UINT_FIELD(fldname) \
      67             :     token = pg_strtok(&length);     /* skip :fldname */ \
      68             :     token = pg_strtok(&length);     /* get field value */ \
      69             :     local_node->fldname = atoui(token)
      70             : 
      71             : /* Read an unsigned integer field (anything written using UINT64_FORMAT) */
      72             : #define READ_UINT64_FIELD(fldname) \
      73             :     token = pg_strtok(&length);     /* skip :fldname */ \
      74             :     token = pg_strtok(&length);     /* get field value */ \
      75             :     local_node->fldname = strtou64(token, NULL, 10)
      76             : 
      77             : /* Read a long integer field (anything written as ":fldname %ld") */
      78             : #define READ_LONG_FIELD(fldname) \
      79             :     token = pg_strtok(&length);     /* skip :fldname */ \
      80             :     token = pg_strtok(&length);     /* get field value */ \
      81             :     local_node->fldname = atol(token)
      82             : 
      83             : /* Read an OID field (don't hard-wire assumption that OID is same as uint) */
      84             : #define READ_OID_FIELD(fldname) \
      85             :     token = pg_strtok(&length);     /* skip :fldname */ \
      86             :     token = pg_strtok(&length);     /* get field value */ \
      87             :     local_node->fldname = atooid(token)
      88             : 
      89             : /* Read a char field (ie, one ascii character) */
      90             : #define READ_CHAR_FIELD(fldname) \
      91             :     token = pg_strtok(&length);     /* skip :fldname */ \
      92             :     token = pg_strtok(&length);     /* get field value */ \
      93             :     /* avoid overhead of calling debackslash() for one char */ \
      94             :     local_node->fldname = (length == 0) ? '\0' : (token[0] == '\\' ? token[1] : token[0])
      95             : 
      96             : /* Read an enumerated-type field that was written as an integer code */
      97             : #define READ_ENUM_FIELD(fldname, enumtype) \
      98             :     token = pg_strtok(&length);     /* skip :fldname */ \
      99             :     token = pg_strtok(&length);     /* get field value */ \
     100             :     local_node->fldname = (enumtype) atoi(token)
     101             : 
     102             : /* Read a float field */
     103             : #define READ_FLOAT_FIELD(fldname) \
     104             :     token = pg_strtok(&length);     /* skip :fldname */ \
     105             :     token = pg_strtok(&length);     /* get field value */ \
     106             :     local_node->fldname = atof(token)
     107             : 
     108             : /* Read a boolean field */
     109             : #define READ_BOOL_FIELD(fldname) \
     110             :     token = pg_strtok(&length);     /* skip :fldname */ \
     111             :     token = pg_strtok(&length);     /* get field value */ \
     112             :     local_node->fldname = strtobool(token)
     113             : 
     114             : /* Read a character-string field */
     115             : #define READ_STRING_FIELD(fldname) \
     116             :     token = pg_strtok(&length);     /* skip :fldname */ \
     117             :     token = pg_strtok(&length);     /* get field value */ \
     118             :     local_node->fldname = nullable_string(token, length)
     119             : 
     120             : /* Read a parse location field (and possibly throw away the value) */
     121             : #ifdef WRITE_READ_PARSE_PLAN_TREES
     122             : #define READ_LOCATION_FIELD(fldname) \
     123             :     token = pg_strtok(&length);     /* skip :fldname */ \
     124             :     token = pg_strtok(&length);     /* get field value */ \
     125             :     local_node->fldname = restore_location_fields ? atoi(token) : -1
     126             : #else
     127             : #define READ_LOCATION_FIELD(fldname) \
     128             :     token = pg_strtok(&length);     /* skip :fldname */ \
     129             :     token = pg_strtok(&length);     /* get field value */ \
     130             :     (void) token;               /* in case not used elsewhere */ \
     131             :     local_node->fldname = -1 /* set field to "unknown" */
     132             : #endif
     133             : 
     134             : /* Read a Node field */
     135             : #define READ_NODE_FIELD(fldname) \
     136             :     token = pg_strtok(&length);     /* skip :fldname */ \
     137             :     (void) token;               /* in case not used elsewhere */ \
     138             :     local_node->fldname = nodeRead(NULL, 0)
     139             : 
     140             : /* Read a bitmapset field */
     141             : #define READ_BITMAPSET_FIELD(fldname) \
     142             :     token = pg_strtok(&length);     /* skip :fldname */ \
     143             :     (void) token;               /* in case not used elsewhere */ \
     144             :     local_node->fldname = _readBitmapset()
     145             : 
     146             : /* Read an attribute number array */
     147             : #define READ_ATTRNUMBER_ARRAY(fldname, len) \
     148             :     token = pg_strtok(&length);     /* skip :fldname */ \
     149             :     local_node->fldname = readAttrNumberCols(len)
     150             : 
     151             : /* Read an oid array */
     152             : #define READ_OID_ARRAY(fldname, len) \
     153             :     token = pg_strtok(&length);     /* skip :fldname */ \
     154             :     local_node->fldname = readOidCols(len)
     155             : 
     156             : /* Read an int array */
     157             : #define READ_INT_ARRAY(fldname, len) \
     158             :     token = pg_strtok(&length);     /* skip :fldname */ \
     159             :     local_node->fldname = readIntCols(len)
     160             : 
     161             : /* Read a bool array */
     162             : #define READ_BOOL_ARRAY(fldname, len) \
     163             :     token = pg_strtok(&length);     /* skip :fldname */ \
     164             :     local_node->fldname = readBoolCols(len)
     165             : 
     166             : /* Routine exit */
     167             : #define READ_DONE() \
     168             :     return local_node
     169             : 
     170             : 
     171             : /*
     172             :  * NOTE: use atoi() to read values written with %d, or atoui() to read
     173             :  * values written with %u in outfuncs.c.  An exception is OID values,
     174             :  * for which use atooid().  (As of 7.1, outfuncs.c writes OIDs as %u,
     175             :  * but this will probably change in the future.)
     176             :  */
     177             : #define atoui(x)  ((unsigned int) strtoul((x), NULL, 10))
     178             : 
     179             : #define strtobool(x)  ((*(x) == 't') ? true : false)
     180             : 
     181             : static char *
     182    13054672 : nullable_string(const char *token, int length)
     183             : {
     184             :     /* outToken emits <> for NULL, and pg_strtok makes that an empty string */
     185    13054672 :     if (length == 0)
     186     6073364 :         return NULL;
     187             :     /* outToken emits "" for empty string */
     188     6981308 :     if (length == 2 && token[0] == '"' && token[1] == '"')
     189         156 :         return pstrdup("");
     190             :     /* otherwise, we must remove protective backslashes added by outToken */
     191     6981152 :     return debackslash(token, length);
     192             : }
     193             : 
     194             : 
     195             : /*
     196             :  * _readBitmapset
     197             :  *
     198             :  * Note: this code is used in contexts where we know that a Bitmapset
     199             :  * is expected.  There is equivalent code in nodeRead() that can read a
     200             :  * Bitmapset when we come across one in other contexts.
     201             :  */
     202             : static Bitmapset *
     203    15361610 : _readBitmapset(void)
     204             : {
     205    15361610 :     Bitmapset  *result = NULL;
     206             : 
     207             :     READ_TEMP_LOCALS();
     208             : 
     209    15361610 :     token = pg_strtok(&length);
     210    15361610 :     if (token == NULL)
     211           0 :         elog(ERROR, "incomplete Bitmapset structure");
     212    15361610 :     if (length != 1 || token[0] != '(')
     213           0 :         elog(ERROR, "unrecognized token: \"%.*s\"", length, token);
     214             : 
     215    15361610 :     token = pg_strtok(&length);
     216    15361610 :     if (token == NULL)
     217           0 :         elog(ERROR, "incomplete Bitmapset structure");
     218    15361610 :     if (length != 1 || token[0] != 'b')
     219           0 :         elog(ERROR, "unrecognized token: \"%.*s\"", length, token);
     220             : 
     221             :     for (;;)
     222     4165318 :     {
     223             :         int         val;
     224             :         char       *endptr;
     225             : 
     226    19526928 :         token = pg_strtok(&length);
     227    19526928 :         if (token == NULL)
     228           0 :             elog(ERROR, "unterminated Bitmapset structure");
     229    19526928 :         if (length == 1 && token[0] == ')')
     230    15361610 :             break;
     231     4165318 :         val = (int) strtol(token, &endptr, 10);
     232     4165318 :         if (endptr != token + length)
     233           0 :             elog(ERROR, "unrecognized integer: \"%.*s\"", length, token);
     234     4165318 :         result = bms_add_member(result, val);
     235             :     }
     236             : 
     237    15361610 :     return result;
     238             : }
     239             : 
     240             : /*
     241             :  * We export this function for use by extensions that define extensible nodes.
     242             :  * That's somewhat historical, though, because calling nodeRead() will work.
     243             :  */
     244             : Bitmapset *
     245           0 : readBitmapset(void)
     246             : {
     247           0 :     return _readBitmapset();
     248             : }
     249             : 
     250             : #include "readfuncs.funcs.c"
     251             : 
     252             : 
     253             : /*
     254             :  * Support functions for nodes with custom_read_write attribute or
     255             :  * special_read_write attribute
     256             :  */
     257             : 
     258             : static Const *
     259     2428866 : _readConst(void)
     260             : {
     261     2428866 :     READ_LOCALS(Const);
     262             : 
     263     2428866 :     READ_OID_FIELD(consttype);
     264     2428866 :     READ_INT_FIELD(consttypmod);
     265     2428866 :     READ_OID_FIELD(constcollid);
     266     2428866 :     READ_INT_FIELD(constlen);
     267     2428866 :     READ_BOOL_FIELD(constbyval);
     268     2428866 :     READ_BOOL_FIELD(constisnull);
     269     2428866 :     READ_LOCATION_FIELD(location);
     270             : 
     271     2428866 :     token = pg_strtok(&length); /* skip :constvalue */
     272     2428866 :     if (local_node->constisnull)
     273      192790 :         token = pg_strtok(&length); /* skip "<>" */
     274             :     else
     275     2236076 :         local_node->constvalue = readDatum(local_node->constbyval);
     276             : 
     277     2428866 :     READ_DONE();
     278             : }
     279             : 
     280             : static BoolExpr *
     281      319332 : _readBoolExpr(void)
     282             : {
     283      319332 :     READ_LOCALS(BoolExpr);
     284             : 
     285             :     /* do-it-yourself enum representation */
     286      319332 :     token = pg_strtok(&length); /* skip :boolop */
     287      319332 :     token = pg_strtok(&length); /* get field value */
     288      319332 :     if (length == 3 && strncmp(token, "and", 3) == 0)
     289      242388 :         local_node->boolop = AND_EXPR;
     290       76944 :     else if (length == 2 && strncmp(token, "or", 2) == 0)
     291       41414 :         local_node->boolop = OR_EXPR;
     292       35530 :     else if (length == 3 && strncmp(token, "not", 3) == 0)
     293       35530 :         local_node->boolop = NOT_EXPR;
     294             :     else
     295           0 :         elog(ERROR, "unrecognized boolop \"%.*s\"", length, token);
     296             : 
     297      319332 :     READ_NODE_FIELD(args);
     298      319332 :     READ_LOCATION_FIELD(location);
     299             : 
     300      319332 :     READ_DONE();
     301             : }
     302             : 
     303             : static A_Const *
     304     1152532 : _readA_Const(void)
     305             : {
     306     1152532 :     READ_LOCALS(A_Const);
     307             : 
     308             :     /* We expect either NULL or :val here */
     309     1152532 :     token = pg_strtok(&length);
     310     1152532 :     if (length == 4 && strncmp(token, "NULL", 4) == 0)
     311       60192 :         local_node->isnull = true;
     312             :     else
     313             :     {
     314     1092340 :         union ValUnion *tmp = nodeRead(NULL, 0);
     315             : 
     316             :         /* To forestall valgrind complaints, copy only the valid data */
     317     1092340 :         switch (nodeTag(tmp))
     318             :         {
     319      440714 :             case T_Integer:
     320      440714 :                 memcpy(&local_node->val, tmp, sizeof(Integer));
     321      440714 :                 break;
     322       10720 :             case T_Float:
     323       10720 :                 memcpy(&local_node->val, tmp, sizeof(Float));
     324       10720 :                 break;
     325       53450 :             case T_Boolean:
     326       53450 :                 memcpy(&local_node->val, tmp, sizeof(Boolean));
     327       53450 :                 break;
     328      583412 :             case T_String:
     329      583412 :                 memcpy(&local_node->val, tmp, sizeof(String));
     330      583412 :                 break;
     331        4044 :             case T_BitString:
     332        4044 :                 memcpy(&local_node->val, tmp, sizeof(BitString));
     333        4044 :                 break;
     334           0 :             default:
     335           0 :                 elog(ERROR, "unrecognized node type: %d",
     336             :                      (int) nodeTag(tmp));
     337             :                 break;
     338             :         }
     339             :     }
     340             : 
     341     1152532 :     READ_LOCATION_FIELD(location);
     342             : 
     343     1152532 :     READ_DONE();
     344             : }
     345             : 
     346             : /*
     347             :  * _readConstraint
     348             :  */
     349             : static Constraint *
     350       53794 : _readConstraint(void)
     351             : {
     352       53794 :     READ_LOCALS(Constraint);
     353             : 
     354       53794 :     READ_STRING_FIELD(conname);
     355       53794 :     READ_BOOL_FIELD(deferrable);
     356       53794 :     READ_BOOL_FIELD(initdeferred);
     357       53794 :     READ_LOCATION_FIELD(location);
     358             : 
     359       53794 :     token = pg_strtok(&length); /* skip :contype */
     360       53794 :     token = pg_strtok(&length); /* get field value */
     361       53794 :     if (length == 4 && strncmp(token, "NULL", 4) == 0)
     362          48 :         local_node->contype = CONSTR_NULL;
     363       53746 :     else if (length == 8 && strncmp(token, "NOT_NULL", 8) == 0)
     364       11604 :         local_node->contype = CONSTR_NOTNULL;
     365       42142 :     else if (length == 7 && strncmp(token, "DEFAULT", 7) == 0)
     366        3152 :         local_node->contype = CONSTR_DEFAULT;
     367       38990 :     else if (length == 8 && strncmp(token, "IDENTITY", 8) == 0)
     368         664 :         local_node->contype = CONSTR_IDENTITY;
     369       38326 :     else if (length == 9 && strncmp(token, "GENERATED", 9) == 0)
     370        1690 :         local_node->contype = CONSTR_GENERATED;
     371       36636 :     else if (length == 5 && strncmp(token, "CHECK", 5) == 0)
     372        3688 :         local_node->contype = CONSTR_CHECK;
     373       32948 :     else if (length == 11 && strncmp(token, "PRIMARY_KEY", 11) == 0)
     374       20790 :         local_node->contype = CONSTR_PRIMARY;
     375       12158 :     else if (length == 6 && strncmp(token, "UNIQUE", 6) == 0)
     376        7218 :         local_node->contype = CONSTR_UNIQUE;
     377        4940 :     else if (length == 9 && strncmp(token, "EXCLUSION", 9) == 0)
     378         420 :         local_node->contype = CONSTR_EXCLUSION;
     379        4520 :     else if (length == 11 && strncmp(token, "FOREIGN_KEY", 11) == 0)
     380        4220 :         local_node->contype = CONSTR_FOREIGN;
     381         300 :     else if (length == 15 && strncmp(token, "ATTR_DEFERRABLE", 15) == 0)
     382         162 :         local_node->contype = CONSTR_ATTR_DEFERRABLE;
     383         138 :     else if (length == 19 && strncmp(token, "ATTR_NOT_DEFERRABLE", 19) == 0)
     384           0 :         local_node->contype = CONSTR_ATTR_NOT_DEFERRABLE;
     385         138 :     else if (length == 13 && strncmp(token, "ATTR_DEFERRED", 13) == 0)
     386         126 :         local_node->contype = CONSTR_ATTR_DEFERRED;
     387          12 :     else if (length == 14 && strncmp(token, "ATTR_IMMEDIATE", 14) == 0)
     388          12 :         local_node->contype = CONSTR_ATTR_IMMEDIATE;
     389             : 
     390       53794 :     switch (local_node->contype)
     391             :     {
     392          48 :         case CONSTR_NULL:
     393             :             /* no extra fields */
     394          48 :             break;
     395             : 
     396       11604 :         case CONSTR_NOTNULL:
     397       11604 :             READ_NODE_FIELD(keys);
     398       11604 :             READ_INT_FIELD(inhcount);
     399       11604 :             READ_BOOL_FIELD(is_no_inherit);
     400       11604 :             READ_BOOL_FIELD(skip_validation);
     401       11604 :             READ_BOOL_FIELD(initially_valid);
     402       11604 :             break;
     403             : 
     404        3152 :         case CONSTR_DEFAULT:
     405        3152 :             READ_NODE_FIELD(raw_expr);
     406        3152 :             READ_STRING_FIELD(cooked_expr);
     407        3152 :             break;
     408             : 
     409         664 :         case CONSTR_IDENTITY:
     410         664 :             READ_NODE_FIELD(options);
     411         664 :             READ_CHAR_FIELD(generated_when);
     412         664 :             break;
     413             : 
     414        1690 :         case CONSTR_GENERATED:
     415        1690 :             READ_NODE_FIELD(raw_expr);
     416        1690 :             READ_STRING_FIELD(cooked_expr);
     417        1690 :             READ_CHAR_FIELD(generated_when);
     418        1690 :             break;
     419             : 
     420        3688 :         case CONSTR_CHECK:
     421        3688 :             READ_BOOL_FIELD(is_no_inherit);
     422        3688 :             READ_NODE_FIELD(raw_expr);
     423        3688 :             READ_STRING_FIELD(cooked_expr);
     424        3688 :             READ_BOOL_FIELD(skip_validation);
     425        3688 :             READ_BOOL_FIELD(initially_valid);
     426        3688 :             break;
     427             : 
     428       20790 :         case CONSTR_PRIMARY:
     429       20790 :             READ_NODE_FIELD(keys);
     430       20790 :             READ_NODE_FIELD(including);
     431       20790 :             READ_NODE_FIELD(options);
     432       20790 :             READ_STRING_FIELD(indexname);
     433       20790 :             READ_STRING_FIELD(indexspace);
     434       20790 :             READ_BOOL_FIELD(reset_default_tblspc);
     435             :             /* access_method and where_clause not currently used */
     436       20790 :             break;
     437             : 
     438        7218 :         case CONSTR_UNIQUE:
     439        7218 :             READ_BOOL_FIELD(nulls_not_distinct);
     440        7218 :             READ_NODE_FIELD(keys);
     441        7218 :             READ_NODE_FIELD(including);
     442        7218 :             READ_NODE_FIELD(options);
     443        7218 :             READ_STRING_FIELD(indexname);
     444        7218 :             READ_STRING_FIELD(indexspace);
     445        7218 :             READ_BOOL_FIELD(reset_default_tblspc);
     446             :             /* access_method and where_clause not currently used */
     447        7218 :             break;
     448             : 
     449         420 :         case CONSTR_EXCLUSION:
     450         420 :             READ_NODE_FIELD(exclusions);
     451         420 :             READ_NODE_FIELD(including);
     452         420 :             READ_NODE_FIELD(options);
     453         420 :             READ_STRING_FIELD(indexname);
     454         420 :             READ_STRING_FIELD(indexspace);
     455         420 :             READ_BOOL_FIELD(reset_default_tblspc);
     456         420 :             READ_STRING_FIELD(access_method);
     457         420 :             READ_NODE_FIELD(where_clause);
     458         420 :             break;
     459             : 
     460        4220 :         case CONSTR_FOREIGN:
     461        4220 :             READ_NODE_FIELD(pktable);
     462        4220 :             READ_NODE_FIELD(fk_attrs);
     463        4220 :             READ_NODE_FIELD(pk_attrs);
     464        4220 :             READ_CHAR_FIELD(fk_matchtype);
     465        4220 :             READ_CHAR_FIELD(fk_upd_action);
     466        4220 :             READ_CHAR_FIELD(fk_del_action);
     467        4220 :             READ_NODE_FIELD(fk_del_set_cols);
     468        4220 :             READ_NODE_FIELD(old_conpfeqop);
     469        4220 :             READ_OID_FIELD(old_pktable_oid);
     470        4220 :             READ_BOOL_FIELD(skip_validation);
     471        4220 :             READ_BOOL_FIELD(initially_valid);
     472        4220 :             break;
     473             : 
     474         300 :         case CONSTR_ATTR_DEFERRABLE:
     475             :         case CONSTR_ATTR_NOT_DEFERRABLE:
     476             :         case CONSTR_ATTR_DEFERRED:
     477             :         case CONSTR_ATTR_IMMEDIATE:
     478             :             /* no extra fields */
     479         300 :             break;
     480             : 
     481           0 :         default:
     482           0 :             elog(ERROR, "unrecognized ConstrType: %d", (int) local_node->contype);
     483             :             break;
     484             :     }
     485             : 
     486       53794 :     READ_DONE();
     487             : }
     488             : 
     489             : static RangeTblEntry *
     490     1418154 : _readRangeTblEntry(void)
     491             : {
     492     1418154 :     READ_LOCALS(RangeTblEntry);
     493             : 
     494             :     /* put alias + eref first to make dump more legible */
     495     1418154 :     READ_NODE_FIELD(alias);
     496     1418154 :     READ_NODE_FIELD(eref);
     497     1418154 :     READ_ENUM_FIELD(rtekind, RTEKind);
     498             : 
     499     1418154 :     switch (local_node->rtekind)
     500             :     {
     501      858920 :         case RTE_RELATION:
     502      858920 :             READ_OID_FIELD(relid);
     503      858920 :             READ_CHAR_FIELD(relkind);
     504      858920 :             READ_INT_FIELD(rellockmode);
     505      858920 :             READ_NODE_FIELD(tablesample);
     506      858920 :             READ_UINT_FIELD(perminfoindex);
     507      858920 :             break;
     508      102398 :         case RTE_SUBQUERY:
     509      102398 :             READ_NODE_FIELD(subquery);
     510      102398 :             READ_BOOL_FIELD(security_barrier);
     511             :             /* we re-use these RELATION fields, too: */
     512      102398 :             READ_OID_FIELD(relid);
     513      102398 :             READ_CHAR_FIELD(relkind);
     514      102398 :             READ_INT_FIELD(rellockmode);
     515      102398 :             READ_UINT_FIELD(perminfoindex);
     516      102398 :             break;
     517      154616 :         case RTE_JOIN:
     518      154616 :             READ_ENUM_FIELD(jointype, JoinType);
     519      154616 :             READ_INT_FIELD(joinmergedcols);
     520      154616 :             READ_NODE_FIELD(joinaliasvars);
     521      154616 :             READ_NODE_FIELD(joinleftcols);
     522      154616 :             READ_NODE_FIELD(joinrightcols);
     523      154616 :             READ_NODE_FIELD(join_using_alias);
     524      154616 :             break;
     525       84150 :         case RTE_FUNCTION:
     526       84150 :             READ_NODE_FIELD(functions);
     527       84150 :             READ_BOOL_FIELD(funcordinality);
     528       84150 :             break;
     529         498 :         case RTE_TABLEFUNC:
     530         498 :             READ_NODE_FIELD(tablefunc);
     531             :             /* The RTE must have a copy of the column type info, if any */
     532         498 :             if (local_node->tablefunc)
     533             :             {
     534         282 :                 TableFunc  *tf = local_node->tablefunc;
     535             : 
     536         282 :                 local_node->coltypes = tf->coltypes;
     537         282 :                 local_node->coltypmods = tf->coltypmods;
     538         282 :                 local_node->colcollations = tf->colcollations;
     539             :             }
     540         498 :             break;
     541       17092 :         case RTE_VALUES:
     542       17092 :             READ_NODE_FIELD(values_lists);
     543       17092 :             READ_NODE_FIELD(coltypes);
     544       17092 :             READ_NODE_FIELD(coltypmods);
     545       17092 :             READ_NODE_FIELD(colcollations);
     546       17092 :             break;
     547        9168 :         case RTE_CTE:
     548        9168 :             READ_STRING_FIELD(ctename);
     549        9168 :             READ_UINT_FIELD(ctelevelsup);
     550        9168 :             READ_BOOL_FIELD(self_reference);
     551        9168 :             READ_NODE_FIELD(coltypes);
     552        9168 :             READ_NODE_FIELD(coltypmods);
     553        9168 :             READ_NODE_FIELD(colcollations);
     554        9168 :             break;
     555         876 :         case RTE_NAMEDTUPLESTORE:
     556         876 :             READ_STRING_FIELD(enrname);
     557         876 :             READ_FLOAT_FIELD(enrtuples);
     558         876 :             READ_NODE_FIELD(coltypes);
     559         876 :             READ_NODE_FIELD(coltypmods);
     560         876 :             READ_NODE_FIELD(colcollations);
     561             :             /* we re-use these RELATION fields, too: */
     562         876 :             READ_OID_FIELD(relid);
     563         876 :             break;
     564      190436 :         case RTE_RESULT:
     565             :             /* no extra fields */
     566      190436 :             break;
     567           0 :         default:
     568           0 :             elog(ERROR, "unrecognized RTE kind: %d",
     569             :                  (int) local_node->rtekind);
     570             :             break;
     571             :     }
     572             : 
     573     1418154 :     READ_BOOL_FIELD(lateral);
     574     1418154 :     READ_BOOL_FIELD(inh);
     575     1418154 :     READ_BOOL_FIELD(inFromCl);
     576     1418154 :     READ_NODE_FIELD(securityQuals);
     577             : 
     578     1418154 :     READ_DONE();
     579             : }
     580             : 
     581             : static A_Expr *
     582      550170 : _readA_Expr(void)
     583             : {
     584      550170 :     READ_LOCALS(A_Expr);
     585             : 
     586      550170 :     token = pg_strtok(&length);
     587             : 
     588      550170 :     if (length == 3 && strncmp(token, "ANY", 3) == 0)
     589             :     {
     590       12416 :         local_node->kind = AEXPR_OP_ANY;
     591       12416 :         READ_NODE_FIELD(name);
     592             :     }
     593      537754 :     else if (length == 3 && strncmp(token, "ALL", 3) == 0)
     594             :     {
     595         144 :         local_node->kind = AEXPR_OP_ALL;
     596         144 :         READ_NODE_FIELD(name);
     597             :     }
     598      537610 :     else if (length == 8 && strncmp(token, "DISTINCT", 8) == 0)
     599             :     {
     600         742 :         local_node->kind = AEXPR_DISTINCT;
     601         742 :         READ_NODE_FIELD(name);
     602             :     }
     603      536868 :     else if (length == 12 && strncmp(token, "NOT_DISTINCT", 12) == 0)
     604             :     {
     605          68 :         local_node->kind = AEXPR_NOT_DISTINCT;
     606          68 :         READ_NODE_FIELD(name);
     607             :     }
     608      536800 :     else if (length == 6 && strncmp(token, "NULLIF", 6) == 0)
     609             :     {
     610         294 :         local_node->kind = AEXPR_NULLIF;
     611         294 :         READ_NODE_FIELD(name);
     612             :     }
     613      536506 :     else if (length == 2 && strncmp(token, "IN", 2) == 0)
     614             :     {
     615       18190 :         local_node->kind = AEXPR_IN;
     616       18190 :         READ_NODE_FIELD(name);
     617             :     }
     618      518316 :     else if (length == 4 && strncmp(token, "LIKE", 4) == 0)
     619             :     {
     620        2050 :         local_node->kind = AEXPR_LIKE;
     621        2050 :         READ_NODE_FIELD(name);
     622             :     }
     623      516266 :     else if (length == 5 && strncmp(token, "ILIKE", 5) == 0)
     624             :     {
     625         144 :         local_node->kind = AEXPR_ILIKE;
     626         144 :         READ_NODE_FIELD(name);
     627             :     }
     628      516122 :     else if (length == 7 && strncmp(token, "SIMILAR", 7) == 0)
     629             :     {
     630          58 :         local_node->kind = AEXPR_SIMILAR;
     631          58 :         READ_NODE_FIELD(name);
     632             :     }
     633      516064 :     else if (length == 7 && strncmp(token, "BETWEEN", 7) == 0)
     634             :     {
     635         540 :         local_node->kind = AEXPR_BETWEEN;
     636         540 :         READ_NODE_FIELD(name);
     637             :     }
     638      515524 :     else if (length == 11 && strncmp(token, "NOT_BETWEEN", 11) == 0)
     639             :     {
     640          12 :         local_node->kind = AEXPR_NOT_BETWEEN;
     641          12 :         READ_NODE_FIELD(name);
     642             :     }
     643      515512 :     else if (length == 11 && strncmp(token, "BETWEEN_SYM", 11) == 0)
     644             :     {
     645          12 :         local_node->kind = AEXPR_BETWEEN_SYM;
     646          12 :         READ_NODE_FIELD(name);
     647             :     }
     648      515500 :     else if (length == 15 && strncmp(token, "NOT_BETWEEN_SYM", 15) == 0)
     649             :     {
     650          12 :         local_node->kind = AEXPR_NOT_BETWEEN_SYM;
     651          12 :         READ_NODE_FIELD(name);
     652             :     }
     653      515488 :     else if (length == 5 && strncmp(token, ":name", 5) == 0)
     654             :     {
     655      515488 :         local_node->kind = AEXPR_OP;
     656      515488 :         local_node->name = nodeRead(NULL, 0);
     657             :     }
     658             :     else
     659           0 :         elog(ERROR, "unrecognized A_Expr kind: \"%.*s\"", length, token);
     660             : 
     661      550170 :     READ_NODE_FIELD(lexpr);
     662      550170 :     READ_NODE_FIELD(rexpr);
     663      550170 :     READ_LOCATION_FIELD(location);
     664             : 
     665      550170 :     READ_DONE();
     666             : }
     667             : 
     668             : static ExtensibleNode *
     669           0 : _readExtensibleNode(void)
     670             : {
     671             :     const ExtensibleNodeMethods *methods;
     672             :     ExtensibleNode *local_node;
     673             :     const char *extnodename;
     674             : 
     675             :     READ_TEMP_LOCALS();
     676             : 
     677           0 :     token = pg_strtok(&length); /* skip :extnodename */
     678           0 :     token = pg_strtok(&length); /* get extnodename */
     679             : 
     680           0 :     extnodename = nullable_string(token, length);
     681           0 :     if (!extnodename)
     682           0 :         elog(ERROR, "extnodename has to be supplied");
     683           0 :     methods = GetExtensibleNodeMethods(extnodename, false);
     684             : 
     685           0 :     local_node = (ExtensibleNode *) newNode(methods->node_size,
     686             :                                             T_ExtensibleNode);
     687           0 :     local_node->extnodename = extnodename;
     688             : 
     689             :     /* deserialize the private fields */
     690           0 :     methods->nodeRead(local_node);
     691             : 
     692           0 :     READ_DONE();
     693             : }
     694             : 
     695             : 
     696             : /*
     697             :  * parseNodeString
     698             :  *
     699             :  * Given a character string representing a node tree, parseNodeString creates
     700             :  * the internal node structure.
     701             :  *
     702             :  * The string to be read must already have been loaded into pg_strtok().
     703             :  */
     704             : Node *
     705    40248640 : parseNodeString(void)
     706             : {
     707             :     READ_TEMP_LOCALS();
     708             : 
     709             :     /* Guard against stack overflow due to overly complex expressions */
     710    40248640 :     check_stack_depth();
     711             : 
     712    40248640 :     token = pg_strtok(&length);
     713             : 
     714             : #define MATCH(tokname, namelen) \
     715             :     (length == namelen && memcmp(token, tokname, namelen) == 0)
     716             : 
     717             : #include "readfuncs.switch.c"
     718             : 
     719           0 :     elog(ERROR, "badly formatted node string \"%.32s\"...", token);
     720             :     return NULL;                /* keep compiler quiet */
     721             : }
     722             : 
     723             : 
     724             : /*
     725             :  * readDatum
     726             :  *
     727             :  * Given a string representation of a constant, recreate the appropriate
     728             :  * Datum.  The string representation embeds length info, but not byValue,
     729             :  * so we must be told that.
     730             :  */
     731             : Datum
     732     2236076 : readDatum(bool typbyval)
     733             : {
     734             :     Size        length,
     735             :                 i;
     736             :     int         tokenLength;
     737             :     const char *token;
     738             :     Datum       res;
     739             :     char       *s;
     740             : 
     741             :     /*
     742             :      * read the actual length of the value
     743             :      */
     744     2236076 :     token = pg_strtok(&tokenLength);
     745     2236076 :     length = atoui(token);
     746             : 
     747     2236076 :     token = pg_strtok(&tokenLength);    /* read the '[' */
     748     2236076 :     if (token == NULL || token[0] != '[')
     749           0 :         elog(ERROR, "expected \"[\" to start datum, but got \"%s\"; length = %zu",
     750             :              token ? token : "[NULL]", length);
     751             : 
     752     2236076 :     if (typbyval)
     753             :     {
     754     1555252 :         if (length > (Size) sizeof(Datum))
     755           0 :             elog(ERROR, "byval datum but length = %zu", length);
     756     1555252 :         res = (Datum) 0;
     757     1555252 :         s = (char *) (&res);
     758    13997268 :         for (i = 0; i < (Size) sizeof(Datum); i++)
     759             :         {
     760    12442016 :             token = pg_strtok(&tokenLength);
     761    12442016 :             s[i] = (char) atoi(token);
     762             :         }
     763             :     }
     764      680824 :     else if (length <= 0)
     765           0 :         res = (Datum) NULL;
     766             :     else
     767             :     {
     768      680824 :         s = (char *) palloc(length);
     769    54198300 :         for (i = 0; i < length; i++)
     770             :         {
     771    53517476 :             token = pg_strtok(&tokenLength);
     772    53517476 :             s[i] = (char) atoi(token);
     773             :         }
     774      680824 :         res = PointerGetDatum(s);
     775             :     }
     776             : 
     777     2236076 :     token = pg_strtok(&tokenLength);    /* read the ']' */
     778     2236076 :     if (token == NULL || token[0] != ']')
     779           0 :         elog(ERROR, "expected \"]\" to end datum, but got \"%s\"; length = %zu",
     780             :              token ? token : "[NULL]", length);
     781             : 
     782     2236076 :     return res;
     783             : }
     784             : 
     785             : /*
     786             :  * common implementation for scalar-array-reading functions
     787             :  *
     788             :  * The data format is either "<>" for a NULL pointer (in which case numCols
     789             :  * is ignored) or "(item item item)" where the number of items must equal
     790             :  * numCols.  The convfunc must be okay with stopping at whitespace or a
     791             :  * right parenthesis, since pg_strtok won't null-terminate the token.
     792             :  */
     793             : #define READ_SCALAR_ARRAY(fnname, datatype, convfunc) \
     794             : datatype * \
     795             : fnname(int numCols) \
     796             : { \
     797             :     datatype   *vals; \
     798             :     READ_TEMP_LOCALS(); \
     799             :     token = pg_strtok(&length); \
     800             :     if (token == NULL) \
     801             :         elog(ERROR, "incomplete scalar array"); \
     802             :     if (length == 0) \
     803             :         return NULL;            /* it was "<>", so return NULL pointer */ \
     804             :     if (length != 1 || token[0] != '(') \
     805             :         elog(ERROR, "unrecognized token: \"%.*s\"", length, token); \
     806             :     vals = (datatype *) palloc(numCols * sizeof(datatype)); \
     807             :     for (int i = 0; i < numCols; i++) \
     808             :     { \
     809             :         token = pg_strtok(&length); \
     810             :         if (token == NULL || token[0] == ')') \
     811             :             elog(ERROR, "incomplete scalar array"); \
     812             :         vals[i] = convfunc(token); \
     813             :     } \
     814             :     token = pg_strtok(&length); \
     815             :     if (token == NULL || length != 1 || token[0] != ')') \
     816             :         elog(ERROR, "incomplete scalar array"); \
     817             :     return vals; \
     818             : }
     819             : 
     820             : /*
     821             :  * Note: these functions are exported in nodes.h for possible use by
     822             :  * extensions, so don't mess too much with their names or API.
     823             :  */
     824      365910 : READ_SCALAR_ARRAY(readAttrNumberCols, int16, atoi)
     825      462848 : READ_SCALAR_ARRAY(readOidCols, Oid, atooid)
     826             : /* outfuncs.c has writeIndexCols, but we don't yet need that here */
     827             : /* READ_SCALAR_ARRAY(readIndexCols, Index, atoui) */
     828       21400 : READ_SCALAR_ARRAY(readIntCols, int, atoi)
     829      149258 : READ_SCALAR_ARRAY(readBoolCols, bool, strtobool)

Generated by: LCOV version 1.14