PostgreSQL Source Code git master
Loading...
Searching...
No Matches
readfuncs.c File Reference
#include "postgres.h"
#include "miscadmin.h"
#include "nodes/bitmapset.h"
#include "nodes/readfuncs.h"
#include "readfuncs.funcs.c"
#include "readfuncs.switch.c"
Include dependency graph for readfuncs.c:

Go to the source code of this file.

Macros

#define READ_LOCALS_NO_FIELDS(nodeTypeName)    nodeTypeName *local_node = makeNode(nodeTypeName)
 
#define READ_TEMP_LOCALS()
 
#define READ_LOCALS(nodeTypeName)
 
#define READ_INT_FIELD(fldname)
 
#define READ_UINT_FIELD(fldname)
 
#define READ_INT64_FIELD(fldname)
 
#define READ_UINT64_FIELD(fldname)
 
#define READ_LONG_FIELD(fldname)
 
#define READ_OID_FIELD(fldname)
 
#define READ_CHAR_FIELD(fldname)
 
#define READ_ENUM_FIELD(fldname, enumtype)
 
#define READ_FLOAT_FIELD(fldname)
 
#define READ_BOOL_FIELD(fldname)
 
#define READ_STRING_FIELD(fldname)
 
#define READ_LOCATION_FIELD(fldname)
 
#define READ_NODE_FIELD(fldname)
 
#define READ_BITMAPSET_FIELD(fldname)
 
#define READ_ATTRNUMBER_ARRAY(fldname, len)
 
#define READ_OID_ARRAY(fldname, len)
 
#define READ_INT_ARRAY(fldname, len)
 
#define READ_BOOL_ARRAY(fldname, len)
 
#define READ_DONE()    return local_node
 
#define atoui(x)   ((unsigned int) strtoul((x), NULL, 10))
 
#define strtobool(x)   ((*(x) == 't') ? true : false)
 
#define MATCH(tokname, namelen)    (length == namelen && memcmp(token, tokname, namelen) == 0)
 
#define READ_SCALAR_ARRAY(fnname, datatype, convfunc)
 

Functions

static charnullable_string (const char *token, int length)
 
static Bitmapset_readBitmapset (void)
 
BitmapsetreadBitmapset (void)
 
static Const_readConst (void)
 
static BoolExpr_readBoolExpr (void)
 
static A_Const_readA_Const (void)
 
static RangeTblEntry_readRangeTblEntry (void)
 
static A_Expr_readA_Expr (void)
 
static ExtensibleNode_readExtensibleNode (void)
 
NodeparseNodeString (void)
 
Datum readDatum (bool typbyval)
 

Macro Definition Documentation

◆ atoui

#define atoui (   x)    ((unsigned int) strtoul((x), NULL, 10))

Definition at line 181 of file readfuncs.c.

◆ MATCH

#define MATCH (   tokname,
  namelen 
)     (length == namelen && memcmp(token, tokname, namelen) == 0)

◆ READ_ATTRNUMBER_ARRAY

#define READ_ATTRNUMBER_ARRAY (   fldname,
  len 
)
Value:
token = pg_strtok(&length); /* skip :fldname */ \
int16 * readAttrNumberCols(int numCols)
const void size_t len
static int fb(int x)
const char * pg_strtok(int *length)
Definition read.c:153

Definition at line 151 of file readfuncs.c.

