diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2023-01-05 14:12:17 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2023-01-05 14:12:17 -0500 |
commit | 3706cc97aa36bb65fd82dbfc79ca809033bcad1f (patch) | |
tree | 8abc1f1e246198923bcef97ffb7fcc66020cd4ec /src/backend/optimizer/util/plancat.c | |
parent | aa26980ca0813200c25b06e3ad0f54d449cce8b2 (diff) | |
download | postgresql-3706cc97aa36bb65fd82dbfc79ca809033bcad1f.tar.gz postgresql-3706cc97aa36bb65fd82dbfc79ca809033bcad1f.zip |
Fix calculation of which GENERATED columns need to be updated.
We were identifying the updatable generated columns of inheritance
children by transposing the calculation made for their parent.
However, there's nothing that says a traditional-inheritance child
can't have generated columns that aren't there in its parent, or that
have different dependencies than are in the parent's expression.
(At present it seems that we don't enforce that for partitioning
either, which is likely wrong to some degree or other; but the case
clearly needs to be handled with traditional inheritance.)
Hence, drop the very-klugy-anyway "extraUpdatedCols" RTE field
in favor of identifying which generated columns depend on updated
columns during executor startup. In HEAD we can remove
extraUpdatedCols altogether; in back branches, it's still there but
always empty. Another difference between the HEAD and back-branch
versions of this patch is that in HEAD we can add the new bitmap field
to ResultRelInfo, but that would cause an ABI break in back branches.
Like 4b3e37993, add a List field at the end of struct EState instead.
Back-patch to v13. The bogus calculation is also being made in v12,
but it doesn't have the same visible effect because we don't use it
to decide which generated columns to recalculate; as a consequence of
which the patch doesn't apply easily. I think that there might still
be a demonstrable bug associated with trigger firing conditions, but
that's such a weird corner-case usage that I'm content to leave it
unfixed in v12.
Amit Langote and Tom Lane
Discussion: https://postgr.es/m/CA+HiwqFshLKNvQUd1DgwJ-7tsTp=dwv7KZqXC4j2wYBV1aCDUA@mail.gmail.com
Discussion: https://postgr.es/m/2793383.1672944799@sss.pgh.pa.us
Diffstat (limited to 'src/backend/optimizer/util/plancat.c')
-rw-r--r-- | src/backend/optimizer/util/plancat.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index c328a2f9129..419f2ac55fa 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -2198,6 +2198,11 @@ has_row_triggers(PlannerInfo *root, Index rti, CmdType event) return result; } +/* + * has_stored_generated_columns + * + * Does table identified by RTI have any STORED GENERATED columns? + */ bool has_stored_generated_columns(PlannerInfo *root, Index rti) { @@ -2218,6 +2223,57 @@ has_stored_generated_columns(PlannerInfo *root, Index rti) } /* + * get_dependent_generated_columns + * + * Get the column numbers of any STORED GENERATED columns of the relation + * that depend on any column listed in target_cols. Both the input and + * result bitmapsets contain column numbers offset by + * FirstLowInvalidHeapAttributeNumber. + */ +Bitmapset * +get_dependent_generated_columns(PlannerInfo *root, Index rti, + Bitmapset *target_cols) +{ + Bitmapset *dependentCols = NULL; + RangeTblEntry *rte = planner_rt_fetch(rti, root); + Relation relation; + TupleDesc tupdesc; + TupleConstr *constr; + + /* Assume we already have adequate lock */ + relation = table_open(rte->relid, NoLock); + + tupdesc = RelationGetDescr(relation); + constr = tupdesc->constr; + + if (constr && constr->has_generated_stored) + { + for (int i = 0; i < constr->num_defval; i++) + { + AttrDefault *defval = &constr->defval[i]; + Node *expr; + Bitmapset *attrs_used = NULL; + + /* skip if not generated column */ + if (!TupleDescAttr(tupdesc, defval->adnum - 1)->attgenerated) + continue; + + /* identify columns this generated column depends on */ + expr = stringToNode(defval->adbin); + pull_varattnos(expr, 1, &attrs_used); + + if (bms_overlap(target_cols, attrs_used)) + dependentCols = bms_add_member(dependentCols, + defval->adnum - FirstLowInvalidHeapAttributeNumber); + } + } + + table_close(relation, NoLock); + + return dependentCols; +} + +/* * set_relation_partition_info * * Set partitioning scheme and related information for a partitioned table. |