Skip to content

Commit a6bc330

Browse files
committed
Add read support for some missing raw parse nodes
The node types A_Const, Constraint, and A_Expr had custom output functions, but no read functions were implemented so far. The A_Expr output format had to be tweaked a bit to make it easier to parse. Be a bit more cautious about applying strncmp to unterminated strings. Also error out if an unrecognized enum value is found in each case, instead of just printing a placeholder value. That was maybe ok for debugging but won't work if we want to have robust round-tripping. Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us> Discussion: https://www.postgresql.org/message-id/flat/4159834.1657405226@sss.pgh.pa.us
1 parent 2cb1a5a commit a6bc330

File tree

3 files changed

+253
-11
lines changed

3 files changed

+253
-11
lines changed

src/backend/nodes/outfuncs.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -548,12 +548,12 @@ _outA_Expr(StringInfo str, const A_Expr *node)
548548
WRITE_NODE_FIELD(name);
549549
break;
550550
case AEXPR_OP_ANY:
551-
WRITE_NODE_FIELD(name);
552551
appendStringInfoString(str, " ANY");
552+
WRITE_NODE_FIELD(name);
553553
break;
554554
case AEXPR_OP_ALL:
555-
WRITE_NODE_FIELD(name);
556555
appendStringInfoString(str, " ALL");
556+
WRITE_NODE_FIELD(name);
557557
break;
558558
case AEXPR_DISTINCT:
559559
appendStringInfoString(str, " DISTINCT");
@@ -600,7 +600,7 @@ _outA_Expr(StringInfo str, const A_Expr *node)
600600
WRITE_NODE_FIELD(name);
601601
break;
602602
default:
603-
appendStringInfoString(str, " ??");
603+
elog(ERROR, "unrecognized A_Expr_Kind: %d", (int) node->kind);
604604
break;
605605
}
606606

@@ -782,8 +782,7 @@ _outConstraint(StringInfo str, const Constraint *node)
782782
break;
783783

784784
default:
785-
appendStringInfo(str, "<unrecognized_constraint %d>",
786-
(int) node->contype);
785+
elog(ERROR, "unrecognized ConstrType: %d", (int) node->contype);
787786
break;
788787
}
789788
}

src/backend/nodes/readfuncs.c

Lines changed: 246 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -270,11 +270,11 @@ _readBoolExpr(void)
270270
/* do-it-yourself enum representation */
271271
token = pg_strtok(&length); /* skip :boolop */
272272
token = pg_strtok(&length); /* get field value */
273-
if (strncmp(token, "and", 3) == 0)
273+
if (length == 3 && strncmp(token, "and", 3) == 0)
274274
local_node->boolop = AND_EXPR;
275-
else if (strncmp(token, "or", 2) == 0)
275+
else if (length == 2 && strncmp(token, "or", 2) == 0)
276276
local_node->boolop = OR_EXPR;
277-
else if (strncmp(token, "not", 3) == 0)
277+
else if (length == 3 && strncmp(token, "not", 3) == 0)
278278
local_node->boolop = NOT_EXPR;
279279
else
280280
elog(ERROR, "unrecognized boolop \"%.*s\"", length, token);
@@ -285,6 +285,162 @@ _readBoolExpr(void)
285285
READ_DONE();
286286
}
287287