182 : false)
183
184static char *
185nullable_string(const char *token, int length)
186{
187 /* outToken emits <> for NULL, and pg_strtok makes that an empty string */
188 if (length == 0)
189 return NULL;
190 /* outToken emits "" for empty string */
191 if (length == 2 && token[0] == '"' && token[1] == '"')
192 return pstrdup("");
193 /* otherwise, we must remove protective backslashes added by outToken */
194 return debackslash(token, length);
195}
196
197
198/*
199 * _readBitmapset
200 *
201 * Note: this code is used in contexts where we know that a Bitmapset
202 * is expected. There is equivalent code in nodeRead() that can read a
203 * Bitmapset when we come across one in other contexts.
204 */
205static Bitmapset *
206_readBitmapset(void)
207{
208 Bitmapset *result = NULL;
209
211
212 token = pg_strtok(&length);
213 if (token == NULL)
214 elog(ERROR, "incomplete Bitmapset structure");
215 if (length != 1 || token[0] != '(')
216 elog(ERROR, "unrecognized token: \"%.*s\"", length, token);
217
218 token = pg_strtok(&length);
219 if (token == NULL)
220 elog(ERROR, "incomplete Bitmapset structure");
221 if (length != 1 || token[0] != 'b')
222 elog(ERROR, "unrecognized token: \"%.*s\"", length, token);
223
224 for (;;)
225 {
226 int val;
227 char *endptr;
228
229 token = pg_strtok(&length);
230 if (token == NULL)
231 elog(ERROR, "unterminated Bitmapset structure");
232 if (length == 1 && token[0] == ')')
233 break;
234 val = (int) strtol(token, &endptr, 10);
235 if (endptr != token + length)
236 elog(ERROR, "unrecognized integer: \"%.*s\"", length, token);
237 result = bms_add_member(result, val);
238 }
239
240 return result;
241}
242
243/*
244 * We export this function for use by extensions that define extensible nodes.
245 * That's somewhat historical, though, because calling nodeRead() will work.
246 */
247Bitmapset *
248readBitmapset(void)
249{
250 return _readBitmapset();
251}
252
253#include "readfuncs.funcs.c"
254
255
256/*
257 * Support functions for nodes with custom_read_write attribute or
258 * special_read_write attribute
259 */
260
261static Const *
262_readConst(void)
263{
265
266 READ_OID_FIELD(consttype);
272 READ_LOCATION_FIELD(location);
273
274 token = pg_strtok(&length); /* skip :constvalue */
275 if (local_node->constisnull)
276 token = pg_strtok(&length); /* skip "<>" */
277 else
278 local_node->constvalue = readDatum(local_node->constbyval);
279
280 READ_DONE();
281}
282
283static BoolExpr *
284_readBoolExpr(void)
285{
287
288 /* do-it-yourself enum representation */
289 token = pg_strtok(&length); /* skip :boolop */
290 token = pg_strtok(&length); /* get field value */
291 if (length == 3 && strncmp(token, "and", 3) == 0)
292 local_node->boolop = AND_EXPR;
293 else if (length == 2 && strncmp(token, "or", 2) == 0)
294 local_node->boolop = OR_EXPR;
295 else if (length == 3 && strncmp(token, "not", 3) == 0)
296 local_node->boolop = NOT_EXPR;
297 else
298 elog(ERROR, "unrecognized boolop \"%.*s\"", length, token);
299
300 READ_NODE_FIELD(args);
301 READ_LOCATION_FIELD(location);
302
303 READ_DONE();
304}
305
306static A_Const *
307_readA_Const(void)
308{
310
311 /* We expect either NULL or :val here */
312 token = pg_strtok(&length);
313 if (length == 4 && strncmp(token, "NULL", 4) == 0)
314 local_node->isnull = true;
315 else
316 {
317 union ValUnion *tmp = nodeRead(NULL, 0);
318
319 /* To forestall valgrind complaints, copy only the valid data */
320 switch (nodeTag(tmp))
321 {
322 case T_Integer:
323 memcpy(&local_node->val, tmp, sizeof(Integer));
324 break;
325 case T_Float:
326 memcpy(&local_node->val, tmp, sizeof(Float));
327 break;
328 case T_Boolean:
329 memcpy(&local_node->val, tmp, sizeof(Boolean));
330 break;
331 case T_String:
332 memcpy(&local_node->val, tmp, sizeof(String));
333 break;
334 case T_BitString:
335 memcpy(&local_node->val, tmp, sizeof(BitString));
336 break;
337 default:
338 elog(ERROR, "unrecognized node type: %d",
339 (int) nodeTag(tmp));
340 break;
341 }
342 }
343
344 READ_LOCATION_FIELD(location);
345
346 READ_DONE();
347}
348
349static RangeTblEntry *
351{
353
354 READ_NODE_FIELD(alias);
356 READ_ENUM_FIELD(rtekind, RTEKind);
357
358 switch (local_node->rtekind)
359 {
360 case RTE_RELATION:
361 READ_OID_FIELD(relid);
362 READ_BOOL_FIELD(inh);
363 READ_CHAR_FIELD(relkind);
366 READ_NODE_FIELD(tablesample);
367 break;
368 case RTE_SUBQUERY:
369 READ_NODE_FIELD(subquery);
370 READ_BOOL_FIELD(security_barrier);
371 /* we re-use these RELATION fields, too: */
372 READ_OID_FIELD(relid);
373 READ_BOOL_FIELD(inh);
374 READ_CHAR_FIELD(relkind);
377 break;
378 case RTE_JOIN:
379 READ_ENUM_FIELD(jointype, JoinType);
385 break;
386 case RTE_FUNCTION:
388 READ_BOOL_FIELD(funcordinality);
389 break;
390 case RTE_TABLEFUNC:
391 READ_NODE_FIELD(tablefunc);
392 /* The RTE must have a copy of the column type info, if any */
393 if (local_node->tablefunc)
394 {
395 TableFunc *tf = local_node->tablefunc;
396
397 local_node->coltypes = tf->coltypes;
398 local_node->coltypmods = tf->coltypmods;
399 local_node->colcollations = tf->colcollations;
400 }
401 break;
402 case RTE_VALUES:
403 READ_NODE_FIELD(values_lists);
407 break;
408 case RTE_CTE:
409 READ_STRING_FIELD(ctename);
410 READ_UINT_FIELD(ctelevelsup);
415 break;
417 READ_STRING_FIELD(enrname);
418 READ_FLOAT_FIELD(enrtuples);
422 /* we re-use these RELATION fields, too: */
423 READ_OID_FIELD(relid);
424 break;
425 case RTE_GRAPH_TABLE:
426 READ_NODE_FIELD(graph_pattern);
427 READ_NODE_FIELD(graph_table_columns);
428 /* we re-use these RELATION fields, too: */
429 READ_OID_FIELD(relid);
430 READ_CHAR_FIELD(relkind);
433 break;
434 case RTE_RESULT:
435 /* no extra fields */
436 break;
437 case RTE_GROUP:
438 READ_NODE_FIELD(groupexprs);
439 break;
440 default:
441 elog(ERROR, "unrecognized RTE kind: %d",
442 (int) local_node->rtekind);
443 break;
444 }
445
446 READ_BOOL_FIELD(lateral);
449
450 READ_DONE();
451}
452
453static A_Expr *
454_readA_Expr(void)
455{
457
458 token = pg_strtok(&length);
459
460 if (length == 3 && strncmp(token, "ANY", 3) == 0)
461 {
462 local_node->kind = AEXPR_OP_ANY;
464 }
465 else if (length == 3 && strncmp(token, "ALL", 3) == 0)
466 {
467 local_node->kind = AEXPR_OP_ALL;
469 }
470 else if (length == 8 && strncmp(token, "DISTINCT", 8) == 0)
471 {
474 }
475 else if (length == 12 && strncmp(token, "NOT_DISTINCT", 12) == 0)
476 {
479 }
480 else if (length == 6 && strncmp(token, "NULLIF", 6) == 0)
481 {
482 local_node->kind = AEXPR_NULLIF;
484 }
485 else if (length == 2 && strncmp(token, "IN", 2) == 0)
486 {
487 local_node->kind = AEXPR_IN;
489 }
490 else if (length == 4 && strncmp(token, "LIKE", 4) == 0)
491 {
492 local_node->kind = AEXPR_LIKE;
494 }
495 else if (length == 5 && strncmp(token, "ILIKE", 5) == 0)
496 {
497 local_node->kind = AEXPR_ILIKE;
499 }
500 else if (length == 7 && strncmp(token, "SIMILAR", 7) == 0)
501 {
504 }
505 else if (length == 7 && strncmp(token, "BETWEEN", 7) == 0)
506 {
509 }
510 else if (length == 11 && strncmp(token, "NOT_BETWEEN", 11) == 0)
511 {
514 }
515 else if (length == 11 && strncmp(token, "BETWEEN_SYM", 11) == 0)
516 {
519 }
520 else if (length == 15 && strncmp(token, "NOT_BETWEEN_SYM", 15) == 0)
521 {
524 }
525 else if (length == 5 && strncmp(token, ":name", 5) == 0)
526 {
527 local_node->kind = AEXPR_OP;
528 local_node->name = nodeRead(NULL, 0);
529 }
530 else
531 elog(ERROR, "unrecognized A_Expr kind: \"%.*s\"", length, token);
532
533 READ_NODE_FIELD(lexpr);
534 READ_NODE_FIELD(rexpr);
535 READ_LOCATION_FIELD(rexpr_list_start);
536 READ_LOCATION_FIELD(rexpr_list_end);
537 READ_LOCATION_FIELD(location);
538
539 READ_DONE();
540}
541
542static ExtensibleNode *
544{
545 const ExtensibleNodeMethods *methods;
547 const char *extnodename;
548
550
551 token = pg_strtok(&length); /* skip :extnodename */
552 token = pg_strtok(&length); /* get extnodename */
553
554 extnodename = nullable_string(token, length);
555 if (!extnodename)
556 elog(ERROR, "extnodename has to be supplied");
557 methods = GetExtensibleNodeMethods(extnodename, false);
558
561 local_node->extnodename = extnodename;
562
563 /* deserialize the private fields */
564 methods->nodeRead(local_node);
565
566 READ_DONE();
567}
568
569
570/*
571 * parseNodeString
572 *
573 * Given a character string representing a node tree, parseNodeString creates
574 * the internal node structure.
575 *
576 * The string to be read must already have been loaded into pg_strtok().
577 */
578Node *
579parseNodeString(void)
580{
582
583 /* Guard against stack overflow due to overly complex expressions */
585
586 token = pg_strtok(&length);
587
588#define MATCH(tokname, namelen) \
589 (length == namelen && memcmp(token, tokname, namelen) == 0)
590
591#include "readfuncs.switch.c"
592
593 elog(ERROR, "badly formatted node string \"%.32s\"...", token);
594 return NULL; /* keep compiler quiet */
595}
596
597
598/*
599 * readDatum
600 *
601 * Given a string representation of a constant, recreate the appropriate
602 * Datum. The string representation embeds length info, but not byValue,
603 * so we must be told that.
604 */
605Datum
606readDatum(bool typbyval)
607{
608 Size length;
609 int tokenLength;
610 const char *token;
611 Datum res;
612 char *s;
613
614 /*
615 * read the actual length of the value
616 */
618 length = atoui(token);
619
620 token = pg_strtok(&tokenLength); /* read the '[' */
621 if (token == NULL || token[0] != '[')
622 elog(ERROR, "expected \"[\" to start datum, but got \"%s\"; length = %zu",
623 token ? token : "[NULL]", length);
624
625 if (typbyval)
626 {
627 if (length > (Size) sizeof(Datum))
628 elog(ERROR, "byval datum but length = %zu", length);
629 res = (Datum) 0;
630 s = (char *) (&res);
631 for (Size i = 0; i < (Size) sizeof(Datum); i++)
632 {
634 s[i] = (char) atoi(token);
635 }
636 }
637 else if (length <= 0)
638 res = (Datum) 0;
639 else
640 {
641 s = (char *) palloc(length);
642 for (Size i = 0; i < length; i++)
643 {
645 s[i] = (char) atoi(token);
646 }
647 res = PointerGetDatum(s);
648 }
649
650 token = pg_strtok(&tokenLength); /* read the ']' */
651 if (token == NULL || token[0] != ']')
652 elog(ERROR, "expected \"]\" to end datum, but got \"%s\"; length = %zu",
653 token ? token : "[NULL]", length);
654
655 return res;
656}
657
658/*
659 * common implementation for scalar-array-reading functions
660 *
661 * The data format is either "<>" for a NULL pointer (in which case numCols
662 * is ignored) or "(item item item)" where the number of items must equal
663 * numCols. The convfunc must be okay with stopping at whitespace or a
664 * right parenthesis, since pg_strtok won't null-terminate the token.
665 */
666#define READ_SCALAR_ARRAY(fnname, datatype, convfunc) \
667datatype * \
668fnname(int numCols) \
669{ \
670 datatype *vals; \
671 READ_TEMP_LOCALS(); \
672 token = pg_strtok(&length); \
673 if (token == NULL) \
674 elog(ERROR, "incomplete scalar array"); \
675 if (length == 0) \
676 return NULL; /* it was "<>", so return NULL pointer */ \
677 if (length != 1 || token[0] != '(') \
678 elog(ERROR, "unrecognized token: \"%.*s\"", length, token); \
679 vals = (datatype *) palloc(numCols * sizeof(datatype)); \
680 for (int i = 0; i < numCols; i++) \
681 { \
682 token = pg_strtok(&length); \
683 if (token == NULL || token[0] == ')') \
684 elog(ERROR, "incomplete scalar array"); \
685 vals[i] = convfunc(token); \
686 } \
687 token = pg_strtok(&length); \
688 if (token == NULL || length != 1 || token[0] != ')') \
689 elog(ERROR, "incomplete scalar array"); \
690 return vals; \
691}
692
693/*
694 * Note: these functions are exported in nodes.h for possible use by
695 * extensions, so don't mess too much with their names or API.
696 */
699/* outfuncs.c has writeIndexCols, but we don't yet need that here */
700/* READ_SCALAR_ARRAY(readIndexCols, Index, atoui) */
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition bitmapset.c:799
int16_t int16
Definition c.h:613
size_t Size
Definition c.h:691
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
const ExtensibleNodeMethods * GetExtensibleNodeMethods(const char *extnodename, bool missing_ok)
Definition extensible.c:125
#define token
long val
Definition informix.c:689
int i
Definition isn.c:77
char * pstrdup(const char *in)
Definition mcxt.c:1781
void * palloc(Size size)
Definition mcxt.c:1387
#define nodeTag(nodeptr)
Definition nodes.h:139
int * readIntCols(int numCols)
static Node * newNode(size_t size, NodeTag tag)
Definition nodes.h:150
Oid * readOidCols(int numCols)
JoinType
Definition nodes.h:298
bool * readBoolCols(int numCols)
@ AEXPR_BETWEEN
Definition parsenodes.h:340
@ AEXPR_NULLIF
Definition parsenodes.h:335
@ AEXPR_NOT_DISTINCT
Definition parsenodes.h:334
@ AEXPR_BETWEEN_SYM
Definition parsenodes.h:342
@ AEXPR_NOT_BETWEEN_SYM
Definition parsenodes.h:343
@ AEXPR_ILIKE
Definition parsenodes.h:338
@ AEXPR_IN
Definition parsenodes.h:336
@ AEXPR_NOT_BETWEEN
Definition parsenodes.h:341
@ AEXPR_DISTINCT
Definition parsenodes.h:333
@ AEXPR_SIMILAR
Definition parsenodes.h:339
@ AEXPR_LIKE
Definition parsenodes.h:337
@ AEXPR_OP
Definition parsenodes.h:330
@ AEXPR_OP_ANY
Definition parsenodes.h:331
@ AEXPR_OP_ALL
Definition parsenodes.h:332
RTEKind
@ RTE_JOIN
@ RTE_CTE
@ RTE_NAMEDTUPLESTORE
@ RTE_VALUES
@ RTE_SUBQUERY
@ RTE_RESULT
@ RTE_FUNCTION
@ RTE_TABLEFUNC
@ RTE_GROUP
@ RTE_GRAPH_TABLE
@ RTE_RELATION
static Datum PointerGetDatum(const void *X)
Definition postgres.h:342
uint64_t Datum
Definition postgres.h:70
unsigned int Oid
#define atooid(x)
@ AND_EXPR
Definition primnodes.h:964
@ OR_EXPR
Definition primnodes.h:964
@ NOT_EXPR
Definition primnodes.h:964
char * debackslash(const char *token, int length)
Definition read.c:214
void * nodeRead(const char *token, int tok_len)
Definition read.c:320
#define READ_INT_FIELD(fldname)
Definition readfuncs.c:58
#define READ_UINT_FIELD(fldname)
Definition readfuncs.c:64
#define READ_NODE_FIELD(fldname)
Definition readfuncs.c:139
static ExtensibleNode * _readExtensibleNode(void)
Definition readfuncs.c:544
#define READ_CHAR_FIELD(fldname)
Definition readfuncs.c:94
static char * nullable_string(const char *token, int length)
Definition readfuncs.c:186
#define READ_SCALAR_ARRAY(fnname, datatype, convfunc)
Definition readfuncs.c:667
Node * parseNodeString(void)
Definition readfuncs.c:580
#define READ_OID_FIELD(fldname)
Definition readfuncs.c:88
#define READ_LOCATION_FIELD(fldname)
Definition readfuncs.c:131
static Bitmapset * _readBitmapset(void)
Definition readfuncs.c:207
static A_Const * _readA_Const(void)
Definition readfuncs.c:308
static Const * _readConst(void)
Definition readfuncs.c:263
#define READ_STRING_FIELD(fldname)
Definition readfuncs.c:119
#define READ_FLOAT_FIELD(fldname)
Definition readfuncs.c:107
Datum readDatum(bool typbyval)
Definition readfuncs.c:607
#define READ_BOOL_FIELD(fldname)
Definition readfuncs.c:113
#define atoui(x)
Definition readfuncs.c:181
#define strtobool(x)
Definition readfuncs.c:183
static BoolExpr * _readBoolExpr(void)
Definition readfuncs.c:285
#define READ_ENUM_FIELD(fldname, enumtype)
Definition readfuncs.c:101
#define READ_TEMP_LOCALS()
Definition readfuncs.c:48
static A_Expr * _readA_Expr(void)
Definition readfuncs.c:455
Bitmapset * readBitmapset(void)
Definition readfuncs.c:249
#define READ_LOCALS(nodeTypeName)
Definition readfuncs.c:53
#define READ_DONE()
Definition readfuncs.c:171
static RangeTblEntry * _readRangeTblEntry(void)
Definition readfuncs.c:351
static const struct fns functions
Definition regcomp.c:358
void check_stack_depth(void)
Definition stack_depth.c:95
void(* nodeRead)(struct ExtensibleNode *node)
Definition extensible.h:72
Definition value.h:48
Definition nodes.h:135
Definition value.h:64
const char * name

