diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2007-06-11 01:16:30 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2007-06-11 01:16:30 +0000 |
commit | 6808f1b1de0ebcd4af558ba84c3226b2027f55ea (patch) | |
tree | ebd12580d3aaca6ec79b5d99563a1eff02451e88 /src/backend/executor/execQual.c | |
parent | 85d72f05167b87bc44464b2eabea8538f1fd1e45 (diff) |
Support UPDATE/DELETE WHERE CURRENT OF cursor_name, per SQL standard.
Along the way, allow FOR UPDATE in non-WITH-HOLD cursors; there may once
have been a reason to disallow that, but it seems to work now, and it's
really rather necessary if you want to select a row via a cursor and then
update it in a concurrent-safe fashion.
Original patch by Arul Shaji, rather heavily editorialized by Tom Lane.
Diffstat (limited to 'src/backend/executor/execQual.c')
-rw-r--r-- | src/backend/executor/execQual.c | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index fd54b89f0a5..5549142e703 100644 --- a/src/backend/executor/execQual.c +++ b/src/backend/executor/execQual.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.218 2007/06/05 21:31:04 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.219 2007/06/11 01:16:22 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -151,6 +151,8 @@ static Datum ExecEvalCoerceViaIO(CoerceViaIOState *iostate, static Datum ExecEvalArrayCoerceExpr(ArrayCoerceExprState *astate, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone); +static Datum ExecEvalCurrentOfExpr(ExprState *exprstate, ExprContext *econtext, + bool *isNull, ExprDoneCond *isDone); /* ---------------------------------------------------------------- @@ -3618,6 +3620,41 @@ ExecEvalArrayCoerceExpr(ArrayCoerceExprState *astate, astate->amstate); } +/* ---------------------------------------------------------------- + * ExecEvalCurrentOfExpr + * + * Normally, the planner will convert CURRENT OF into a TidScan qualification, + * but we have plain execQual support in case it doesn't. + * ---------------------------------------------------------------- + */ +static Datum +ExecEvalCurrentOfExpr(ExprState *exprstate, ExprContext *econtext, + bool *isNull, ExprDoneCond *isDone) +{ + CurrentOfExpr *cexpr = (CurrentOfExpr *) exprstate->expr; + bool result; + HeapTuple tup; + ItemPointerData cursor_tid; + + if (isDone) + *isDone = ExprSingleResult; + *isNull = false; + + Assert(cexpr->cvarno != INNER); + Assert(cexpr->cvarno != OUTER); + Assert(!TupIsNull(econtext->ecxt_scantuple)); + tup = econtext->ecxt_scantuple->tts_tuple; + if (tup == NULL) + elog(ERROR, "CURRENT OF applied to non-materialized tuple"); + + if (execCurrentOf(cexpr->cursor_name, tup->t_tableOid, &cursor_tid)) + result = ItemPointerEquals(&cursor_tid, &(tup->t_self)); + else + result = false; + + return BoolGetDatum(result); +} + /* * ExecEvalExprSwitchContext @@ -4266,6 +4303,10 @@ ExecInitExpr(Expr *node, PlanState *parent) state = (ExprState *) cstate; } break; + case T_CurrentOfExpr: + state = (ExprState *) makeNode(ExprState); + state->evalfunc = ExecEvalCurrentOfExpr; + break; case T_TargetEntry: { TargetEntry *tle = (TargetEntry *) node; |