aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor')
-rw-r--r--src/backend/executor/execExprInterp.c4
-rw-r--r--src/backend/executor/execMain.c5
-rw-r--r--src/backend/executor/execUtils.c4
-rw-r--r--src/backend/executor/nodeModifyTable.c41
4 files changed, 39 insertions, 15 deletions
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index 09f6a5f14c1..1c3477b03c9 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -2324,6 +2324,10 @@ CheckVarSlotCompatibility(TupleTableSlot *slot, int attnum, Oid vartype)
attr = TupleDescAttr(slot_tupdesc, attnum - 1);
+ /* Internal error: somebody forgot to expand it. */
+ if (attr->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
+ elog(ERROR, "unexpected virtual generated column reference");
+
if (attr->attisdropped)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_COLUMN),
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 74ef35cd250..39d80ccfbad 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -1781,6 +1781,7 @@ ExecRelCheck(ResultRelInfo *resultRelInfo,
continue;
checkconstr = stringToNode(check[i].ccbin);
+ checkconstr = (Expr *) expand_generated_columns_in_expr((Node *) checkconstr, rel, 1);
resultRelInfo->ri_ConstraintExprs[i] =
ExecPrepareExpr(checkconstr, estate);
}
@@ -2328,7 +2329,9 @@ ExecBuildSlotValueDescription(Oid reloid,
if (table_perm || column_perm)
{
- if (slot->tts_isnull[i])
+ if (att->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
+ val = "virtual";
+ else if (slot->tts_isnull[i])
val = "null";
else
{
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index c9c756f8568..448fc09aaac 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -1393,8 +1393,8 @@ Bitmapset *
ExecGetExtraUpdatedCols(ResultRelInfo *relinfo, EState *estate)
{
/* Compute the info if we didn't already */
- if (relinfo->ri_GeneratedExprsU == NULL)
- ExecInitStoredGenerated(relinfo, estate, CMD_UPDATE);
+ if (!relinfo->ri_extraUpdatedCols_valid)
+ ExecInitGenerated(relinfo, estate, CMD_UPDATE);
return relinfo->ri_extraUpdatedCols;
}
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 349ed2d6d2c..a15e7863b0d 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -391,11 +391,14 @@ ExecCheckTIDVisible(EState *estate,
}
/*
- * Initialize to compute stored generated columns for a tuple
+ * Initialize generated columns handling for a tuple
+ *
+ * This fills the resultRelInfo's ri_GeneratedExprsI/ri_NumGeneratedNeededI or
+ * ri_GeneratedExprsU/ri_NumGeneratedNeededU fields, depending on cmdtype.
+ * This is used only for stored generated columns.
*
- * This fills the resultRelInfo's ri_GeneratedExprsI/ri_NumGeneratedNeededI
- * or ri_GeneratedExprsU/ri_NumGeneratedNeededU fields, depending on cmdtype.
* If cmdType == CMD_UPDATE, the ri_extraUpdatedCols field is filled too.
+ * This is used by both stored and virtual generated columns.
*
* Note: usually, a given query would need only one of ri_GeneratedExprsI and
* ri_GeneratedExprsU per result rel; but MERGE can need both, and so can
@@ -403,9 +406,9 @@ ExecCheckTIDVisible(EState *estate,
* UPDATE and INSERT actions.
*/
void
-ExecInitStoredGenerated(ResultRelInfo *resultRelInfo,
- EState *estate,
- CmdType cmdtype)
+ExecInitGenerated(ResultRelInfo *resultRelInfo,
+ EState *estate,
+ CmdType cmdtype)
{
Relation rel = resultRelInfo->ri_RelationDesc;
TupleDesc tupdesc = RelationGetDescr(rel);
@@ -416,7 +419,7 @@ ExecInitStoredGenerated(ResultRelInfo *resultRelInfo,
MemoryContext oldContext;
/* Nothing to do if no generated columns */
- if (!(tupdesc->constr && tupdesc->constr->has_generated_stored))
+ if (!(tupdesc->constr && (tupdesc->constr->has_generated_stored || tupdesc->constr->has_generated_virtual)))
return;
/*
@@ -442,7 +445,9 @@ ExecInitStoredGenerated(ResultRelInfo *resultRelInfo,
for (int i = 0; i < natts; i++)
{
- if (TupleDescAttr(tupdesc, i)->attgenerated == ATTRIBUTE_GENERATED_STORED)
+ char attgenerated = TupleDescAttr(tupdesc, i)->attgenerated;
+
+ if (attgenerated)
{
Expr *expr;
@@ -467,8 +472,11 @@ ExecInitStoredGenerated(ResultRelInfo *resultRelInfo,
}
/* No luck, so prepare the expression for execution */
- ri_GeneratedExprs[i] = ExecPrepareExpr(expr, estate);
- ri_NumGeneratedNeeded++;
+ if (attgenerated == ATTRIBUTE_GENERATED_STORED)
+ {
+ ri_GeneratedExprs[i] = ExecPrepareExpr(expr, estate);
+ ri_NumGeneratedNeeded++;
+ }
/* If UPDATE, mark column in resultRelInfo->ri_extraUpdatedCols */
if (cmdtype == CMD_UPDATE)
@@ -478,6 +486,13 @@ ExecInitStoredGenerated(ResultRelInfo *resultRelInfo,
}
}
+ if (ri_NumGeneratedNeeded == 0)
+ {
+ /* didn't need it after all */
+ pfree(ri_GeneratedExprs);
+ ri_GeneratedExprs = NULL;
+ }
+
/* Save in appropriate set of fields */
if (cmdtype == CMD_UPDATE)
{
@@ -486,6 +501,8 @@ ExecInitStoredGenerated(ResultRelInfo *resultRelInfo,
resultRelInfo->ri_GeneratedExprsU = ri_GeneratedExprs;
resultRelInfo->ri_NumGeneratedNeededU = ri_NumGeneratedNeeded;
+
+ resultRelInfo->ri_extraUpdatedCols_valid = true;
}
else
{
@@ -526,7 +543,7 @@ ExecComputeStoredGenerated(ResultRelInfo *resultRelInfo,
if (cmdtype == CMD_UPDATE)
{
if (resultRelInfo->ri_GeneratedExprsU == NULL)
- ExecInitStoredGenerated(resultRelInfo, estate, cmdtype);
+ ExecInitGenerated(resultRelInfo, estate, cmdtype);
if (resultRelInfo->ri_NumGeneratedNeededU == 0)
return;
ri_GeneratedExprs = resultRelInfo->ri_GeneratedExprsU;
@@ -534,7 +551,7 @@ ExecComputeStoredGenerated(ResultRelInfo *resultRelInfo,
else
{
if (resultRelInfo->ri_GeneratedExprsI == NULL)
- ExecInitStoredGenerated(resultRelInfo, estate, cmdtype);
+ ExecInitGenerated(resultRelInfo, estate, cmdtype);
/* Early exit is impossible given the prior Assert */
Assert(resultRelInfo->ri_NumGeneratedNeededI > 0);
ri_GeneratedExprs = resultRelInfo->ri_GeneratedExprsI;