◆ READ_BITMAPSET_FIELD

#define READ_BITMAPSET_FIELD (   fldname)
Value:
token = pg_strtok(&length); /* skip :fldname */ \
(void) token; /* in case not used elsewhere */ \

Definition at line 145 of file readfuncs.c.

◆ READ_BOOL_ARRAY

#define READ_BOOL_ARRAY (   fldname,
  len 
)
Value:
token = pg_strtok(&length); /* skip :fldname */ \

Definition at line 166 of file readfuncs.c.

◆ READ_BOOL_FIELD

#define READ_BOOL_FIELD (   fldname)
Value:
token = pg_strtok(&length); /* skip :fldname */ \
token = pg_strtok(&length); /* get field value */ \

Definition at line 113 of file readfuncs.c.

◆ READ_CHAR_FIELD

#define READ_CHAR_FIELD (   fldname)
Value:
token = pg_strtok(&length); /* skip :fldname */ \
token = pg_strtok(&length); /* get field value */ \
/* avoid overhead of calling debackslash() for one char */ \
local_node->fldname = (length == 0) ? '\0' : (token[0] == '\\' ? token[1] : token[0])

Definition at line 94 of file readfuncs.c.

98 : (token[0] == '\\' ? token[1] : token[0])

◆ READ_DONE