288+
static A_Const *
289+
_readA_Const(void)
290+
{
291+
READ_LOCALS(A_Const);
292+
293+
token = pg_strtok(&length);
294+
if (length == 4 && strncmp(token, "NULL", 4) == 0)
295+
local_node->isnull = true;
296+
else
297+
{
298+
union ValUnion *tmp = nodeRead(NULL, 0);
299+
300+
memcpy(&local_node->val, tmp, sizeof(*tmp));
301+
}
302+
303+
READ_LOCATION_FIELD(location);
304+
305+
READ_DONE();
306+
}
307+
308+
/*
309+
* _readConstraint
310+
*/
311+
static Constraint *
312+
_readConstraint(void)
313+
{
314+
READ_LOCALS(Constraint);
315+
316+
READ_STRING_FIELD(conname);
317+
READ_BOOL_FIELD(deferrable);
318+
READ_BOOL_FIELD(initdeferred);
319+
READ_LOCATION_FIELD(location);
320+
321+
token = pg_strtok(&length); /* skip :contype */
322+
token = pg_strtok(&length); /* get field value */
323+
if (length == 4 && strncmp(token, "NULL", 4) == 0)
324+
local_node->contype = CONSTR_NULL;
325+
else if (length == 8 && strncmp(token, "NOT_NULL", 8) == 0)
326+
local_node->contype = CONSTR_NOTNULL;
327+
else if (length == 7 && strncmp(token, "DEFAULT", 7) == 0)
328+
local_node->contype = CONSTR_DEFAULT;
329+
else if (length == 8 && strncmp(token, "IDENTITY", 8) == 0)
330+
local_node->contype = CONSTR_IDENTITY;
331+
else if (length == 9 && strncmp(token, "GENERATED", 9) == 0)
332+
local_node->contype = CONSTR_GENERATED;
333+
else if (length == 5 && strncmp(token, "CHECK", 5) == 0)
334+
local_node->contype = CONSTR_CHECK;
335+
else if (length == 11 && strncmp(token, "PRIMARY_KEY", 11) == 0)
336+
local_node->contype = CONSTR_PRIMARY;
337+
else if (length == 6 && strncmp(token, "UNIQUE", 6) == 0)
338+
local_node->contype = CONSTR_UNIQUE;
339+
else if (length == 9 && strncmp(token, "EXCLUSION", 9) == 0)
340+
local_node->contype = CONSTR_EXCLUSION;
341+
else if (length == 11 && strncmp(token, "FOREIGN_KEY", 11) == 0)
342+
local_node->contype = CONSTR_FOREIGN;
343+
else if (length == 15 && strncmp(token, "ATTR_DEFERRABLE", 15) == 0)
344+
local_node->contype = CONSTR_ATTR_DEFERRABLE;
345+
else if (length == 19 && strncmp(token, "ATTR_NOT_DEFERRABLE", 19) == 0)
346+
local_node->contype = CONSTR_ATTR_NOT_DEFERRABLE;
347+
else if (length == 13 && strncmp(token, "ATTR_DEFERRED", 13) == 0)
348+
local_node->contype = CONSTR_ATTR_DEFERRED;
349+
else if (length == 14 && strncmp(token, "ATTR_IMMEDIATE", 14) == 0)
350+
local_node->contype = CONSTR_ATTR_IMMEDIATE;
351+
352+
switch (local_node->contype)
353+
{
354+
case CONSTR_NULL:
355+
case CONSTR_NOTNULL:
356+
/* no extra fields */
357+
break;
358+
359+
case CONSTR_DEFAULT:
360+
READ_NODE_FIELD(raw_expr);
361+
READ_STRING_FIELD(cooked_expr);
362+
break;
363+
364+
case CONSTR_IDENTITY:
365+
READ_NODE_FIELD(options);
366+
READ_CHAR_FIELD(generated_when);
367+
break;
368+
369+
case CONSTR_GENERATED:
370+
READ_NODE_FIELD(raw_expr);
371+
READ_STRING_FIELD(cooked_expr);
372+
READ_CHAR_FIELD(generated_when);
373+
break;
374+
375+
case CONSTR_CHECK:
376+
READ_BOOL_FIELD(is_no_inherit);
377+
READ_NODE_FIELD(raw_expr);
378+
READ_STRING_FIELD(cooked_expr);
379+
READ_BOOL_FIELD(skip_validation);
380+
READ_BOOL_FIELD(initially_valid);
381+
break;
382+
383+
case CONSTR_PRIMARY:
384+
READ_NODE_FIELD(keys);
385+
READ_NODE_FIELD(including);
386+
READ_NODE_FIELD(options);
387+
READ_STRING_FIELD(indexname);
388+
READ_STRING_FIELD(indexspace);
389+
READ_BOOL_FIELD(reset_default_tblspc);
390+
/* access_method and where_clause not currently used */
391+
break;
392+
393+
case CONSTR_UNIQUE:
394+
READ_BOOL_FIELD(nulls_not_distinct);
395+
READ_NODE_FIELD(keys);
396+
READ_NODE_FIELD(including);
397+
READ_NODE_FIELD(options);
398+
READ_STRING_FIELD(indexname);
399+
READ_STRING_FIELD(indexspace);
400+
READ_BOOL_FIELD(reset_default_tblspc);
401+
/* access_method and where_clause not currently used */
402+
break;
403+
404+
case CONSTR_EXCLUSION:
405+
READ_NODE_FIELD(exclusions);
406+
READ_NODE_FIELD(including);
407+
READ_NODE_FIELD(options);
408+
READ_STRING_FIELD(indexname);
409+
READ_STRING_FIELD(indexspace);
410+
READ_BOOL_FIELD(reset_default_tblspc);
411+
READ_STRING_FIELD(access_method);
412+
READ_NODE_FIELD(where_clause);
413+
break;
414+
415+
case CONSTR_FOREIGN:
416+
READ_NODE_FIELD(pktable);
417+
READ_NODE_FIELD(fk_attrs);
418+
READ_NODE_FIELD(pk_attrs);
419+
READ_CHAR_FIELD(fk_matchtype);
420+
READ_CHAR_FIELD(fk_upd_action);
421+
READ_CHAR_FIELD(fk_del_action);
422+
READ_NODE_FIELD(fk_del_set_cols);
423+
READ_NODE_FIELD(old_conpfeqop);
424+
READ_OID_FIELD(old_pktable_oid);
425+
READ_BOOL_FIELD(skip_validation);
426+
READ_BOOL_FIELD(initially_valid);
427+
break;
428+
429+
case CONSTR_ATTR_DEFERRABLE:
430+
case CONSTR_ATTR_NOT_DEFERRABLE:
431+
case CONSTR_ATTR_DEFERRED:
432+
case CONSTR_ATTR_IMMEDIATE:
433+
/* no extra fields */
434+
break;
435+
436+
default:
437+
elog(ERROR, "unrecognized ConstrType: %d", (int) local_node->contype);
438+
break;
439+
}
440+
441+
READ_DONE();
442+
}
443+
288444
static RangeTblEntry *
289445
_readRangeTblEntry(void)
290446
{
@@ -376,6 +532,93 @@ _readRangeTblEntry(void)
376532
READ_DONE();
377533
}
378534

