From aa730a9d98232517fda500d94311e71bec7beaef Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Fri, 12 Aug 2022 20:10:30 +0200 Subject: [PATCH v1 3/7] 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. 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. --- src/backend/nodes/outfuncs.c | 9 +- src/backend/nodes/readfuncs.c | 247 +++++++++++++++++++++++++++++++++ src/include/nodes/parsenodes.h | 6 +- 3 files changed, 254 insertions(+), 8 deletions(-) diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 60610e3a4b..24ea0487e7 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -548,12 +548,12 @@ _outA_Expr(StringInfo str, const A_Expr *node) WRITE_NODE_FIELD(name); break; case AEXPR_OP_ANY: - WRITE_NODE_FIELD(name); appendStringInfoString(str, " ANY"); + WRITE_NODE_FIELD(name); break; case AEXPR_OP_ALL: - WRITE_NODE_FIELD(name); appendStringInfoString(str, " ALL"); + WRITE_NODE_FIELD(name); break; case AEXPR_DISTINCT: appendStringInfoString(str, " DISTINCT"); @@ -600,7 +600,7 @@ _outA_Expr(StringInfo str, const A_Expr *node) WRITE_NODE_FIELD(name); break; default: - appendStringInfoString(str, " ??"); + elog(ERROR, "unrecognized A_Expr_Kind: %d", (int) node->kind); break; } @@ -782,8 +782,7 @@ _outConstraint(StringInfo str, const Constraint *node) break; default: - appendStringInfo(str, "", - (int) node->contype); + elog(ERROR, "unrecognized ConstrType: %d", (int) node->contype); break; } } diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index bee62fc15c..93049cebb8 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -285,6 +285,162 @@ _readBoolExpr(void) READ_DONE(); } +static A_Const * +_readA_Const(void) +{ + READ_LOCALS(A_Const); + + token = pg_strtok(&length); + if (strncmp(token, "NULL", 4) == 0) + local_node->isnull = true; + else + { + union ValUnion *tmp = nodeRead(NULL, 0); + + memcpy(&local_node->val, tmp, sizeof(*tmp)); + } + + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readConstraint + */ +static Constraint * +_readConstraint(void) +{ + READ_LOCALS(Constraint); + + READ_STRING_FIELD(conname); + READ_BOOL_FIELD(deferrable); + READ_BOOL_FIELD(initdeferred); + READ_LOCATION_FIELD(location); + + token = pg_strtok(&length); /* skip :contype */ + token = pg_strtok(&length); /* get field value */ + if (strncmp(token, "NULL", 4) == 0) + local_node->contype = CONSTR_NULL; + else if (strncmp(token, "NOT_NULL", 8) == 0) + local_node->contype = CONSTR_NOTNULL; + else if (strncmp(token, "DEFAULT", 7) == 0) + local_node->contype = CONSTR_DEFAULT; + else if (strncmp(token, "IDENTITY", 8) == 0) + local_node->contype = CONSTR_IDENTITY; + else if (strncmp(token, "GENERATED", 9) == 0) + local_node->contype = CONSTR_GENERATED; + else if (strncmp(token, "CHECK", 5) == 0) + local_node->contype = CONSTR_CHECK; + else if (strncmp(token, "PRIMARY_KEY", 11) == 0) + local_node->contype = CONSTR_PRIMARY; + else if (strncmp(token, "UNIQUE", 6) == 0) + local_node->contype = CONSTR_UNIQUE; + else if (strncmp(token, "EXCLUSION", 9) == 0) + local_node->contype = CONSTR_EXCLUSION; + else if (strncmp(token, "FOREIGN_KEY", 11) == 0) + local_node->contype = CONSTR_FOREIGN; + else if (strncmp(token, "ATTR_DEFERRABLE", 15) == 0) + local_node->contype = CONSTR_ATTR_DEFERRABLE; + else if (strncmp(token, "ATTR_NOT_DEFERRABLE", 19) == 0) + local_node->contype = CONSTR_ATTR_NOT_DEFERRABLE; + else if (strncmp(token, "ATTR_DEFERRED", 13) == 0) + local_node->contype = CONSTR_ATTR_DEFERRED; + else if (strncmp(token, "ATTR_IMMEDIATE", 14) == 0) + local_node->contype = CONSTR_ATTR_IMMEDIATE; + + switch (local_node->contype) + { + case CONSTR_NULL: + case CONSTR_NOTNULL: + /* no extra fields */ + break; + + case CONSTR_DEFAULT: + READ_NODE_FIELD(raw_expr); + READ_STRING_FIELD(cooked_expr); + break; + + case CONSTR_IDENTITY: + READ_NODE_FIELD(options); + READ_CHAR_FIELD(generated_when); + break; + + case CONSTR_GENERATED: + READ_NODE_FIELD(raw_expr); + READ_STRING_FIELD(cooked_expr); + READ_CHAR_FIELD(generated_when); + break; + + case CONSTR_CHECK: + READ_BOOL_FIELD(is_no_inherit); + READ_NODE_FIELD(raw_expr); + READ_STRING_FIELD(cooked_expr); + READ_BOOL_FIELD(skip_validation); + READ_BOOL_FIELD(initially_valid); + break; + + case CONSTR_PRIMARY: + READ_NODE_FIELD(keys); + READ_NODE_FIELD(including); + READ_NODE_FIELD(options); + READ_STRING_FIELD(indexname); + READ_STRING_FIELD(indexspace); + READ_BOOL_FIELD(reset_default_tblspc); + /* access_method and where_clause not currently used */ + break; + + case CONSTR_UNIQUE: + READ_BOOL_FIELD(nulls_not_distinct); + READ_NODE_FIELD(keys); + READ_NODE_FIELD(including); + READ_NODE_FIELD(options); + READ_STRING_FIELD(indexname); + READ_STRING_FIELD(indexspace); + READ_BOOL_FIELD(reset_default_tblspc); + /* access_method and where_clause not currently used */ + break; + + case CONSTR_EXCLUSION: + READ_NODE_FIELD(exclusions); + READ_NODE_FIELD(including); + READ_NODE_FIELD(options); + READ_STRING_FIELD(indexname); + READ_STRING_FIELD(indexspace); + READ_BOOL_FIELD(reset_default_tblspc); + READ_STRING_FIELD(access_method); + READ_NODE_FIELD(where_clause); + break; + + case CONSTR_FOREIGN: + READ_NODE_FIELD(pktable); + READ_NODE_FIELD(fk_attrs); + READ_NODE_FIELD(pk_attrs); + READ_CHAR_FIELD(fk_matchtype); + READ_CHAR_FIELD(fk_upd_action); + READ_CHAR_FIELD(fk_del_action); + READ_NODE_FIELD(fk_del_set_cols); + READ_NODE_FIELD(old_conpfeqop); + READ_OID_FIELD(old_pktable_oid); + READ_BOOL_FIELD(skip_validation); + READ_BOOL_FIELD(initially_valid); + break; + + case CONSTR_ATTR_DEFERRABLE: + case CONSTR_ATTR_NOT_DEFERRABLE: + case CONSTR_ATTR_DEFERRED: + case CONSTR_ATTR_IMMEDIATE: + /* no extra fields */ + break; + + default: + elog(ERROR, "unrecognized ConstrType: %d", (int) local_node->contype); + break; + } + + READ_DONE(); +} + static RangeTblEntry * _readRangeTblEntry(void) { @@ -376,6 +532,97 @@ _readRangeTblEntry(void) READ_DONE(); } +static A_Expr * +_readA_Expr(void) +{ + READ_LOCALS(A_Expr); + + token = pg_strtok(&length); + + if (strncmp(token, "ANY", 3) == 0) + { + local_node->kind = AEXPR_OP_ANY; + READ_NODE_FIELD(name); + } + else if (strncmp(token, "ALL", 3) == 0) + { + local_node->kind = AEXPR_OP_ALL; + READ_NODE_FIELD(name); + } + else if (strncmp(token, "DISTINCT", 8) == 0) + { + local_node->kind = AEXPR_DISTINCT; + READ_NODE_FIELD(name); + } + else if (strncmp(token, "NOT_DISTINCT", 12) == 0) + { + local_node->kind = AEXPR_NOT_DISTINCT; + READ_NODE_FIELD(name); + } + else if (strncmp(token, "NULLIF", 6) == 0) + { + local_node->kind = AEXPR_NULLIF; + READ_NODE_FIELD(name); + } + else if (strncmp(token, "IN", 2) == 0) + { + local_node->kind = AEXPR_IN; + READ_NODE_FIELD(name); + } + else if (strncmp(token, "LIKE", 4) == 0) + { + local_node->kind = AEXPR_LIKE; + READ_NODE_FIELD(name); + } + else if (strncmp(token, "ILIKE", 5) == 0) + { + local_node->kind = AEXPR_ILIKE; + READ_NODE_FIELD(name); + } + else if (strncmp(token, "SIMILAR", 7) == 0) + { + local_node->kind = AEXPR_SIMILAR; + READ_NODE_FIELD(name); + } + /* + * Note: Order matters, strings that are prefixes of other strings must + * come later. + */ + else if (strncmp(token, "BETWEEN_SYM", 11) == 0) + { + local_node->kind = AEXPR_BETWEEN_SYM; + READ_NODE_FIELD(name); + } + else if (strncmp(token, "NOT_BETWEEN_SYM", 15) == 0) + { + local_node->kind = AEXPR_NOT_BETWEEN_SYM; + READ_NODE_FIELD(name); + } + else if (strncmp(token, "BETWEEN", 7) == 0) + { + local_node->kind = AEXPR_BETWEEN; + READ_NODE_FIELD(name); + } + else if (strncmp(token, "NOT_BETWEEN", 11) == 0) + { + local_node->kind = AEXPR_NOT_BETWEEN; + READ_NODE_FIELD(name); + } + else if (strncmp(token, ":name", 5) == 0) + { + local_node->kind = AEXPR_OP; + local_node->name = nodeRead(NULL, 0); + } + else + elog(ERROR, "unrecognized A_Expr kind: %s", token); + + READ_NODE_FIELD(lexpr); + READ_NODE_FIELD(rexpr); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + static ExtensibleNode * _readExtensibleNode(void) { diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index b376031856..fd308af4e5 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -291,7 +291,7 @@ typedef enum A_Expr_Kind typedef struct A_Expr { - pg_node_attr(custom_read_write, no_read) + pg_node_attr(custom_read_write) NodeTag type; A_Expr_Kind kind; /* see above */ @@ -319,7 +319,7 @@ union ValUnion typedef struct A_Const { - pg_node_attr(custom_copy_equal, custom_read_write, no_read) + pg_node_attr(custom_copy_equal, custom_read_write) NodeTag type; union ValUnion val; @@ -2619,7 +2619,7 @@ typedef enum ConstrType /* types of constraints */ typedef struct Constraint { - pg_node_attr(custom_read_write, no_read) + pg_node_attr(custom_read_write) NodeTag type; ConstrType contype; /* see above */ -- 2.37.1