From 202203bed6bb5c1965c72710e8df59193b4b5932 Mon Sep 17 00:00:00 2001 From: Matthias van de Meent Date: Wed, 3 Jan 2024 15:24:15 +0100 Subject: [PATCH v1 6/7] NodeSupport: Apply some more defaults/serialization optimizations This reduces raw serialized size of the initdb pg_rewrite.ev_action dataset by 7.5%, it's pglz-compressed dataset by 4%/12kB, and the size of the template0 database by 2 blocks. --- src/backend/nodes/outfuncs.c | 32 +++++++++++++-------------- src/backend/nodes/readfuncs.c | 37 +++++++++++++++++-------------- src/include/nodes/parsenodes.h | 17 +++++++++------ src/include/nodes/pathnodes.h | 2 +- src/include/nodes/primnodes.h | 40 +++++++++++++++++++--------------- 5 files changed, 70 insertions(+), 58 deletions(-) diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index f6cfcc8a4c..83f7e43242 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -457,18 +457,18 @@ _outConst(StringInfo str, const Const *node) WRITE_NODE_TYPE("CONST"); WRITE_OID_FIELD(consttype); - WRITE_INT_FIELD(consttypmod); + WRITE_INT_FIELD_DEFAULT(consttypmod, -1); WRITE_OID_FIELD(constcollid); - WRITE_INT_FIELD(constlen); + WRITE_INT_FIELD_DEFAULT(constlen, -1); WRITE_BOOL_FIELD(constbyval); WRITE_BOOL_FIELD(constisnull); WRITE_LOCATION_FIELD(location); - appendStringInfoString(str, " :constvalue "); - if (node->constisnull) - appendStringInfoString(str, "<>"); - else + if (!node->constisnull) + { + appendStringInfoString(str, " :constvalue "); outDatum(str, node->constvalue, node->constlen, node->constbyval); + } } static void @@ -579,10 +579,10 @@ _outRangeTblEntry(StringInfo str, const RangeTblEntry *node) { case RTE_RELATION: WRITE_OID_FIELD(relid); - WRITE_CHAR_FIELD(relkind); - WRITE_INT_FIELD(rellockmode); + WRITE_CHAR_FIELD_DEFAULT(relkind, 'r'); /* default: 'r'elation */ + WRITE_INT_FIELD_DEFAULT(rellockmode, 1); /* AccessShareLock */ WRITE_NODE_FIELD(tablesample); - WRITE_UINT_FIELD(perminfoindex); + WRITE_UINT_FIELD_DEFAULT(perminfoindex, 1); /* Index starts at 1 */ break; case RTE_SUBQUERY: WRITE_NODE_FIELD(subquery); @@ -591,7 +591,7 @@ _outRangeTblEntry(StringInfo str, const RangeTblEntry *node) WRITE_OID_FIELD(relid); WRITE_CHAR_FIELD(relkind); WRITE_INT_FIELD(rellockmode); - WRITE_UINT_FIELD(perminfoindex); + WRITE_UINT_FIELD_DEFAULT(perminfoindex, 1); /* Index starts at 1 */ break; case RTE_JOIN: WRITE_ENUM_FIELD(jointype, JoinType); @@ -640,8 +640,8 @@ _outRangeTblEntry(StringInfo str, const RangeTblEntry *node) } WRITE_BOOL_FIELD(lateral); - WRITE_BOOL_FIELD(inh); - WRITE_BOOL_FIELD(inFromCl); + WRITE_BOOL_FIELD_DEFAULT(inh, true); /* safe assumption */ + WRITE_BOOL_FIELD_DEFAULT(inFromCl, true); /* safe assumption */ WRITE_NODE_FIELD(securityQuals); } @@ -798,7 +798,7 @@ _outConstraint(StringInfo str, const Constraint *node) WRITE_INT_FIELD(inhcount); WRITE_BOOL_FIELD(is_no_inherit); WRITE_BOOL_FIELD(skip_validation); - WRITE_BOOL_FIELD(initially_valid); + WRITE_BOOL_FIELD_DEFAULT(initially_valid, true); break; case CONSTR_DEFAULT: @@ -826,7 +826,7 @@ _outConstraint(StringInfo str, const Constraint *node) WRITE_NODE_FIELD(raw_expr); WRITE_STRING_FIELD(cooked_expr); WRITE_BOOL_FIELD(skip_validation); - WRITE_BOOL_FIELD(initially_valid); + WRITE_BOOL_FIELD_DEFAULT(initially_valid, true); break; case CONSTR_PRIMARY: @@ -842,7 +842,7 @@ _outConstraint(StringInfo str, const Constraint *node) case CONSTR_UNIQUE: appendStringInfoString(str, "UNIQUE"); - WRITE_BOOL_FIELD(nulls_not_distinct); + WRITE_BOOL_FIELD_DEFAULT(nulls_not_distinct, true); WRITE_NODE_FIELD(keys); WRITE_NODE_FIELD(including); WRITE_NODE_FIELD(options); @@ -876,7 +876,7 @@ _outConstraint(StringInfo str, const Constraint *node) WRITE_NODE_FIELD(old_conpfeqop); WRITE_OID_FIELD(old_pktable_oid); WRITE_BOOL_FIELD(skip_validation); - WRITE_BOOL_FIELD(initially_valid); + WRITE_BOOL_FIELD_DEFAULT(initially_valid, true); break; case CONSTR_ATTR_DEFERRABLE: diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index 4287a7ec6e..19c023fb32 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -356,18 +356,23 @@ _readConst(void) READ_LOCALS(Const); READ_OID_FIELD(consttype); - READ_INT_FIELD(consttypmod); + READ_INT_FIELD_DEFAULT(consttypmod, -1); READ_OID_FIELD(constcollid); - READ_INT_FIELD(constlen); + READ_INT_FIELD_DEFAULT(constlen, -1); READ_BOOL_FIELD(constbyval); READ_BOOL_FIELD(constisnull); READ_LOCATION_FIELD(location); - token = pg_strtok(&length); /* skip :constvalue */ - if (local_node->constisnull) - token = pg_strtok(&length); /* skip "<>" */ - else + if (pg_strtoken_next(":constvalue")) + { + token = pg_strtok(&length); /* skip :constvalue */ + Assert(strncmp(token, ":constvalue", sizeof(":constvalue") - 1) == 0); local_node->constvalue = readDatum(local_node->constbyval); + } + else + { + /* value was omitted */ + } READ_DONE(); } @@ -493,7 +498,7 @@ _readConstraint(void) READ_INT_FIELD(inhcount); READ_BOOL_FIELD(is_no_inherit); READ_BOOL_FIELD(skip_validation); - READ_BOOL_FIELD(initially_valid); + READ_BOOL_FIELD_DEFAULT(initially_valid, true); break; case CONSTR_DEFAULT: @@ -517,7 +522,7 @@ _readConstraint(void) READ_NODE_FIELD(raw_expr); READ_STRING_FIELD(cooked_expr); READ_BOOL_FIELD(skip_validation); - READ_BOOL_FIELD(initially_valid); + READ_BOOL_FIELD_DEFAULT(initially_valid, true); break; case CONSTR_PRIMARY: @@ -531,7 +536,7 @@ _readConstraint(void) break; case CONSTR_UNIQUE: - READ_BOOL_FIELD(nulls_not_distinct); + READ_BOOL_FIELD_DEFAULT(nulls_not_distinct, true); READ_NODE_FIELD(keys); READ_NODE_FIELD(including); READ_NODE_FIELD(options); @@ -563,7 +568,7 @@ _readConstraint(void) READ_NODE_FIELD(old_conpfeqop); READ_OID_FIELD(old_pktable_oid); READ_BOOL_FIELD(skip_validation); - READ_BOOL_FIELD(initially_valid); + READ_BOOL_FIELD_DEFAULT(initially_valid, true); break; case CONSTR_ATTR_DEFERRABLE: @@ -595,10 +600,10 @@ _readRangeTblEntry(void) { case RTE_RELATION: READ_OID_FIELD(relid); - READ_CHAR_FIELD(relkind); - READ_INT_FIELD(rellockmode); + READ_CHAR_FIELD_DEFAULT(relkind, 'r'); + READ_INT_FIELD_DEFAULT(rellockmode, 1); READ_NODE_FIELD(tablesample); - READ_UINT_FIELD(perminfoindex); + READ_UINT_FIELD_DEFAULT(perminfoindex, 1); break; case RTE_SUBQUERY: READ_NODE_FIELD(subquery); @@ -607,7 +612,7 @@ _readRangeTblEntry(void) READ_OID_FIELD(relid); READ_CHAR_FIELD(relkind); READ_INT_FIELD(rellockmode); - READ_UINT_FIELD(perminfoindex); + READ_UINT_FIELD_DEFAULT(perminfoindex, 1); break; case RTE_JOIN: READ_ENUM_FIELD(jointype, JoinType); @@ -666,8 +671,8 @@ _readRangeTblEntry(void) } READ_BOOL_FIELD(lateral); - READ_BOOL_FIELD(inh); - READ_BOOL_FIELD(inFromCl); + READ_BOOL_FIELD_DEFAULT(inh, true); /* safe assumption */ + READ_BOOL_FIELD_DEFAULT(inFromCl, true); /* safe assumption */ READ_NODE_FIELD(securityQuals); READ_DONE(); diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index e11b044b89..dd6508ae84 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -261,7 +261,7 @@ typedef struct TypeName bool setof; /* is a set? */ bool pct_type; /* %TYPE specified? */ List *typmods; /* type modifier expression(s) */ - int32 typemod; /* prespecified type modifier */ + int32 typemod pg_node_attr(default(-1)); /* prespecified type modifier */ List *arrayBounds; /* array bounds */ int location; /* token location, or -1 if unknown */ } TypeName; @@ -556,7 +556,8 @@ typedef struct WindowDef char *refname; /* referenced window name, if any */ List *partitionClause; /* PARTITION BY expression list */ List *orderClause; /* ORDER BY (list of SortBy) */ - int frameOptions; /* frame_clause options, see below */ + /* frame_clause options, see below */ + int frameOptions pg_node_attr(default(FRAMEOPTION_DEFAULTS)); Node *startOffset; /* expression for starting bound, if any */ Node *endOffset; /* expression for ending bound, if any */ int location; /* parse location, or -1 if none/unknown */ @@ -1235,7 +1236,8 @@ typedef struct RTEPermissionInfo NodeTag type; Oid relid; /* relation OID */ - bool inh; /* separately check inheritance children? */ + /* separately check inheritance children? */ + bool inh pg_node_attr(default(true)); /* bitmask of required access permissions, in views usually ACL_SELECT */ AclMode requiredPerms pg_node_attr(default(ACL_SELECT)); Oid checkAsUser; /* if valid, check access as this role */ @@ -1388,8 +1390,8 @@ typedef struct SortGroupClause Oid eqop; /* the equality operator ('=' op) */ Oid sortop; /* the ordering operator ('<' op), or 0 */ bool nulls_first; /* do NULLs come before normal values? */ - /* can eqop be implemented by hashing? */ - bool hashable pg_node_attr(query_jumble_ignore); + /* can eqop be implemented by hashing? (often true for builtin operators) */ + bool hashable pg_node_attr(query_jumble_ignore, default(true)); } SortGroupClause; /* @@ -1491,7 +1493,8 @@ typedef struct WindowClause List *partitionClause; /* PARTITION BY list */ /* ORDER BY list */ List *orderClause; - int frameOptions; /* frame_clause options, see WindowDef */ + /* frame_clause options, see WindowDef */ + int frameOptions pg_node_attr(default(FRAMEOPTION_DEFAULTS)); Node *startOffset; /* expression for starting bound, if any */ Node *endOffset; /* expression for ending bound, if any */ /* qual to help short-circuit execution */ @@ -2025,7 +2028,7 @@ typedef struct SelectStmt typedef struct SetOperationStmt { NodeTag type; - SetOperation op; /* type of set op */ + SetOperation op pg_node_attr(default(1)); /* type of set op */ bool all; /* ALL specified? */ Node *larg; /* left child */ Node *rarg; /* right child */ diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index e688fc2b79..78ee667704 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -3380,7 +3380,7 @@ typedef struct AggTransInfo /* Additional data about transtype */ int32 aggtranstypmod pg_node_attr(default(-1)); - int transtypeLen; + int transtypeLen pg_node_attr(default(-1)); bool transtypeByVal; /* Space-consumption estimate */ diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index acb275900f..bb11231554 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -245,7 +245,7 @@ typedef struct Var /* * attribute number of this var, or zero for all attrs ("whole-row Var") */ - AttrNumber varattno; + AttrNumber varattno pg_node_attr(default(1)); /* pg_type OID for the type of this var */ Oid vartype pg_node_attr(query_jumble_ignore); @@ -305,7 +305,7 @@ typedef struct Const /* OID of collation, or InvalidOid if none */ Oid constcollid pg_node_attr(query_jumble_ignore); /* typlen of the constant's datatype */ - int constlen pg_node_attr(query_jumble_ignore); + int constlen pg_node_attr(query_jumble_ignore, default(-1)); /* the constant's value */ Datum constvalue pg_node_attr(query_jumble_ignore); /* whether the constant is null (if true, constvalue is undefined) */ @@ -364,7 +364,8 @@ typedef struct Param { Expr xpr; ParamKind paramkind; /* kind of parameter. See above */ - int paramid; /* numeric ID for parameter */ + /* numeric ID for parameter */ + int paramid pg_node_attr(default(1)); Oid paramtype; /* pg_type OID of parameter's datatype */ /* typmod value, if known */ int32 paramtypmod pg_node_attr(query_jumble_ignore, default(-1)); @@ -476,7 +477,7 @@ typedef struct Aggref bool aggvariadic pg_node_attr(query_jumble_ignore); /* aggregate kind (see pg_aggregate.h) */ - char aggkind pg_node_attr(query_jumble_ignore); + char aggkind pg_node_attr(query_jumble_ignore, default('n')); /* aggregate input already sorted */ bool aggpresorted pg_node_attr(equal_ignore, query_jumble_ignore); @@ -760,7 +761,7 @@ typedef struct OpExpr Oid opfuncid pg_node_attr(equal_ignore_if_zero, query_jumble_ignore); /* PG_TYPE OID of result value */ - Oid opresulttype pg_node_attr(query_jumble_ignore); + Oid opresulttype pg_node_attr(query_jumble_ignore, default(BOOLOID)); /* true if operator returns set */ bool opretset pg_node_attr(query_jumble_ignore); @@ -845,8 +846,8 @@ typedef struct ScalarArrayOpExpr /* PG_PROC OID of negator of opfuncid function or InvalidOid. See above */ Oid negfuncid pg_node_attr(equal_ignore_if_zero, query_jumble_ignore); - /* true for ANY, false for ALL */ - bool useOr; + /* true for ANY, false for ALL - usually users use ANY */ + bool useOr pg_node_attr(default(true)); /* OID of collation that operator should use */ Oid inputcollid pg_node_attr(query_jumble_ignore); @@ -1127,7 +1128,7 @@ typedef struct RelabelType /* OID of collation, or InvalidOid if none */ Oid resultcollid pg_node_attr(query_jumble_ignore); /* how to display this node */ - CoercionForm relabelformat pg_node_attr(query_jumble_ignore); + CoercionForm relabelformat pg_node_attr(query_jumble_ignore, default(COERCE_EXPLICIT_CAST)); int location; /* token location, or -1 if unknown */ } RelabelType; @@ -1148,8 +1149,8 @@ typedef struct CoerceViaIO /* output typmod is not stored, but is presumed -1 */ /* OID of collation, or InvalidOid if none */ Oid resultcollid pg_node_attr(query_jumble_ignore); - /* how to display this node */ - CoercionForm coerceformat pg_node_attr(query_jumble_ignore); + /* how to display this node, in pg_rewrite this is generally an implicit cast */ + CoercionForm coerceformat pg_node_attr(query_jumble_ignore, default(COERCE_IMPLICIT_CAST)); int location; /* token location, or -1 if unknown */ } CoerceViaIO; @@ -1176,8 +1177,9 @@ typedef struct ArrayCoerceExpr int32 resulttypmod pg_node_attr(query_jumble_ignore, default(-1)); /* OID of collation, or InvalidOid if none */ Oid resultcollid pg_node_attr(query_jumble_ignore); - /* how to display this node */ - CoercionForm coerceformat pg_node_attr(query_jumble_ignore); + /* How to display this node. Arrays don't often have implicit casts, so + * we default to explicit casts */ + CoercionForm coerceformat pg_node_attr(query_jumble_ignore, default(COERCE_EXPLICIT_CAST)); int location; /* token location, or -1 if unknown */ } ArrayCoerceExpr; @@ -1293,7 +1295,7 @@ typedef struct CaseTestExpr Expr xpr; Oid typeId; /* type for substituted value */ /* typemod for substituted value */ - int32 typeMod pg_node_attr(query_jumble_ignore); + int32 typeMod pg_node_attr(query_jumble_ignore, default(-1)); /* collation for the substituted value */ Oid collation pg_node_attr(query_jumble_ignore); } CaseTestExpr; @@ -1702,7 +1704,8 @@ typedef struct NullTest { Expr xpr; Expr *arg; /* input expression */ - NullTestType nulltesttype; /* IS NULL, IS NOT NULL */ + /* IS NULL, IS NOT NULL */ + NullTestType nulltesttype pg_node_attr(default(IS_NOT_NULL)); /* T to perform field-by-field null checks */ bool argisrow pg_node_attr(query_jumble_ignore); int location; /* token location, or -1 if unknown */ @@ -1789,7 +1792,7 @@ typedef struct CoerceToDomainValue /* type for substituted value */ Oid typeId; /* typemod for substituted value */ - int32 typeMod pg_node_attr(query_jumble_ignore); + int32 typeMod pg_node_attr(query_jumble_ignore, default(-1)); /* collation for the substituted value */ Oid collation pg_node_attr(query_jumble_ignore); /* token location, or -1 if unknown */ @@ -1809,7 +1812,7 @@ typedef struct SetToDefault /* type for substituted value */ Oid typeId; /* typemod for substituted value */ - int32 typeMod pg_node_attr(query_jumble_ignore); + int32 typeMod pg_node_attr(query_jumble_ignore, default(-1)); /* collation for the substituted value */ Oid collation pg_node_attr(query_jumble_ignore); /* token location, or -1 if unknown */ @@ -1926,8 +1929,9 @@ typedef struct TargetEntry Expr xpr; /* expression to evaluate */ Expr *expr; - /* attribute number (see notes above) */ - AttrNumber resno; + /* attribute number (see notes above). + * Counting starts at 1, so that's the default for serialization, too. */ + AttrNumber resno pg_node_attr(default(1)); /* name of the column (could be NULL) */ char *resname pg_node_attr(query_jumble_ignore); /* nonzero if referenced by a sort/group clause */ -- 2.40.1