#define READ_DONE ( )     return local_node

Definition at line 171 of file readfuncs.c.

◆ READ_ENUM_FIELD

#define READ_ENUM_FIELD (   fldname,
  enumtype 
)
Value:
token = pg_strtok(&length); /* skip :fldname */ \
token = pg_strtok(&length); /* get field value */ \
local_node->fldname = (enumtype) atoi(token)

Definition at line 101 of file readfuncs.c.

◆ READ_FLOAT_FIELD

#define READ_FLOAT_FIELD (   fldname)
Value:
token = pg_strtok(&length); /* skip :fldname */ \
token = pg_strtok(&length); /* get field value */ \
local_node->fldname = atof(token)

Definition at line 107 of file readfuncs.c.

◆ READ_INT64_FIELD

#define READ_INT64_FIELD (   fldname)
Value:
token = pg_strtok(&length); /* skip :fldname */ \
token = pg_strtok(&length); /* get field value */ \
local_node->fldname = strtoi64(token, NULL, 10)

Definition at line 70 of file readfuncs.c.

◆ READ_INT_ARRAY

#define READ_INT_ARRAY (   fldname,
  len 
)
Value:
token = pg_strtok(&length); /* skip :fldname */ \

Definition at line 161 of file readfuncs.c.

◆ READ_INT_FIELD