535+
static A_Expr *
536+
_readA_Expr(void)
537+
{
538+
READ_LOCALS(A_Expr);
539+
540+
token = pg_strtok(&length);
541+
542+
if (length == 3 && strncmp(token, "ANY", 3) == 0)
543+
{
544+
local_node->kind = AEXPR_OP_ANY;
545+
READ_NODE_FIELD(name);
546+
}
547+
else if (length == 3 && strncmp(token, "ALL", 3) == 0)
548+
{
549+
local_node->kind = AEXPR_OP_ALL;
550+
READ_NODE_FIELD(name);
551+
}
552+
else if (length == 8 && strncmp(token, "DISTINCT", 8) == 0)
553+
{
554+
local_node->kind = AEXPR_DISTINCT;
555+
READ_NODE_FIELD(name);
556+
}
557+
else if (length == 12 && strncmp(token, "NOT_DISTINCT", 12) == 0)
558+
{
559+
local_node->kind = AEXPR_NOT_DISTINCT;
560+
READ_NODE_FIELD(name);
561+
}
562+
else if (length == 6 && strncmp(token, "NULLIF", 6) == 0)
563+
{
564+
local_node->kind = AEXPR_NULLIF;
565+
READ_NODE_FIELD(name);
566+
}
567+
else if (length == 2 && strncmp(token, "IN", 2) == 0)
568+
{
569+
local_node->kind = AEXPR_IN;
570+
READ_NODE_FIELD(name);
571+
}
572+
else if (length == 4 && strncmp(token, "LIKE", 4) == 0)
573+
{
574+
local_node->kind = AEXPR_LIKE;
575+
READ_NODE_FIELD(name);
576+
}
577+
else if (length == 5 && strncmp(token, "ILIKE", 5) == 0)
578+
{
579+
local_node->kind = AEXPR_ILIKE;
580+
READ_NODE_FIELD(name);
581+
}
582+
else if (length == 7 && strncmp(token, "SIMILAR", 7) == 0)
583+
{
584+
local_node->kind = AEXPR_SIMILAR;
585+
READ_NODE_FIELD(name);
586+
}
587+
else if (length == 7 && strncmp(token, "BETWEEN", 7) == 0)
588+
{
589+
local_node->kind = AEXPR_BETWEEN;
590+
READ_NODE_FIELD(name);
591+
}
592+
else if (length == 11 && strncmp(token, "NOT_BETWEEN", 11) == 0)
593+
{
594+
local_node->kind = AEXPR_NOT_BETWEEN;
595+
READ_NODE_FIELD(name);
596+
}
597+
else if (length == 11 && strncmp(token, "BETWEEN_SYM", 11) == 0)
598+
{
599+
local_node->kind = AEXPR_BETWEEN_SYM;
600+
READ_NODE_FIELD(name);
601+
}
602+
else if (length == 15 && strncmp(token, "NOT_BETWEEN_SYM", 15) == 0)
603+
{
604+
local_node->kind = AEXPR_NOT_BETWEEN_SYM;
605+
READ_NODE_FIELD(name);
606+
}
607+
else if (length == 5 && strncmp(token, ":name", 5) == 0)
608+
{
609+
local_node->kind = AEXPR_OP;
610+
local_node->name = nodeRead(NULL, 0);
611+
}
612+
else
613+
elog(ERROR, "unrecognized A_Expr kind: \"%.*s\"", length, token);
614+
615+
READ_NODE_FIELD(lexpr);
616+
READ_NODE_FIELD(rexpr);
617+
READ_LOCATION_FIELD(location);
618+
619+
READ_DONE();
620+
}
621+
379622
static ExtensibleNode *
380623
_readExtensibleNode(void)
381624
{

src/include/nodes/parsenodes.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ typedef enum A_Expr_Kind
291291

292292
typedef struct A_Expr
293293
{
294-
pg_node_attr(custom_read_write, no_read)
294+
pg_node_attr(custom_read_write)
295295

296296
NodeTag type;
297297
A_Expr_Kind kind; /* see above */
@@ -319,7 +319,7 @@ union ValUnion
319319

320320
typedef struct A_Const
321321
{
322-
pg_node_attr(custom_copy_equal, custom_read_write, no_read)
322+
pg_node_attr(custom_copy_equal, custom_read_write)
323323

324324
NodeTag type;
325325
union ValUnion val;
@@ -2332,7 +2332,7 @@ typedef enum ConstrType /* types of constraints */
23322332

23332333
typedef struct Constraint
23342334
{
2335-
pg_node_attr(custom_read_write, no_read)
2335+
pg_node_attr(custom_read_write)
23362336

23372337
NodeTag type;
23382338
ConstrType contype; /* see above */

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy