LCOV - differential code coverage report
Current view: top level - src/backend/nodes - readfuncs.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 38.5 % 361 139 182 3 36 1 10 108 16 5 9 16 202 115
Current Date: 2023-04-08 15:15:32 Functions: 68.8 % 16 11 3 2 6 5 2 5 9
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  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 ECB             :  */
     177                 : #define atoui(x)  ((unsigned int) strtoul((x), NULL, 10))
     178                 : 
     179                 : #define strtobool(x)  ((*(x) == 't') ? true : false)
     180                 : 
     181                 : static char *
     182 GNC     1419725 : nullable_string(const char *token, int length)
     183                 : {
     184                 :     /* outToken emits <> for NULL, and pg_strtok makes that an empty string */
     185         1419725 :     if (length == 0)
     186           37659 :         return NULL;
     187                 :     /* outToken emits "" for empty string */
     188         1382066 :     if (length == 2 && token[0] == '"' && token[1] == '"')
     189 UNC           0 :         return pstrdup("");
     190                 :     /* otherwise, we must remove protective backslashes added by outToken */
     191 GNC     1382066 :     return debackslash(token, length);
     192                 : }
     193 EUB             : 
     194                 : 
     195 ECB             : /*
     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 GIC     5102248 : _readBitmapset(void)
     204                 : {
     205         5102248 :     Bitmapset  *result = NULL;
     206                 : 
     207                 :     READ_TEMP_LOCALS();
     208                 : 
     209         5102248 :     token = pg_strtok(&length);
     210         5102248 :     if (token == NULL)
     211 LBC           0 :         elog(ERROR, "incomplete Bitmapset structure");
     212 GIC     5102248 :     if (length != 1 || token[0] != '(')
     213 LBC           0 :         elog(ERROR, "unrecognized token: \"%.*s\"", length, token);
     214                 : 
     215 GIC     5102248 :     token = pg_strtok(&length);
     216         5102248 :     if (token == NULL)
     217 LBC           0 :         elog(ERROR, "incomplete Bitmapset structure");
     218 CBC     5102248 :     if (length != 1 || token[0] != 'b')
     219 UBC           0 :         elog(ERROR, "unrecognized token: \"%.*s\"", length, token);
     220 ECB             : 
     221 EUB             :     for (;;)
     222 GIC     1302540 :     {
     223 ECB             :         int         val;
     224                 :         char       *endptr;
     225 EUB             : 
     226 CBC     6404788 :         token = pg_strtok(&length);
     227 GBC     6404788 :         if (token == NULL)
     228 UIC           0 :             elog(ERROR, "unterminated Bitmapset structure");
     229 GIC     6404788 :         if (length == 1 && token[0] == ')')
     230 CBC     5102248 :             break;
     231 GIC     1302540 :         val = (int) strtol(token, &endptr, 10);
     232         1302540 :         if (endptr != token + length)
     233 UIC           0 :             elog(ERROR, "unrecognized integer: \"%.*s\"", length, token);
     234 CBC     1302540 :         result = bms_add_member(result, val);
     235 ECB             :     }
     236 EUB             : 
     237 CBC     5102248 :     return result;
     238 ECB             : }
     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 UIC           0 : readBitmapset(void)
     246 ECB             : {
     247 UIC           0 :     return _readBitmapset();
     248                 : }
     249                 : 
     250                 : #include "readfuncs.funcs.c"
     251                 : 
     252 ECB             : 
     253                 : /*
     254                 :  * Support functions for nodes with custom_read_write attribute or
     255                 :  * special_read_write attribute
     256                 :  */
     257                 : 
     258 EUB             : static Const *
     259 GBC      728485 : _readConst(void)
     260                 : {
     261          728485 :     READ_LOCALS(Const);
     262                 : 
     263          728485 :     READ_OID_FIELD(consttype);
     264          728485 :     READ_INT_FIELD(consttypmod);
     265 GIC      728485 :     READ_OID_FIELD(constcollid);
     266 GBC      728485 :     READ_INT_FIELD(constlen);
     267 GIC      728485 :     READ_BOOL_FIELD(constbyval);
     268 GBC      728485 :     READ_BOOL_FIELD(constisnull);
     269          728485 :     READ_LOCATION_FIELD(location);
     270                 : 
     271          728485 :     token = pg_strtok(&length); /* skip :constvalue */
     272 GIC      728485 :     if (local_node->constisnull)
     273 GBC      125633 :         token = pg_strtok(&length); /* skip "<>" */
     274 EUB             :     else
     275 GIC      602852 :         local_node->constvalue = readDatum(local_node->constbyval);
     276 EUB             : 
     277 GIC      728485 :     READ_DONE();
     278 EUB             : }
     279                 : 
     280                 : static BoolExpr *
     281 GIC       98498 : _readBoolExpr(void)
     282                 : {
     283           98498 :     READ_LOCALS(BoolExpr);
     284                 : 
     285                 :     /* do-it-yourself enum representation */
     286           98498 :     token = pg_strtok(&length); /* skip :boolop */
     287           98498 :     token = pg_strtok(&length); /* get field value */
     288 GNC       98498 :     if (length == 3 && strncmp(token, "and", 3) == 0)
     289 GIC       58124 :         local_node->boolop = AND_EXPR;
     290 GNC       40374 :     else if (length == 2 && strncmp(token, "or", 2) == 0)
     291 GIC       28915 :         local_node->boolop = OR_EXPR;
     292 GNC       11459 :     else if (length == 3 && strncmp(token, "not", 3) == 0)
     293 GIC       11459 :         local_node->boolop = NOT_EXPR;
     294                 :     else
     295 UIC           0 :         elog(ERROR, "unrecognized boolop \"%.*s\"", length, token);
     296                 : 
     297 GIC       98498 :     READ_NODE_FIELD(args);
     298           98498 :     READ_LOCATION_FIELD(location);
     299                 : 
     300           98498 :     READ_DONE();
     301                 : }
     302                 : 
     303                 : static A_Const *
     304 UNC           0 : _readA_Const(void)
     305                 : {
     306               0 :     READ_LOCALS(A_Const);
     307                 : 
     308                 :     /* We expect either NULL or :val here */
     309               0 :     token = pg_strtok(&length);
     310               0 :     if (length == 4 && strncmp(token, "NULL", 4) == 0)
     311               0 :         local_node->isnull = true;
     312                 :     else
     313                 :     {
     314               0 :         union ValUnion *tmp = nodeRead(NULL, 0);
     315                 : 
     316                 :         /* To forestall valgrind complaints, copy only the valid data */
     317               0 :         switch (nodeTag(tmp))
     318                 :         {
     319               0 :             case T_Integer:
     320               0 :                 memcpy(&local_node->val, tmp, sizeof(Integer));
     321               0 :                 break;
     322               0 :             case T_Float:
     323               0 :                 memcpy(&local_node->val, tmp, sizeof(Float));
     324               0 :                 break;
     325               0 :             case T_Boolean:
     326               0 :                 memcpy(&local_node->val, tmp, sizeof(Boolean));
     327               0 :                 break;
     328               0 :             case T_String:
     329               0 :                 memcpy(&local_node->val, tmp, sizeof(String));
     330               0 :                 break;
     331               0 :             case T_BitString:
     332               0 :                 memcpy(&local_node->val, tmp, sizeof(BitString));
     333               0 :                 break;
     334               0 :             default:
     335               0 :                 elog(ERROR, "unrecognized node type: %d",
     336                 :                      (int) nodeTag(tmp));
     337                 :                 break;
     338                 :         }
     339                 :     }
     340                 : 
     341 UIC           0 :     READ_LOCATION_FIELD(location);
     342                 : 
     343               0 :     READ_DONE();
     344                 : }
     345                 : 
     346                 : /*
     347                 :  * _readConstraint
     348                 :  */
     349                 : static Constraint *
     350 UNC           0 : _readConstraint(void)
     351                 : {
     352               0 :     READ_LOCALS(Constraint);
     353                 : 
     354               0 :     READ_STRING_FIELD(conname);
     355               0 :     READ_BOOL_FIELD(deferrable);
     356               0 :     READ_BOOL_FIELD(initdeferred);
     357 UIC           0 :     READ_LOCATION_FIELD(location);
     358                 : 
     359 UNC           0 :     token = pg_strtok(&length); /* skip :contype */
     360               0 :     token = pg_strtok(&length); /* get field value */
     361               0 :     if (length == 4 && strncmp(token, "NULL", 4) == 0)
     362               0 :         local_node->contype = CONSTR_NULL;
     363               0 :     else if (length == 8 && strncmp(token, "NOT_NULL", 8) == 0)
     364               0 :         local_node->contype = CONSTR_NOTNULL;
     365               0 :     else if (length == 7 && strncmp(token, "DEFAULT", 7) == 0)
     366               0 :         local_node->contype = CONSTR_DEFAULT;
     367               0 :     else if (length == 8 && strncmp(token, "IDENTITY", 8) == 0)
     368               0 :         local_node->contype = CONSTR_IDENTITY;
     369               0 :     else if (length == 9 && strncmp(token, "GENERATED", 9) == 0)
     370               0 :         local_node->contype = CONSTR_GENERATED;
     371               0 :     else if (length == 5 && strncmp(token, "CHECK", 5) == 0)
     372               0 :         local_node->contype = CONSTR_CHECK;
     373               0 :     else if (length == 11 && strncmp(token, "PRIMARY_KEY", 11) == 0)
     374               0 :         local_node->contype = CONSTR_PRIMARY;
     375               0 :     else if (length == 6 && strncmp(token, "UNIQUE", 6) == 0)
     376               0 :         local_node->contype = CONSTR_UNIQUE;
     377               0 :     else if (length == 9 && strncmp(token, "EXCLUSION", 9) == 0)
     378               0 :         local_node->contype = CONSTR_EXCLUSION;
     379               0 :     else if (length == 11 && strncmp(token, "FOREIGN_KEY", 11) == 0)
     380               0 :         local_node->contype = CONSTR_FOREIGN;
     381               0 :     else if (length == 15 && strncmp(token, "ATTR_DEFERRABLE", 15) == 0)
     382               0 :         local_node->contype = CONSTR_ATTR_DEFERRABLE;
     383               0 :     else if (length == 19 && strncmp(token, "ATTR_NOT_DEFERRABLE", 19) == 0)
     384               0 :         local_node->contype = CONSTR_ATTR_NOT_DEFERRABLE;
     385               0 :     else if (length == 13 && strncmp(token, "ATTR_DEFERRED", 13) == 0)
     386               0 :         local_node->contype = CONSTR_ATTR_DEFERRED;
     387               0 :     else if (length == 14 && strncmp(token, "ATTR_IMMEDIATE", 14) == 0)
     388               0 :         local_node->contype = CONSTR_ATTR_IMMEDIATE;
     389                 : 
     390               0 :     switch (local_node->contype)
     391                 :     {
     392               0 :         case CONSTR_NULL:
     393                 :             /* no extra fields */
     394               0 :             break;
     395                 : 
     396               0 :         case CONSTR_NOTNULL:
     397               0 :             READ_BOOL_FIELD(is_no_inherit);
     398               0 :             READ_STRING_FIELD(colname);
     399               0 :             READ_BOOL_FIELD(skip_validation);
     400               0 :             READ_BOOL_FIELD(initially_valid);
     401               0 :             break;
     402                 : 
     403               0 :         case CONSTR_DEFAULT:
     404               0 :             READ_NODE_FIELD(raw_expr);
     405               0 :             READ_STRING_FIELD(cooked_expr);
     406               0 :             break;
     407                 : 
     408               0 :         case CONSTR_IDENTITY:
     409               0 :             READ_NODE_FIELD(options);
     410               0 :             READ_CHAR_FIELD(generated_when);
     411               0 :             break;
     412                 : 
     413               0 :         case CONSTR_GENERATED:
     414               0 :             READ_NODE_FIELD(raw_expr);
     415               0 :             READ_STRING_FIELD(cooked_expr);
     416               0 :             READ_CHAR_FIELD(generated_when);
     417               0 :             break;
     418                 : 
     419               0 :         case CONSTR_CHECK:
     420               0 :             READ_BOOL_FIELD(is_no_inherit);
     421               0 :             READ_NODE_FIELD(raw_expr);
     422               0 :             READ_STRING_FIELD(cooked_expr);
     423               0 :             READ_BOOL_FIELD(skip_validation);
     424               0 :             READ_BOOL_FIELD(initially_valid);
     425               0 :             break;
     426                 : 
     427               0 :         case CONSTR_PRIMARY:
     428               0 :             READ_NODE_FIELD(keys);
     429               0 :             READ_NODE_FIELD(including);
     430               0 :             READ_NODE_FIELD(options);
     431               0 :             READ_STRING_FIELD(indexname);
     432               0 :             READ_STRING_FIELD(indexspace);
     433               0 :             READ_BOOL_FIELD(reset_default_tblspc);
     434                 :             /* access_method and where_clause not currently used */
     435               0 :             break;
     436                 : 
     437               0 :         case CONSTR_UNIQUE:
     438               0 :             READ_BOOL_FIELD(nulls_not_distinct);
     439               0 :             READ_NODE_FIELD(keys);
     440               0 :             READ_NODE_FIELD(including);
     441               0 :             READ_NODE_FIELD(options);
     442               0 :             READ_STRING_FIELD(indexname);
     443               0 :             READ_STRING_FIELD(indexspace);
     444               0 :             READ_BOOL_FIELD(reset_default_tblspc);
     445                 :             /* access_method and where_clause not currently used */
     446               0 :             break;
     447                 : 
     448               0 :         case CONSTR_EXCLUSION:
     449               0 :             READ_NODE_FIELD(exclusions);
     450               0 :             READ_NODE_FIELD(including);
     451               0 :             READ_NODE_FIELD(options);
     452               0 :             READ_STRING_FIELD(indexname);
     453               0 :             READ_STRING_FIELD(indexspace);
     454               0 :             READ_BOOL_FIELD(reset_default_tblspc);
     455               0 :             READ_STRING_FIELD(access_method);
     456               0 :             READ_NODE_FIELD(where_clause);
     457               0 :             break;
     458                 : 
     459               0 :         case CONSTR_FOREIGN:
     460               0 :             READ_NODE_FIELD(pktable);
     461               0 :             READ_NODE_FIELD(fk_attrs);
     462               0 :             READ_NODE_FIELD(pk_attrs);
     463               0 :             READ_CHAR_FIELD(fk_matchtype);
     464               0 :             READ_CHAR_FIELD(fk_upd_action);
     465               0 :             READ_CHAR_FIELD(fk_del_action);
     466               0 :             READ_NODE_FIELD(fk_del_set_cols);
     467               0 :             READ_NODE_FIELD(old_conpfeqop);
     468               0 :             READ_OID_FIELD(old_pktable_oid);
     469               0 :             READ_BOOL_FIELD(skip_validation);
     470               0 :             READ_BOOL_FIELD(initially_valid);
     471               0 :             break;
     472                 : 
     473               0 :         case CONSTR_ATTR_DEFERRABLE:
     474                 :         case CONSTR_ATTR_NOT_DEFERRABLE:
     475                 :         case CONSTR_ATTR_DEFERRED:
     476                 :         case CONSTR_ATTR_IMMEDIATE:
     477                 :             /* no extra fields */
     478               0 :             break;
     479                 : 
     480               0 :         default:
     481               0 :             elog(ERROR, "unrecognized ConstrType: %d", (int) local_node->contype);
     482                 :             break;
     483                 :     }
     484                 : 
     485 UIC           0 :     READ_DONE();
     486                 : }
     487                 : 
     488                 : static RangeTblEntry *
     489 GIC      323138 : _readRangeTblEntry(void)
     490                 : {
     491          323138 :     READ_LOCALS(RangeTblEntry);
     492                 : 
     493                 :     /* put alias + eref first to make dump more legible */
     494          323138 :     READ_NODE_FIELD(alias);
     495          323138 :     READ_NODE_FIELD(eref);
     496          323138 :     READ_ENUM_FIELD(rtekind, RTEKind);
     497                 : 
     498          323138 :     switch (local_node->rtekind)
     499                 :     {
     500          196495 :         case RTE_RELATION:
     501          196495 :             READ_OID_FIELD(relid);
     502          196495 :             READ_CHAR_FIELD(relkind);
     503          196495 :             READ_INT_FIELD(rellockmode);
     504          196495 :             READ_NODE_FIELD(tablesample);
     505 GNC      196495 :             READ_UINT_FIELD(perminfoindex);
     506 GIC      196495 :             break;
     507           45344 :         case RTE_SUBQUERY:
     508           45344 :             READ_NODE_FIELD(subquery);
     509           45344 :             READ_BOOL_FIELD(security_barrier);
     510                 :             /* we re-use these RELATION fields, too: */
     511 GNC       45344 :             READ_OID_FIELD(relid);
     512           45344 :             READ_INT_FIELD(rellockmode);
     513           45344 :             READ_UINT_FIELD(perminfoindex);
     514 GIC       45344 :             break;
     515           63033 :         case RTE_JOIN:
     516           63033 :             READ_ENUM_FIELD(jointype, JoinType);
     517           63033 :             READ_INT_FIELD(joinmergedcols);
     518           63033 :             READ_NODE_FIELD(joinaliasvars);
     519           63033 :             READ_NODE_FIELD(joinleftcols);
     520           63033 :             READ_NODE_FIELD(joinrightcols);
     521           63033 :             READ_NODE_FIELD(join_using_alias);
     522           63033 :             break;
     523           17034 :         case RTE_FUNCTION:
     524           17034 :             READ_NODE_FIELD(functions);
     525           17034 :             READ_BOOL_FIELD(funcordinality);
     526           17034 :             break;
     527              39 :         case RTE_TABLEFUNC:
     528              39 :             READ_NODE_FIELD(tablefunc);
     529                 :             /* The RTE must have a copy of the column type info, if any */
     530              39 :             if (local_node->tablefunc)
     531                 :             {
     532              39 :                 TableFunc  *tf = local_node->tablefunc;
     533                 : 
     534              39 :                 local_node->coltypes = tf->coltypes;
     535              39 :                 local_node->coltypmods = tf->coltypmods;
     536              39 :                 local_node->colcollations = tf->colcollations;
     537                 :             }
     538              39 :             break;
     539             902 :         case RTE_VALUES:
     540             902 :             READ_NODE_FIELD(values_lists);
     541             902 :             READ_NODE_FIELD(coltypes);
     542             902 :             READ_NODE_FIELD(coltypmods);
     543             902 :             READ_NODE_FIELD(colcollations);
     544             902 :             break;
     545             248 :         case RTE_CTE:
     546             248 :             READ_STRING_FIELD(ctename);
     547             248 :             READ_UINT_FIELD(ctelevelsup);
     548             248 :             READ_BOOL_FIELD(self_reference);
     549             248 :             READ_NODE_FIELD(coltypes);
     550             248 :             READ_NODE_FIELD(coltypmods);
     551             248 :             READ_NODE_FIELD(colcollations);
     552             248 :             break;
     553 UIC           0 :         case RTE_NAMEDTUPLESTORE:
     554               0 :             READ_STRING_FIELD(enrname);
     555               0 :             READ_FLOAT_FIELD(enrtuples);
     556               0 :             READ_NODE_FIELD(coltypes);
     557               0 :             READ_NODE_FIELD(coltypmods);
     558               0 :             READ_NODE_FIELD(colcollations);
     559                 :             /* we re-use these RELATION fields, too: */
     560 UNC           0 :             READ_OID_FIELD(relid);
     561 UIC           0 :             break;
     562 GIC          43 :         case RTE_RESULT:
     563                 :             /* no extra fields */
     564              43 :             break;
     565 UIC           0 :         default:
     566               0 :             elog(ERROR, "unrecognized RTE kind: %d",
     567                 :                  (int) local_node->rtekind);
     568                 :             break;
     569                 :     }
     570                 : 
     571 GIC      323138 :     READ_BOOL_FIELD(lateral);
     572          323138 :     READ_BOOL_FIELD(inh);
     573          323138 :     READ_BOOL_FIELD(inFromCl);
     574          323138 :     READ_NODE_FIELD(securityQuals);
     575                 : 
     576          323138 :     READ_DONE();
     577                 : }
     578                 : 
     579                 : static A_Expr *
     580 UNC           0 : _readA_Expr(void)
     581                 : {
     582               0 :     READ_LOCALS(A_Expr);
     583                 : 
     584               0 :     token = pg_strtok(&length);
     585                 : 
     586               0 :     if (length == 3 && strncmp(token, "ANY", 3) == 0)
     587                 :     {
     588               0 :         local_node->kind = AEXPR_OP_ANY;
     589               0 :         READ_NODE_FIELD(name);
     590                 :     }
     591               0 :     else if (length == 3 && strncmp(token, "ALL", 3) == 0)
     592                 :     {
     593               0 :         local_node->kind = AEXPR_OP_ALL;
     594               0 :         READ_NODE_FIELD(name);
     595                 :     }
     596               0 :     else if (length == 8 && strncmp(token, "DISTINCT", 8) == 0)
     597                 :     {
     598               0 :         local_node->kind = AEXPR_DISTINCT;
     599               0 :         READ_NODE_FIELD(name);
     600                 :     }
     601               0 :     else if (length == 12 && strncmp(token, "NOT_DISTINCT", 12) == 0)
     602                 :     {
     603               0 :         local_node->kind = AEXPR_NOT_DISTINCT;
     604               0 :         READ_NODE_FIELD(name);
     605                 :     }
     606               0 :     else if (length == 6 && strncmp(token, "NULLIF", 6) == 0)
     607                 :     {
     608               0 :         local_node->kind = AEXPR_NULLIF;
     609               0 :         READ_NODE_FIELD(name);
     610                 :     }
     611               0 :     else if (length == 2 && strncmp(token, "IN", 2) == 0)
     612                 :     {
     613               0 :         local_node->kind = AEXPR_IN;
     614               0 :         READ_NODE_FIELD(name);
     615                 :     }
     616               0 :     else if (length == 4 && strncmp(token, "LIKE", 4) == 0)
     617                 :     {
     618               0 :         local_node->kind = AEXPR_LIKE;
     619               0 :         READ_NODE_FIELD(name);
     620                 :     }
     621               0 :     else if (length == 5 && strncmp(token, "ILIKE", 5) == 0)
     622                 :     {
     623               0 :         local_node->kind = AEXPR_ILIKE;
     624               0 :         READ_NODE_FIELD(name);
     625                 :     }
     626               0 :     else if (length == 7 && strncmp(token, "SIMILAR", 7) == 0)
     627                 :     {
     628               0 :         local_node->kind = AEXPR_SIMILAR;
     629               0 :         READ_NODE_FIELD(name);
     630                 :     }
     631               0 :     else if (length == 7 && strncmp(token, "BETWEEN", 7) == 0)
     632                 :     {
     633               0 :         local_node->kind = AEXPR_BETWEEN;
     634               0 :         READ_NODE_FIELD(name);
     635                 :     }
     636               0 :     else if (length == 11 && strncmp(token, "NOT_BETWEEN", 11) == 0)
     637                 :     {
     638               0 :         local_node->kind = AEXPR_NOT_BETWEEN;
     639               0 :         READ_NODE_FIELD(name);
     640                 :     }
     641               0 :     else if (length == 11 && strncmp(token, "BETWEEN_SYM", 11) == 0)
     642                 :     {
     643               0 :         local_node->kind = AEXPR_BETWEEN_SYM;
     644               0 :         READ_NODE_FIELD(name);
     645                 :     }
     646               0 :     else if (length == 15 && strncmp(token, "NOT_BETWEEN_SYM", 15) == 0)
     647                 :     {
     648               0 :         local_node->kind = AEXPR_NOT_BETWEEN_SYM;
     649               0 :         READ_NODE_FIELD(name);
     650                 :     }
     651               0 :     else if (length == 5 && strncmp(token, ":name", 5) == 0)
     652                 :     {
     653               0 :         local_node->kind = AEXPR_OP;
     654               0 :         local_node->name = nodeRead(NULL, 0);
     655                 :     }
     656                 :     else
     657               0 :         elog(ERROR, "unrecognized A_Expr kind: \"%.*s\"", length, token);
     658                 : 
     659               0 :     READ_NODE_FIELD(lexpr);
     660               0 :     READ_NODE_FIELD(rexpr);
     661 UIC           0 :     READ_LOCATION_FIELD(location);
     662                 : 
     663               0 :     READ_DONE();
     664                 : }
     665                 : 
     666                 : static ExtensibleNode *
     667               0 : _readExtensibleNode(void)
     668                 : {
     669                 :     const ExtensibleNodeMethods *methods;
     670                 :     ExtensibleNode *local_node;
     671                 :     const char *extnodename;
     672                 : 
     673                 :     READ_TEMP_LOCALS();
     674                 : 
     675               0 :     token = pg_strtok(&length); /* skip :extnodename */
     676               0 :     token = pg_strtok(&length); /* get extnodename */
     677                 : 
     678               0 :     extnodename = nullable_string(token, length);
     679               0 :     if (!extnodename)
     680               0 :         elog(ERROR, "extnodename has to be supplied");
     681               0 :     methods = GetExtensibleNodeMethods(extnodename, false);
     682                 : 
     683               0 :     local_node = (ExtensibleNode *) newNode(methods->node_size,
     684                 :                                             T_ExtensibleNode);
     685               0 :     local_node->extnodename = extnodename;
     686                 : 
     687                 :     /* deserialize the private fields */
     688               0 :     methods->nodeRead(local_node);
     689                 : 
     690               0 :     READ_DONE();
     691                 : }
     692                 : 
     693                 : 
     694                 : /*
     695                 :  * parseNodeString
     696                 :  *
     697                 :  * Given a character string representing a node tree, parseNodeString creates
     698                 :  * the internal node structure.
     699                 :  *
     700                 :  * The string to be read must already have been loaded into pg_strtok().
     701                 :  */
     702                 : Node *
     703 GIC     9506643 : parseNodeString(void)
     704                 : {
     705                 :     void       *return_value;
     706                 : 
     707                 :     READ_TEMP_LOCALS();
     708                 : 
     709                 :     /* Guard against stack overflow due to overly complex expressions */
     710         9506643 :     check_stack_depth();
     711                 : 
     712         9506643 :     token = pg_strtok(&length);
     713                 : 
     714                 : #define MATCH(tokname, namelen) \
     715                 :     (length == namelen && memcmp(token, tokname, namelen) == 0)
     716                 : 
     717                 :     if (false)
     718                 :         ;
     719                 : #include "readfuncs.switch.c"
     720                 :     else
     721                 :     {
     722 UIC           0 :         elog(ERROR, "badly formatted node string \"%.32s\"...", token);
     723                 :         return_value = NULL;    /* keep compiler quiet */
     724                 :     }
     725                 : 
     726 GIC     9506643 :     return (Node *) return_value;
     727                 : }
     728                 : 
     729                 : 
     730                 : /*
     731                 :  * readDatum
     732                 :  *
     733                 :  * Given a string representation of a constant, recreate the appropriate
     734                 :  * Datum.  The string representation embeds length info, but not byValue,
     735                 :  * so we must be told that.
     736                 :  */
     737                 : Datum
     738          602852 : readDatum(bool typbyval)
     739                 : {
     740                 :     Size        length,
     741                 :                 i;
     742                 :     int         tokenLength;
     743                 :     const char *token;
     744                 :     Datum       res;
     745                 :     char       *s;
     746                 : 
     747                 :     /*
     748                 :      * read the actual length of the value
     749                 :      */
     750          602852 :     token = pg_strtok(&tokenLength);
     751          602852 :     length = atoui(token);
     752                 : 
     753          602852 :     token = pg_strtok(&tokenLength);    /* read the '[' */
     754          602852 :     if (token == NULL || token[0] != '[')
     755 UIC           0 :         elog(ERROR, "expected \"[\" to start datum, but got \"%s\"; length = %zu",
     756                 :              token ? token : "[NULL]", length);
     757                 : 
     758 GIC      602852 :     if (typbyval)
     759                 :     {
     760          376985 :         if (length > (Size) sizeof(Datum))
     761 UIC           0 :             elog(ERROR, "byval datum but length = %zu", length);
     762 GIC      376985 :         res = (Datum) 0;
     763          376985 :         s = (char *) (&res);
     764         3392865 :         for (i = 0; i < (Size) sizeof(Datum); i++)
     765                 :         {
     766         3015880 :             token = pg_strtok(&tokenLength);
     767         3015880 :             s[i] = (char) atoi(token);
     768                 :         }
     769                 :     }
     770          225867 :     else if (length <= 0)
     771 UIC           0 :         res = (Datum) NULL;
     772                 :     else
     773                 :     {
     774 GIC      225867 :         s = (char *) palloc(length);
     775         4614497 :         for (i = 0; i < length; i++)
     776                 :         {
     777         4388630 :             token = pg_strtok(&tokenLength);
     778         4388630 :             s[i] = (char) atoi(token);
     779                 :         }
     780          225867 :         res = PointerGetDatum(s);
     781                 :     }
     782                 : 
     783          602852 :     token = pg_strtok(&tokenLength);    /* read the ']' */
     784          602852 :     if (token == NULL || token[0] != ']')
     785 UIC           0 :         elog(ERROR, "expected \"]\" to end datum, but got \"%s\"; length = %zu",
     786                 :              token ? token : "[NULL]", length);
     787                 : 
     788 GIC      602852 :     return res;
     789                 : }
     790                 : 
     791                 : /*
     792                 :  * common implementation for scalar-array-reading functions
     793                 :  *
     794                 :  * The data format is either "<>" for a NULL pointer (in which case numCols
     795                 :  * is ignored) or "(item item item)" where the number of items must equal
     796                 :  * numCols.  The convfunc must be okay with stopping at whitespace or a
     797                 :  * right parenthesis, since pg_strtok won't null-terminate the token.
     798                 :  */
     799                 : #define READ_SCALAR_ARRAY(fnname, datatype, convfunc) \
     800                 : datatype * \
     801                 : fnname(int numCols) \
     802                 : { \
     803                 :     datatype   *vals; \
     804                 :     READ_TEMP_LOCALS(); \
     805                 :     token = pg_strtok(&length); \
     806                 :     if (token == NULL) \
     807                 :         elog(ERROR, "incomplete scalar array"); \
     808                 :     if (length == 0) \
     809                 :         return NULL;            /* it was "<>", so return NULL pointer */ \
     810                 :     if (length != 1 || token[0] != '(') \
     811                 :         elog(ERROR, "unrecognized token: \"%.*s\"", length, token); \
     812                 :     vals = (datatype *) palloc(numCols * sizeof(datatype)); \
     813                 :     for (int i = 0; i < numCols; i++) \
     814                 :     { \
     815                 :         token = pg_strtok(&length); \
     816                 :         if (token == NULL || token[0] == ')') \
     817                 :             elog(ERROR, "incomplete scalar array"); \
     818                 :         vals[i] = convfunc(token); \
     819                 :     } \
     820                 :     token = pg_strtok(&length); \
     821                 :     if (token == NULL || length != 1 || token[0] != ')') \
     822                 :         elog(ERROR, "incomplete scalar array"); \
     823                 :     return vals; \
     824                 : }
     825                 : 
     826                 : /*
     827                 :  * Note: these functions are exported in nodes.h for possible use by
     828                 :  * extensions, so don't mess too much with their names or API.
     829                 :  */
     830 GNC        1612 : READ_SCALAR_ARRAY(readAttrNumberCols, int16, atoi)
     831            4090 : READ_SCALAR_ARRAY(readOidCols, Oid, atooid)
     832                 : /* outfuncs.c has writeIndexCols, but we don't yet need that here */
     833                 : /* READ_SCALAR_ARRAY(readIndexCols, Index, atoui) */
     834            1612 : READ_SCALAR_ARRAY(readIntCols, int, atoi)
     835             482 : READ_SCALAR_ARRAY(readBoolCols, bool, strtobool)
        

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