#define READ_INT_FIELD (   fldname)
Value:
token = pg_strtok(&length); /* skip :fldname */ \
token = pg_strtok(&length); /* get field value */ \
local_node->fldname = atoi(token)

Definition at line 58 of file readfuncs.c.

◆ READ_LOCALS

#define READ_LOCALS (   nodeTypeName)
Value:
#define READ_LOCALS_NO_FIELDS(nodeTypeName)
Definition readfuncs.c:44

Definition at line 53 of file readfuncs.c.

◆ READ_LOCALS_NO_FIELDS

#define READ_LOCALS_NO_FIELDS (   nodeTypeName)     nodeTypeName *local_node = makeNode(nodeTypeName)

Definition at line 44 of file readfuncs.c.

◆ READ_LOCATION_FIELD

#define READ_LOCATION_FIELD (   fldname)
Value:
token = pg_strtok(&length); /* skip :fldname */ \
token = pg_strtok(&length); /* get field value */ \
(void) token; /* in case not used elsewhere */ \
local_node->fldname = -1 /* set field to "unknown" */

Definition at line 131 of file readfuncs.c.

◆ READ_LONG_FIELD

#define READ_LONG_FIELD (   fldname)
Value:
token = pg_strtok(&length); /* skip :fldname */ \
token = pg_strtok(&length); /* get field value */ \
local_node->fldname = atol(token)

Definition at line 82 of file readfuncs.c.

◆ READ_NODE_FIELD

#define READ_NODE_FIELD (   fldname)
Value:
token = pg_strtok(&length); /* skip :fldname */ \
(void) token; /* in case not used elsewhere */ \
local_node->fldname = nodeRead(NULL, 0)

Definition at line 139 of file readfuncs.c.

◆ READ_OID_ARRAY

#define READ_OID_ARRAY (   fldname,
  len 
)
Value:
token = pg_strtok(&length); /* skip :fldname */ \

Definition at line 156 of file readfuncs.c.

◆ READ_OID_FIELD

#define READ_OID_FIELD (   fldname)
Value:
token = pg_strtok(&length); /* skip :fldname */ \
token = pg_strtok(&length); /* get field value */ \
local_node->fldname = atooid(token)

Definition at line 88 of file readfuncs.c.

◆ READ_SCALAR_ARRAY

#define READ_SCALAR_ARRAY (   fnname,
  datatype,
  convfunc 
)
Value:
datatype * \
fnname(int numCols) \
{ \
datatype *vals; \
token = pg_strtok(&length); \
elog(ERROR, "incomplete scalar array"); \
if (length == 0) \
return NULL; /* it was "<>", so return NULL pointer */ \
if (length != 1 || token[0] != '(') \
elog(ERROR, "unrecognized token: \"%.*s\"", length, token); \
vals = (datatype *) palloc(numCols * sizeof(datatype)); \
for (int i = 0; i < numCols; i++) \
{ \
token = pg_strtok(&length); \
if (token == NULL || token[0] == ')') \
elog(ERROR, "incomplete scalar array"); \
vals[i] = convfunc(token); \
} \
token = pg_strtok(&length); \
if (token == NULL || length != 1 || token[0] != ')') \
elog(ERROR, "incomplete scalar array"); \
return vals; \
}

Definition at line 667 of file readfuncs.c.

