增加insert语句支持右值字段引用功能

This commit is contained in:
Laishenghao
2022-11-14 15:12:08 +08:00
parent a31f86e583
commit adf53e20bb
16 changed files with 643 additions and 20 deletions

View File

@ -621,13 +621,24 @@ static Datum ExecEvalScalarVar(ExprState* exprstate, ExprContext* econtext, bool
break;
}
Assert(slot != NULL);
attnum = variable->varattno;
/* This was checked by ExecInitExpr */
Assert(attnum != InvalidAttrNumber);
RightRefState* refState = econtext->rightRefState;
int index = attnum - 1;
if (IS_ENABLE_INSERT_RIGHT_REF(refState) ||
(IS_ENABLE_UPSERT_RIGHT_REF(refState) && refState->hasExecs[index] && index < refState->colCnt)) {
*isNull = refState->isNulls[index];
return refState->values[index];
}
if (slot == nullptr) {
ereport(ERROR,(errcode(ERRCODE_INVALID_ATTRIBUTE), errmodule(MOD_EXECUTOR),
errmsg("attribute number %d does not exists.", attnum)));
}
/*
* If it's a user attribute, check validity (bogus system attnums will be
* caught inside table's getattr). What we have to check for here is the
@ -6291,7 +6302,6 @@ static bool ExecTargetList(List* targetlist, ExprContext* econtext, Datum* value
ExprDoneCond* itemIsDone, ExprDoneCond* isDone)
{
MemoryContext oldContext;
ListCell* tl = NULL;
bool haveDoneSets = false;
/*
@ -6299,19 +6309,32 @@ static bool ExecTargetList(List* targetlist, ExprContext* econtext, Datum* value
*/
oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
RightRefState* refState = econtext->rightRefState;
int targetCount = list_length(targetlist);
GenericExprState* targetArr[targetCount];
int colCnt = (IS_ENABLE_RIGHT_REF(refState) && refState->colCnt > 0) ? refState->colCnt : 1;
bool hasExecs[colCnt];
SortTargetListAsArray(refState, targetlist, targetArr);
InitOutputValues(refState, targetArr, values, isnull, targetCount, hasExecs);
/*
* evaluate all the expressions in the target list
*/
haveDoneSets = false; /* any exhausted set exprs in tlist? */
foreach (tl, targetlist) {
GenericExprState* gstate = (GenericExprState*)lfirst(tl);
for (GenericExprState* gstate : targetArr) {
TargetEntry* tle = (TargetEntry*)gstate->xprstate.expr;
AttrNumber resind = tle->resno - 1;
ELOG_FIELD_NAME_START(tle->resname);
values[resind] = ExecEvalExpr(gstate->arg, econtext, &isnull[resind], &itemIsDone[resind]);
if (IS_ENABLE_RIGHT_REF(refState) && resind < refState->colCnt) {
hasExecs[resind] = true;
}
if (T_Var == nodeTag(tle->expr) && !isnull[resind]) {
Var *var = (Var *)tle->expr;
@ -6393,8 +6416,7 @@ static bool ExecTargetList(List* targetlist, ExprContext* econtext, Datum* value
* We have some done and some undone sets. Restart the done ones
* so that we can deliver a tuple (if possible).
*/
foreach (tl, targetlist) {
GenericExprState* gstate = (GenericExprState*)lfirst(tl);
for (GenericExprState* gstate : targetArr) {
TargetEntry* tle = (TargetEntry*)gstate->xprstate.expr;
AttrNumber resind = tle->resno - 1;
@ -6420,8 +6442,7 @@ static bool ExecTargetList(List* targetlist, ExprContext* econtext, Datum* value
* XXX is that still necessary?
*/
if (*isDone == ExprEndResult) {
foreach (tl, targetlist) {
GenericExprState* gstate = (GenericExprState*)lfirst(tl);
for (GenericExprState* gstate : targetArr) {
TargetEntry* tle = (TargetEntry*)gstate->xprstate.expr;
AttrNumber resind = tle->resno - 1;
@ -6436,6 +6457,13 @@ static bool ExecTargetList(List* targetlist, ExprContext* econtext, Datum* value
}
}
if (IS_ENABLE_RIGHT_REF(econtext->rightRefState)) {
econtext->rightRefState->values = nullptr;
econtext->rightRefState->isNulls = nullptr;
econtext->rightRefState->hasExecs = nullptr;
}
/* Report success */
MemoryContextSwitchTo(oldContext);
@ -6492,7 +6520,7 @@ TupleTableSlot* ExecProject(ProjectionInfo* projInfo, ExprDoneCond* isDone)
tableam_tslot_getsomeattrs(econtext->ecxt_outertuple, projInfo->pi_lastOuterVar);
}
if (projInfo->pi_lastScanVar > 0) {
if (projInfo->pi_lastScanVar > 0 && econtext->ecxt_scantuple) {
tableam_tslot_getsomeattrs(econtext->ecxt_scantuple, projInfo->pi_lastScanVar);
}
@ -6501,7 +6529,7 @@ TupleTableSlot* ExecProject(ProjectionInfo* projInfo, ExprDoneCond* isDone)
* slots ... a mite ugly, but fast ...
*/
int numSimpleVars = projInfo->pi_numSimpleVars;
if (numSimpleVars > 0) {
if (numSimpleVars > 0 && !IS_ENABLE_RIGHT_REF(projInfo->pi_exprContext->rightRefState)) {
Datum* values = slot->tts_values;
bool* isnull = slot->tts_isnull;
int* varSlotOffsets = projInfo->pi_varSlotOffsets;
@ -6545,9 +6573,19 @@ TupleTableSlot* ExecProject(ProjectionInfo* projInfo, ExprDoneCond* isDone)
* already marked empty.
*/
if (projInfo->pi_targetlist) {
if (!ExecTargetList(
projInfo->pi_targetlist, econtext, slot->tts_values, slot->tts_isnull, projInfo->pi_itemIsDone, isDone))
if (IS_ENABLE_RIGHT_REF(econtext->rightRefState)) {
econtext->rightRefState->isUpsert = projInfo->isUpsertHasRightRef;
}
bool flag = !ExecTargetList(projInfo->pi_targetlist, econtext, slot->tts_values,
slot->tts_isnull, projInfo->pi_itemIsDone, isDone);
if (econtext->rightRefState) {
econtext->rightRefState->isUpsert = false;
}
if (flag) {
return slot; /* no more result rows, return empty slot */
}
}
/*