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