670{ \
671 datatype *vals; \
673 token = pg_strtok(&length); \
674 if (token == NULL) \
675 elog(ERROR, "incomplete scalar array"); \
676 if (length == 0) \
677 return NULL; /* it was "<>", so return NULL pointer */ \
678 if (length != 1 || token[0] != '(') \
679 elog(ERROR, "unrecognized token: \"%.*s\"", length, token); \
680 vals = (datatype *) palloc(numCols * sizeof(datatype)); \
681 for (int i = 0; i < numCols; i++) \
682 { \
683 token = pg_strtok(&length); \
684 if (token == NULL || token[0] == ')') \
685 elog(ERROR, "incomplete scalar array"); \
686 vals[i] = convfunc(token); \
687 } \
688 token = pg_strtok(&length); \
689 if (token == NULL || length != 1 || token[0] != ')') \
690 elog(ERROR, "incomplete scalar array"); \
691 return vals; \
692}

◆ READ_STRING_FIELD

#define READ_STRING_FIELD (   fldname)
Value:
token = pg_strtok(&length); /* skip :fldname */ \
token = pg_strtok(&length); /* get field value */ \
local_node->fldname = nullable_string(token, length)

Definition at line 119 of file readfuncs.c.

◆ READ_TEMP_LOCALS

#define READ_TEMP_LOCALS ( )
Value:
const char *token; \
int length

Definition at line 48 of file readfuncs.c.

◆ READ_UINT64_FIELD

#define READ_UINT64_FIELD (   fldname)
Value:
token = pg_strtok(&length); /* skip :fldname */ \
token = pg_strtok(&length); /* get field value */ \
local_node->fldname = strtou64(token, NULL, 10)

Definition at line 76 of file readfuncs.c.

◆ READ_UINT_FIELD

#define READ_UINT_FIELD (   fldname)
Value:
token = pg_strtok(&length); /* skip :fldname */ \
token = pg_strtok(&length); /* get field value */ \
local_node->fldname = atoui(token)

Definition at line 64 of file readfuncs.c.

◆ strtobool

#define strtobool (   x)    ((*(x) == 't') ? true : false)

Definition at line 183 of file readfuncs.c.

Function Documentation

◆ _readA_Const()

static A_Const * _readA_Const ( void  )
static

Definition at line 308 of file readfuncs.c.

309{
311
312 /* We expect either NULL or :val here */
313 token = pg_strtok(&length);
314 if (length == 4 && strncmp(token, "NULL", 4) == 0)
315 local_node->isnull = true;
316 else
317 {
318 union ValUnion *tmp = nodeRead(NULL, 0);
319
320 /* To forestall valgrind complaints, copy only the valid data */
321 switch (nodeTag(tmp))
322 {
323 case T_Integer:
324 memcpy(&local_node->val, tmp, sizeof(Integer));
325 break;
326 case T_Float:
327 memcpy(&local_node->val, tmp, sizeof(Float));
328 break;
329 case T_Boolean:
330 memcpy(&local_node->val, tmp, sizeof(Boolean));
331 break;
332 case T_String:
333 memcpy(&local_node->val, tmp, sizeof(String));
334 break;
335 case T_BitString:
336 memcpy(&local_node->val, tmp, sizeof(BitString));
337 break;
338 default:
339 elog(ERROR, "unrecognized node type: %d",
340 (int) nodeTag(tmp));
341 break;
342 }
343 }
344
345 READ_LOCATION_FIELD(location);
346
347 READ_DONE();
348}

References elog, ERROR, fb(), nodeRead(), nodeTag, pg_strtok(), READ_DONE, READ_LOCALS, and READ_LOCATION_FIELD.

◆ _readA_Expr()

static A_Expr * _readA_Expr ( void  )
static

Definition at line 455 of file readfuncs.c.

456{
458
459 token = pg_strtok(&length);
460
461 if (length == 3 && strncmp(token, "ANY", 3) == 0)
462 {
463 local_node->kind = AEXPR_OP_ANY;
465 }
466 else if (length == 3 && strncmp(token, "ALL", 3) == 0)
467 {
468 local_node->kind = AEXPR_OP_ALL;
470 }
471 else if (length == 8 && strncmp(token, "DISTINCT", 8) == 0)
472 {
475 }
476 else if (length == 12 && strncmp(token, "NOT_DISTINCT", 12) == 0)
477 {
480 }
481 else if (length == 6 && strncmp(token, "NULLIF", 6) == 0)
482 {
483 local_node->kind = AEXPR_NULLIF;
485 }
486 else if (length == 2 && strncmp(token, "IN", 2) == 0)
487 {
488 local_node->kind = AEXPR_IN;
490 }
491 else if (length == 4 && strncmp(token, "LIKE", 4) == 0)
492 {
493 local_node->kind = AEXPR_LIKE;
495 }
496 else if (length == 5 && strncmp(token, "ILIKE", 5) == 0)
497 {
498 local_node->kind = AEXPR_ILIKE;
500 }
501 else if (length == 7 && strncmp(token, "SIMILAR", 7) == 0)
502 {
505 }
506 else if (length == 7 && strncmp(token, "BETWEEN", 7) == 0)
507 {
510 }
511 else if (length == 11 && strncmp(token, "NOT_BETWEEN", 11) == 0)
512 {
515 }
516 else if (length == 11 && strncmp(token, "BETWEEN_SYM", 11) == 0)
517 {
520 }
521 else if (length == 15 && strncmp(token, "NOT_BETWEEN_SYM", 15) == 0)
522 {
525 }
526 else if (length == 5 && strncmp(token, ":name", 5) == 0)
527 {
528 local_node->kind = AEXPR_OP;
529 local_node->name = nodeRead(NULL, 0);
530 }
531 else
532 elog(ERROR, "unrecognized A_Expr kind: \"%.*s\"", length, token);
533
534 READ_NODE_FIELD(lexpr);
535 READ_NODE_FIELD(rexpr);
536 READ_LOCATION_FIELD(rexpr_list_start);
537 READ_LOCATION_FIELD(rexpr_list_end);
538 READ_LOCATION_FIELD(location);
539
540 READ_DONE();
541}

