diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/optimizer/plan/setrefs.c | 6 | ||||
-rw-r--r-- | src/backend/parser/analyze.c | 33 | ||||
-rw-r--r-- | src/backend/replication/logical/worker.c | 5 | ||||
-rw-r--r-- | src/backend/rewrite/rewriteHandler.c | 41 |
4 files changed, 46 insertions, 39 deletions
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index 8b433714259..127ea3d856d 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -438,9 +438,9 @@ flatten_rtes_walker(Node *node, PlannerGlobal *glob) * In the flat rangetable, we zero out substructure pointers that are not * needed by the executor; this reduces the storage space and copying cost * for cached plans. We keep only the ctename, alias and eref Alias fields, - * which are needed by EXPLAIN, and the selectedCols, insertedCols and - * updatedCols bitmaps, which are needed for executor-startup permissions - * checking and for trigger event checking. + * which are needed by EXPLAIN, and the selectedCols, insertedCols, + * updatedCols, and extraUpdatedCols bitmaps, which are needed for + * executor-startup permissions checking and for trigger event checking. */ static void add_rte_to_flat_rtable(PlannerGlobal *glob, RangeTblEntry *rte) diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 98a83db8b5c..575e22ce0d2 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -2282,7 +2282,6 @@ transformUpdateTargetList(ParseState *pstate, List *origTlist) RangeTblEntry *target_rte; ListCell *orig_tl; ListCell *tl; - TupleDesc tupdesc = pstate->p_target_relation->rd_att; tlist = transformTargetList(pstate, origTlist, EXPR_KIND_UPDATE_SOURCE); @@ -2341,42 +2340,10 @@ transformUpdateTargetList(ParseState *pstate, List *origTlist) if (orig_tl != NULL) elog(ERROR, "UPDATE target count mismatch --- internal error"); - fill_extraUpdatedCols(target_rte, tupdesc); - return tlist; } /* - * Record in extraUpdatedCols generated columns referencing updated base - * columns. - */ -void -fill_extraUpdatedCols(RangeTblEntry *target_rte, TupleDesc tupdesc) -{ - if (tupdesc->constr && - tupdesc->constr->has_generated_stored) - { - for (int i = 0; i < tupdesc->constr->num_defval; i++) - { - AttrDefault defval = tupdesc->constr->defval[i]; - Node *expr; - Bitmapset *attrs_used = NULL; - - /* skip if not generated column */ - if (!TupleDescAttr(tupdesc, defval.adnum - 1)->attgenerated) - continue; - - expr = stringToNode(defval.adbin); - pull_varattnos(expr, 1, &attrs_used); - - if (bms_overlap(target_rte->updatedCols, attrs_used)) - target_rte->extraUpdatedCols = bms_add_member(target_rte->extraUpdatedCols, - defval.adnum - FirstLowInvalidHeapAttributeNumber); - } - } -} - -/* * transformReturningList - * handle a RETURNING clause in INSERT/UPDATE/DELETE */ diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c index 3a5b733ee38..b0f27e0af85 100644 --- a/src/backend/replication/logical/worker.c +++ b/src/backend/replication/logical/worker.c @@ -81,8 +81,6 @@ #include "miscadmin.h" #include "nodes/makefuncs.h" #include "optimizer/optimizer.h" -#include "parser/analyze.h" -#include "parser/parse_relation.h" #include "pgstat.h" #include "postmaster/bgworker.h" #include "postmaster/interrupt.h" @@ -1323,7 +1321,8 @@ apply_handle_update(StringInfo s) } } - fill_extraUpdatedCols(target_rte, RelationGetDescr(rel->localrel)); + /* Also populate extraUpdatedCols, in case we have generated columns */ + fill_extraUpdatedCols(target_rte, rel->localrel); PushActiveSnapshot(GetTransactionSnapshot()); diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index 1faaafab08a..41dd670572d 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -30,6 +30,7 @@ #include "miscadmin.h" #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" +#include "optimizer/optimizer.h" #include "parser/analyze.h" #include "parser/parse_coerce.h" #include "parser/parse_relation.h" @@ -1508,6 +1509,42 @@ rewriteTargetListUD(Query *parsetree, RangeTblEntry *target_rte, } } +/* + * Record in target_rte->extraUpdatedCols the indexes of any generated columns + * that depend on any columns mentioned in target_rte->updatedCols. + */ +void +fill_extraUpdatedCols(RangeTblEntry *target_rte, Relation target_relation) +{ + TupleDesc tupdesc = RelationGetDescr(target_relation); + TupleConstr *constr = tupdesc->constr; + + target_rte->extraUpdatedCols = NULL; + + 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_rte->updatedCols, attrs_used)) + target_rte->extraUpdatedCols = + bms_add_member(target_rte->extraUpdatedCols, + defval->adnum - FirstLowInvalidHeapAttributeNumber); + } + } +} + /* * matchLocks - @@ -1639,6 +1676,7 @@ ApplyRetrieveRule(Query *parsetree, rte->selectedCols = NULL; rte->insertedCols = NULL; rte->updatedCols = NULL; + rte->extraUpdatedCols = NULL; /* * For the most part, Vars referencing the view should remain as @@ -3617,6 +3655,9 @@ RewriteQuery(Query *parsetree, List *rewrite_events) parsetree->override, rt_entry_relation, parsetree->resultRelation); + + /* Also populate extraUpdatedCols (for generated columns) */ + fill_extraUpdatedCols(rt_entry, rt_entry_relation); } else if (event == CMD_DELETE) { |