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