References AEXPR_BETWEEN, AEXPR_BETWEEN_SYM, AEXPR_DISTINCT, AEXPR_ILIKE, AEXPR_IN, AEXPR_LIKE, AEXPR_NOT_BETWEEN, AEXPR_NOT_BETWEEN_SYM, AEXPR_NOT_DISTINCT, AEXPR_NULLIF, AEXPR_OP, AEXPR_OP_ALL, AEXPR_OP_ANY, AEXPR_SIMILAR, elog, ERROR, fb(), name, nodeRead(), pg_strtok(), READ_DONE, READ_LOCALS, READ_LOCATION_FIELD, and READ_NODE_FIELD.

◆ _readBitmapset()

static Bitmapset * _readBitmapset ( void  )
static

Definition at line 207 of file readfuncs.c.

208{
209 Bitmapset *result = NULL;
210
212
213 token = pg_strtok(&length);
214 if (token == NULL)
215 elog(ERROR, "incomplete Bitmapset structure");
216 if (length != 1 || token[0] != '(')
217 elog(ERROR, "unrecognized token: \"%.*s\"", length, token);
218
219 token = pg_strtok(&length);
220 if (token == NULL)
221 elog(ERROR, "incomplete Bitmapset structure");
222 if (length != 1 || token[0] != 'b')
223 elog(ERROR, "unrecognized token: \"%.*s\"", length, token);
224
225 for (;;)
226 {
227 int val;
228 char *endptr;
229
230 token = pg_strtok(&length);
231 if (token == NULL)
232 elog(ERROR, "unterminated Bitmapset structure");
233 if (length == 1 && token[0] == ')')
234 break;
235 val = (int) strtol(token, &endptr, 10);
236 if (endptr != token + length)
237 elog(ERROR, "unrecognized integer: \"%.*s\"", length, token);
238 result = bms_add_member(result, val);
239 }
240
241 return result;
242}

References bms_add_member(), elog, ERROR, fb(), pg_strtok(), READ_TEMP_LOCALS, and val.

Referenced by readBitmapset().

◆ _readBoolExpr()

static BoolExpr * _readBoolExpr ( void  )
static

Definition at line 285 of file readfuncs.c.

286{
288
289 /* do-it-yourself enum representation */
290 token = pg_strtok(&length); /* skip :boolop */
291 token = pg_strtok(&length); /* get field value */
292 if (length == 3 && strncmp(token, "and", 3) == 0)
293 local_node->boolop = AND_EXPR;
294 else if (length == 2 && strncmp(token, "or", 2) == 0)
295 local_node->boolop = OR_EXPR;
296 else if (length == 3 && strncmp(token, "not", 3) == 0)
297 local_node->boolop = NOT_EXPR;
298 else
299 elog(ERROR, "unrecognized boolop \"%.*s\"", length, token);
300
301 READ_NODE_FIELD(args);
302 READ_LOCATION_FIELD(location);
303
304 READ_DONE();
305}

References AND_EXPR, elog, ERROR, fb(), NOT_EXPR, OR_EXPR, pg_strtok(), READ_DONE, READ_LOCALS, READ_LOCATION_FIELD, and READ_NODE_FIELD.

◆ _readConst()

static Const * _readConst ( void  )
static

Definition at line 263 of file readfuncs.c.

264{
266
267 READ_OID_FIELD(consttype);
273 READ_LOCATION_FIELD(location);
274
275 token = pg_strtok(&length); /* skip :constvalue */
276 if (local_node->constisnull)
277 token = pg_strtok(&length); /* skip "<>" */
278 else
279 local_node->constvalue = readDatum(local_node->constbyval);
280
281 READ_DONE();
282}

References fb(), pg_strtok(), READ_BOOL_FIELD, READ_DONE, READ_INT_FIELD, READ_LOCALS, READ_LOCATION_FIELD, READ_OID_FIELD, and readDatum().

◆ _readExtensibleNode()

static ExtensibleNode * _readExtensibleNode ( void  )
static

Definition at line 544 of file readfuncs.c.

545{
546 const ExtensibleNodeMethods *methods;
548 const char *extnodename;
549
551
552 token = pg_strtok(&length); /* skip :extnodename */
553 token = pg_strtok(&length); /* get extnodename */
554
555 extnodename = nullable_string(token, length);
556 if (!extnodename)
557 elog(ERROR, "extnodename has to be supplied");
558 methods = GetExtensibleNodeMethods(extnodename, false);
559
562 local_node->extnodename = extnodename;
563
564 /* deserialize the private fields */
565 methods->nodeRead(local_node);
566
567 READ_DONE();
568}

References elog, ERROR, fb(), GetExtensibleNodeMethods(), newNode(), ExtensibleNodeMethods::node_size, ExtensibleNodeMethods::nodeRead, nullable_string(), pg_strtok(), READ_DONE, and READ_TEMP_LOCALS.

◆ _readRangeTblEntry()

static RangeTblEntry * _readRangeTblEntry ( void  )
static

Definition at line 351 of file readfuncs.c.

