diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2007-10-24 18:37:09 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2007-10-24 18:37:09 +0000 |
commit | c29a9c37bf6bdaaaa65ccbcd4c69c596691134e1 (patch) | |
tree | c7df7fd2c22d5007ff6901800714d93bc4ce8a4c /src/backend/executor/execQual.c | |
parent | 9226ba817b19999d51d39a0a2bde810160d0cf24 (diff) | |
download | postgresql-c29a9c37bf6bdaaaa65ccbcd4c69c596691134e1.tar.gz postgresql-c29a9c37bf6bdaaaa65ccbcd4c69c596691134e1.zip |
Fix UPDATE/DELETE WHERE CURRENT OF to support repeated update and update-
then-delete on the current cursor row. The basic fix is that nodeTidscan.c
has to apply heap_get_latest_tid() to the current-scan-TID obtained from the
cursor query; this ensures we get the latest row version to work with.
However, since that only works if the query plan is a TID scan, we also have
to hack the planner to make sure only that type of plan will be selected.
(Formerly, the planner might decide to apply a seqscan if the table is very
small. This change is probably a Good Thing anyway, since it's hard to see
how a seqscan could really win.) That means the execQual.c code to support
CurrentOfExpr as a regular expression type is dead code, so replace it with
just an elog(). Also, add regression tests covering these cases. Note
that the added tests expose the fact that re-fetching an updated row
misbehaves if the cursor used FOR UPDATE. That's an independent bug that
should be fixed later. Per report from Dharmendra Goyal.
Diffstat (limited to 'src/backend/executor/execQual.c')
-rw-r--r-- | src/backend/executor/execQual.c | 40 |
1 files changed, 6 insertions, 34 deletions
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index cc165006f5c..53ddc658197 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.222 2007/09/06 17:31:58 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.223 2007/10/24 18:37:08 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -3694,45 +3694,17 @@ ExecEvalArrayCoerceExpr(ArrayCoerceExprState *astate, /* ---------------------------------------------------------------- * ExecEvalCurrentOfExpr * - * Normally, the planner will convert CURRENT OF into a TidScan qualification, - * but we have plain execQual support in case it doesn't. + * The planner must convert CURRENT OF into a TidScan qualification. + * So, we have to be able to do ExecInitExpr on a CurrentOfExpr, + * but we shouldn't ever actually execute it. * ---------------------------------------------------------------- */ static Datum ExecEvalCurrentOfExpr(ExprState *exprstate, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone) { - CurrentOfExpr *cexpr = (CurrentOfExpr *) exprstate->expr; - bool result; - bool lisnull; - Oid tableoid; - ItemPointer tuple_tid; - ItemPointerData cursor_tid; - - if (isDone) - *isDone = ExprSingleResult; - *isNull = false; - - Assert(cexpr->cvarno != INNER); - Assert(cexpr->cvarno != OUTER); - Assert(!TupIsNull(econtext->ecxt_scantuple)); - /* Use slot_getattr to catch any possible mistakes */ - tableoid = DatumGetObjectId(slot_getattr(econtext->ecxt_scantuple, - TableOidAttributeNumber, - &lisnull)); - Assert(!lisnull); - tuple_tid = (ItemPointer) - DatumGetPointer(slot_getattr(econtext->ecxt_scantuple, - SelfItemPointerAttributeNumber, - &lisnull)); - Assert(!lisnull); - - if (execCurrentOf(cexpr, econtext, tableoid, &cursor_tid)) - result = ItemPointerEquals(&cursor_tid, tuple_tid); - else - result = false; - - return BoolGetDatum(result); + elog(ERROR, "CURRENT OF cannot be executed"); + return 0; /* keep compiler quiet */ } |