aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor')
-rw-r--r--src/backend/executor/execCurrent.c74
-rw-r--r--src/backend/executor/execQual.c27
-rw-r--r--src/backend/executor/nodeTidscan.c4
3 files changed, 83 insertions, 22 deletions
diff --git a/src/backend/executor/execCurrent.c b/src/backend/executor/execCurrent.c
index ce95d58b81b..72bccd4438e 100644
--- a/src/backend/executor/execCurrent.c
+++ b/src/backend/executor/execCurrent.c
@@ -6,26 +6,29 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/backend/executor/execCurrent.c,v 1.1 2007/06/11 01:16:22 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execCurrent.c,v 1.2 2007/06/11 22:22:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
+#include "catalog/pg_type.h"
#include "executor/executor.h"
+#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/portal.h"
+static char *fetch_param_value(ExprContext *econtext, int paramId);
static ScanState *search_plan_tree(PlanState *node, Oid table_oid);
/*
* execCurrentOf
*
- * Given the name of a cursor and the OID of a table, determine which row
- * of the table is currently being scanned by the cursor, and return its
- * TID into *current_tid.
+ * Given a CURRENT OF expression and the OID of a table, determine which row
+ * of the table is currently being scanned by the cursor named by CURRENT OF,
+ * and return the row's TID into *current_tid.
*
* Returns TRUE if a row was identified. Returns FALSE if the cursor is valid
* for the table but is not currently scanning a row of the table (this is a
@@ -33,14 +36,25 @@ static ScanState *search_plan_tree(PlanState *node, Oid table_oid);
* valid updatable scan of the specified table.
*/
bool
-execCurrentOf(char *cursor_name, Oid table_oid,
+execCurrentOf(CurrentOfExpr *cexpr,
+ ExprContext *econtext,
+ Oid table_oid,
ItemPointer current_tid)
{
+ char *cursor_name;
char *table_name;
Portal portal;
QueryDesc *queryDesc;
ScanState *scanstate;
- HeapTuple tup;
+ bool lisnull;
+ Oid tuple_tableoid;
+ ItemPointer tuple_tid;
+
+ /* Get the cursor name --- may have to look up a parameter reference */
+ if (cexpr->cursor_name)
+ cursor_name = cexpr->cursor_name;
+ else
+ cursor_name = fetch_param_value(econtext, cexpr->cursor_param);
/* Fetch table name for possible use in error messages */
table_name = get_rel_name(table_oid);
@@ -100,17 +114,55 @@ execCurrentOf(char *cursor_name, Oid table_oid,
if (TupIsNull(scanstate->ss_ScanTupleSlot))
return false;
- tup = scanstate->ss_ScanTupleSlot->tts_tuple;
- if (tup == NULL)
- elog(ERROR, "CURRENT OF applied to non-materialized tuple");
- Assert(tup->t_tableOid == table_oid);
+ /* Use slot_getattr to catch any possible mistakes */
+ tuple_tableoid = DatumGetObjectId(slot_getattr(scanstate->ss_ScanTupleSlot,
+ TableOidAttributeNumber,
+ &lisnull));
+ Assert(!lisnull);
+ tuple_tid = (ItemPointer)
+ DatumGetPointer(slot_getattr(scanstate->ss_ScanTupleSlot,
+ SelfItemPointerAttributeNumber,
+ &lisnull));
+ Assert(!lisnull);
+
+ Assert(tuple_tableoid == table_oid);
- *current_tid = tup->t_self;
+ *current_tid = *tuple_tid;
return true;
}
/*
+ * fetch_param_value
+ *
+ * Fetch the string value of a param, verifying it is of type REFCURSOR.
+ */
+static char *
+fetch_param_value(ExprContext *econtext, int paramId)
+{
+ ParamListInfo paramInfo = econtext->ecxt_param_list_info;
+
+ if (paramInfo &&
+ paramId > 0 && paramId <= paramInfo->numParams)
+ {
+ ParamExternData *prm = &paramInfo->params[paramId - 1];
+
+ if (OidIsValid(prm->ptype) && !prm->isnull)
+ {
+ Assert(prm->ptype == REFCURSOROID);
+ /* We know that refcursor uses text's I/O routines */
+ return DatumGetCString(DirectFunctionCall1(textout,
+ prm->value));
+ }
+ }
+
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("no value found for parameter %d", paramId)));
+ return NULL;
+}
+
+/*
* search_plan_tree
*
* Search through a PlanState tree for a scan node on the specified table.
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index 5549142e703..69d28e78a4b 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.219 2007/06/11 01:16:22 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.220 2007/06/11 22:22:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -3632,8 +3632,10 @@ ExecEvalCurrentOfExpr(ExprState *exprstate, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone)
{
CurrentOfExpr *cexpr = (CurrentOfExpr *) exprstate->expr;
- bool result;
- HeapTuple tup;
+ bool result;
+ bool lisnull;
+ Oid tableoid;
+ ItemPointer tuple_tid;
ItemPointerData cursor_tid;
if (isDone)
@@ -3643,12 +3645,19 @@ ExecEvalCurrentOfExpr(ExprState *exprstate, ExprContext *econtext,
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));
+ /* 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;
diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c
index 986ff1f3f19..31a9828b6a1 100644
--- a/src/backend/executor/nodeTidscan.c
+++ b/src/backend/executor/nodeTidscan.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeTidscan.c,v 1.54 2007/06/11 01:16:22 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeTidscan.c,v 1.55 2007/06/11 22:22:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -153,7 +153,7 @@ TidListCreate(TidScanState *tidstate)
CurrentOfExpr *cexpr = (CurrentOfExpr *) expr;
ItemPointerData cursor_tid;
- if (execCurrentOf(cexpr->cursor_name,
+ if (execCurrentOf(cexpr, econtext,
RelationGetRelid(tidstate->ss.ss_currentRelation),
&cursor_tid))
{