352{
354
355 READ_NODE_FIELD(alias);
357 READ_ENUM_FIELD(rtekind, RTEKind);
358
359 switch (local_node->rtekind)
360 {
361 case RTE_RELATION:
362 READ_OID_FIELD(relid);
363 READ_BOOL_FIELD(inh);
364 READ_CHAR_FIELD(relkind);
367 READ_NODE_FIELD(tablesample);
368 break;
369 case RTE_SUBQUERY:
370 READ_NODE_FIELD(subquery);
371 READ_BOOL_FIELD(security_barrier);
372 /* we re-use these RELATION fields, too: */
373 READ_OID_FIELD(relid);
374 READ_BOOL_FIELD(inh);
375 READ_CHAR_FIELD(relkind);
378 break;
379 case RTE_JOIN:
380 READ_ENUM_FIELD(jointype, JoinType);
386 break;
387 case RTE_FUNCTION:
389 READ_BOOL_FIELD(funcordinality);
390 break;
391 case RTE_TABLEFUNC:
392 READ_NODE_FIELD(tablefunc);
393 /* The RTE must have a copy of the column type info, if any */
394 if (local_node->tablefunc)
395 {
396 TableFunc *tf = local_node->tablefunc;
397
398 local_node->coltypes = tf->coltypes;
399 local_node->coltypmods = tf->coltypmods;
400 local_node->colcollations = tf->colcollations;
401 }
402 break;
403 case RTE_VALUES:
404 READ_NODE_FIELD(values_lists);
408 break;
409 case RTE_CTE:
410 READ_STRING_FIELD(ctename);
411 READ_UINT_FIELD(ctelevelsup);
416 break;
418 READ_STRING_FIELD(enrname);
419 READ_FLOAT_FIELD(enrtuples);
423 /* we re-use these RELATION fields, too: */
424 READ_OID_FIELD(relid);
425 break;
426 case RTE_GRAPH_TABLE:
427 READ_NODE_FIELD(graph_pattern);
428 READ_NODE_FIELD(graph_table_columns);
429 /* we re-use these RELATION fields, too: */
430 READ_OID_FIELD(relid);
431 READ_CHAR_FIELD(relkind);
434 break;
435 case RTE_RESULT:
436 /* no extra fields */
437 break;
438 case RTE_GROUP:
439 READ_NODE_FIELD(groupexprs);
440 break;
441 default:
442 elog(ERROR, "unrecognized RTE kind: %d",
443 (int) local_node->rtekind);
444 break;
445 }
446
447 READ_BOOL_FIELD(lateral);
450
451 READ_DONE();
452}

References elog, ERROR, fb(), functions, READ_BOOL_FIELD, READ_CHAR_FIELD, READ_DONE, READ_ENUM_FIELD, READ_FLOAT_FIELD, READ_INT_FIELD, READ_LOCALS, READ_NODE_FIELD, READ_OID_FIELD, READ_STRING_FIELD, READ_UINT_FIELD, RTE_CTE, RTE_FUNCTION, RTE_GRAPH_TABLE, RTE_GROUP, RTE_JOIN, RTE_NAMEDTUPLESTORE, RTE_RELATION, RTE_RESULT, RTE_SUBQUERY, RTE_TABLEFUNC, and RTE_VALUES.

◆ nullable_string()

static char * nullable_string ( const char token,
int  length 
)
static

Definition at line 186 of file readfuncs.c.

187{
188 /* outToken emits <> for NULL, and pg_strtok makes that an empty string */
189 if (length == 0)
190 return NULL;
191 /* outToken emits "" for empty string */
192 if (length == 2 && token[0] == '"' && token[1] == '"')
193 return pstrdup("");
194 /* otherwise, we must remove protective backslashes added by outToken */
195 return debackslash(token, length);
196}

References debackslash(), fb(), and pstrdup().

Referenced by _readExtensibleNode().

◆ parseNodeString()

Node * parseNodeString ( void  )

Definition at line 580 of file readfuncs.c.

581{
583
584 /* Guard against stack overflow due to overly complex expressions */
586
587 token = pg_strtok(&length);
588
589#define MATCH(tokname, namelen) \
590 (length == namelen && memcmp(token, tokname, namelen) == 0)
591
592#include "readfuncs.switch.c"
593
594 elog(ERROR, "badly formatted node string \"%.32s\"...", token);
595 return NULL; /* keep compiler quiet */
596}

References check_stack_depth(), elog, ERROR, fb(), pg_strtok(), and READ_TEMP_LOCALS.

Referenced by nodeRead().

◆ readBitmapset()

Bitmapset * readBitmapset ( void  )

Definition at line 249 of file readfuncs.c.

250{
251 return _readBitmapset();
252}

References _readBitmapset().

◆ readDatum()

Datum readDatum ( bool  typbyval)

Definition at line 607 of file readfuncs.c.

608{
609 Size length;
610 int tokenLength;
611 const char *token;
612 Datum res;
613 char *s;
614
615 /*
616 * read the actual length of the value
617 */
619 length = atoui(token);
620
621 token = pg_strtok(&tokenLength); /* read the '[' */
622 if (token == NULL || token[0] != '[')
623 elog(ERROR, "expected \"[\" to start datum, but got \"%s\"; length = %zu",
624 token ? token : "[NULL]", length);
625
626 if (typbyval)
627 {
628 if (length > (Size) sizeof(Datum))
629 elog(ERROR, "byval datum but length = %zu", length);
630 res = (Datum) 0;
631 s = (char *) (&res);
632 for (Size i = 0; i < (Size) sizeof(Datum); i++)
633 {
635 s[i] = (char) atoi(token);
636 }
637 }
638 else if (length <= 0)
639 res = (Datum) 0;
640 else
641 {
642 s = (char *) palloc(length);
643 for (Size i = 0; i < length; i++)
644 {
646 s[i] = (char) atoi(token);
647 }
648 res = PointerGetDatum(s);
649 }
650
651 token = pg_strtok(&tokenLength); /* read the ']' */
652 if (token == NULL || token[0] != ']')
653 elog(ERROR, "expected \"]\" to end datum, but got \"%s\"; length = %zu",
654 token ? token : "[NULL]", length);
655
656 return res;
657}

References atoui, elog, ERROR, fb(), i, palloc(), pg_strtok(), PointerGetDatum(), and token.

Referenced by _readConst().