diff options
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/execExprInterp.c | 4 | ||||
-rw-r--r-- | src/backend/executor/execMain.c | 5 | ||||
-rw-r--r-- | src/backend/executor/execUtils.c | 4 | ||||
-rw-r--r-- | src/backend/executor/nodeModifyTable.c | 41 |
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; |