Age Owner 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.)
8126 tgl 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 *
195 peter 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] == '"')
195 peter 189 UNC 0 : return pstrdup("");
190 : /* otherwise, we must remove protective backslashes added by outToken */
195 peter 191 GNC 1382066 : return debackslash(token, length);
192 : }
8126 tgl 193 EUB :
194 :
5190 tgl 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 *
5190 tgl 203 GIC 5102248 : _readBitmapset(void)
204 : {
5050 bruce 205 5102248 : Bitmapset *result = NULL;
206 :
207 : READ_TEMP_LOCALS();
208 :
5190 tgl 209 5102248 : token = pg_strtok(&length);
210 5102248 : if (token == NULL)
5190 tgl 211 LBC 0 : elog(ERROR, "incomplete Bitmapset structure");
5190 tgl 212 GIC 5102248 : if (length != 1 || token[0] != '(')
5190 tgl 213 LBC 0 : elog(ERROR, "unrecognized token: \"%.*s\"", length, token);
214 :
5190 tgl 215 GIC 5102248 : token = pg_strtok(&length);
216 5102248 : if (token == NULL)
5190 tgl 217 LBC 0 : elog(ERROR, "incomplete Bitmapset structure");
5190 tgl 218 CBC 5102248 : if (length != 1 || token[0] != 'b')
5190 tgl 219 UBC 0 : elog(ERROR, "unrecognized token: \"%.*s\"", length, token);
5190 tgl 220 ECB :
5190 tgl 221 EUB : for (;;)
5190 tgl 222 GIC 1302540 : {
5050 bruce 223 ECB : int val;
224 : char *endptr;
5190 tgl 225 EUB :
5190 tgl 226 CBC 6404788 : token = pg_strtok(&length);
5190 tgl 227 GBC 6404788 : if (token == NULL)
5190 tgl 228 UIC 0 : elog(ERROR, "unterminated Bitmapset structure");
5190 tgl 229 GIC 6404788 : if (length == 1 && token[0] == ')')
5190 tgl 230 CBC 5102248 : break;
5190 tgl 231 GIC 1302540 : val = (int) strtol(token, &endptr, 10);
232 1302540 : if (endptr != token + length)
5190 tgl 233 UIC 0 : elog(ERROR, "unrecognized integer: \"%.*s\"", length, token);
5190 tgl 234 CBC 1302540 : result = bms_add_member(result, val);
5190 tgl 235 ECB : }
5190 tgl 236 EUB :
5190 tgl 237 CBC 5102248 : return result;
5190 tgl 238 ECB : }
239 :
2613 rhaas 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 *
2613 rhaas 245 UIC 0 : readBitmapset(void)
2613 rhaas 246 ECB : {
2613 rhaas 247 UIC 0 : return _readBitmapset();
248 : }
249 :
250 : #include "readfuncs.funcs.c"
251 :
274 peter 252 ECB :
7440 tgl 253 : /*
254 : * Support functions for nodes with custom_read_write attribute or
255 : * special_read_write attribute
256 : */
274 peter 257 :
274 peter 258 EUB : static Const *
274 peter 259 GBC 728485 : _readConst(void)
260 : {
261 728485 : READ_LOCALS(Const);
262 :
263 728485 : READ_OID_FIELD(consttype);
264 728485 : READ_INT_FIELD(consttypmod);
274 peter 265 GIC 728485 : READ_OID_FIELD(constcollid);
274 peter 266 GBC 728485 : READ_INT_FIELD(constlen);
274 peter 267 GIC 728485 : READ_BOOL_FIELD(constbyval);
274 peter 268 GBC 728485 : READ_BOOL_FIELD(constisnull);
2885 andres 269 728485 : READ_LOCATION_FIELD(location);
270 :
274 peter 271 728485 : token = pg_strtok(&length); /* skip :constvalue */
274 peter 272 GIC 728485 : if (local_node->constisnull)
274 peter 273 GBC 125633 : token = pg_strtok(&length); /* skip "<>" */
274 peter 274 EUB : else
274 peter 275 GIC 602852 : local_node->constvalue = readDatum(local_node->constbyval);
797 peter 276 EUB :
797 peter 277 GIC 728485 : READ_DONE();
797 peter 278 EUB : }
279 :
280 : static BoolExpr *
274 peter 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 */
197 peter 288 GNC 98498 : if (length == 3 && strncmp(token, "and", 3) == 0)
274 peter 289 GIC 58124 : local_node->boolop = AND_EXPR;
197 peter 290 GNC 40374 : else if (length == 2 && strncmp(token, "or", 2) == 0)
274 peter 291 GIC 28915 : local_node->boolop = OR_EXPR;
197 peter 292 GNC 11459 : else if (length == 3 && strncmp(token, "not", 3) == 0)
274 peter 293 GIC 11459 : local_node->boolop = NOT_EXPR;
294 : else
274 peter 295 UIC 0 : elog(ERROR, "unrecognized boolop \"%.*s\"", length, token);
296 :
274 peter 297 GIC 98498 : READ_NODE_FIELD(args);
5300 tgl 298 98498 : READ_LOCATION_FIELD(location);
299 :
7440 300 98498 : READ_DONE();
301 : }
302 :
303 : static A_Const *
197 peter 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 */
21 tgl 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 :
197 peter 341 UIC 0 : READ_LOCATION_FIELD(location);
342 :
343 0 : READ_DONE();
344 : }
345 :
346 : /*
347 : * _readConstraint
348 : */
349 : static Constraint *
197 peter 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);
197 peter 357 UIC 0 : READ_LOCATION_FIELD(location);
358 :
197 peter 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 :
2 alvherre 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 :
197 peter 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 :
197 peter 485 UIC 0 : READ_DONE();
486 : }
487 :
488 : static RangeTblEntry *
274 peter 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);
124 alvherre 505 GNC 196495 : READ_UINT_FIELD(perminfoindex);
274 peter 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: */
81 tgl 511 GNC 45344 : READ_OID_FIELD(relid);
512 45344 : READ_INT_FIELD(rellockmode);
513 45344 : READ_UINT_FIELD(perminfoindex);
274 peter 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;
274 peter 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: */
81 tgl 560 UNC 0 : READ_OID_FIELD(relid);
274 peter 561 UIC 0 : break;
274 peter 562 GIC 43 : case RTE_RESULT:
563 : /* no extra fields */
564 43 : break;
274 peter 565 UIC 0 : default:
566 0 : elog(ERROR, "unrecognized RTE kind: %d",
567 : (int) local_node->rtekind);
568 : break;
569 : }
570 :
274 peter 571 GIC 323138 : READ_BOOL_FIELD(lateral);
2298 tgl 572 323138 : READ_BOOL_FIELD(inh);
274 peter 573 323138 : READ_BOOL_FIELD(inFromCl);
574 323138 : READ_NODE_FIELD(securityQuals);
575 :
7440 tgl 576 323138 : READ_DONE();
577 : }
578 :
579 : static A_Expr *
197 peter 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);
197 peter 661 UIC 0 : READ_LOCATION_FIELD(location);
662 :
663 0 : READ_DONE();
664 : }
665 :
666 : static ExtensibleNode *
274 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 :
7440 tgl 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 *
7440 tgl 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 */
1581 710 9506643 : check_stack_depth();
711 :
8127 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 : {
7440 tgl 722 UIC 0 : elog(ERROR, "badly formatted node string \"%.32s\"...", token);
723 : return_value = NULL; /* keep compiler quiet */
724 : }
725 :
8986 bruce 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
8127 tgl 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);
8126 751 602852 : length = atoui(token);
752 :
7950 753 602852 : token = pg_strtok(&tokenLength); /* read the '[' */
754 602852 : if (token == NULL || token[0] != '[')
3363 tgl 755 UIC 0 : elog(ERROR, "expected \"[\" to start datum, but got \"%s\"; length = %zu",
756 : token ? token : "[NULL]", length);
757 :
8127 tgl 758 GIC 602852 : if (typbyval)
759 : {
8126 760 376985 : if (length > (Size) sizeof(Datum))
3363 tgl 761 UIC 0 : elog(ERROR, "byval datum but length = %zu", length);
8486 tgl 762 GIC 376985 : res = (Datum) 0;
9345 bruce 763 376985 : s = (char *) (&res);
8126 tgl 764 3392865 : for (i = 0; i < (Size) sizeof(Datum); i++)
765 : {
8127 766 3015880 : token = pg_strtok(&tokenLength);
9345 bruce 767 3015880 : s[i] = (char) atoi(token);
768 : }
769 : }
770 225867 : else if (length <= 0)
8486 tgl 771 UIC 0 : res = (Datum) NULL;
772 : else
773 : {
9345 bruce 774 GIC 225867 : s = (char *) palloc(length);
775 4614497 : for (i = 0; i < length; i++)
776 : {
8127 tgl 777 4388630 : token = pg_strtok(&tokenLength);
9345 bruce 778 4388630 : s[i] = (char) atoi(token);
779 : }
780 225867 : res = PointerGetDatum(s);
781 : }
782 :
7950 tgl 783 602852 : token = pg_strtok(&tokenLength); /* read the ']' */
8127 784 602852 : if (token == NULL || token[0] != ']')
3363 tgl 785 UIC 0 : elog(ERROR, "expected \"]\" to end datum, but got \"%s\"; length = %zu",
786 : token ? token : "[NULL]", length);
787 :
8986 bruce 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 : */
263 tgl 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)
|