aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/optimizer/plan/setrefs.c6
-rw-r--r--src/backend/parser/analyze.c33
-rw-r--r--src/backend/replication/logical/worker.c5
-rw-r--r--src/backend/rewrite/rewriteHandler.c41
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)
{