From 6799a6ca21e509f3fd16a057e30970f500273d1a Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Mon, 11 Feb 2002 20:10:50 +0000
Subject: [PATCH] Repair problems with EvalPlanQual where target table is
 scanned as inner indexscan (ie, one with runtime keys).  ExecIndexReScan must
 compute or recompute runtime keys even if we are rescanning in the EPQ case. 
 TidScan seems to have comparable problems.  Per bug noted by Barry Lind
 11-Feb-02.

---
 src/backend/executor/nodeIndexscan.c | 86 +++++++++++++++-------------
 src/backend/executor/nodeTidscan.c   | 25 +++++---
 2 files changed, 64 insertions(+), 47 deletions(-)

diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index 5afee29f527..bde5bce334d 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.65 2001/11/12 17:18:06 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.66 2002/02/11 20:10:48 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -301,24 +301,13 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
 	IndexScanState *indexstate;
 	ExprContext *econtext;
 	ScanDirection direction;
+	int			numIndices;
 	IndexScanDescPtr scanDescs;
 	ScanKey    *scanKeys;
-	IndexScanDesc scan;
-	ScanKey		skey;
-	int			numIndices;
-	int			i;
 	int		  **runtimeKeyInfo;
 	int		   *numScanKeys;
-	List	   *indxqual;
-	List	   *qual;
-	int			n_keys;
-	ScanKey		scan_keys;
-	int		   *run_keys;
+	int			i;
 	int			j;
-	Expr	   *clause;
-	Node	   *scanexpr;
-	Datum		scanvalue;
-	bool		isNull;
 
 	estate = node->scan.plan.state;
 	indexstate = node->indxstate;
@@ -330,10 +319,6 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
 	scanKeys = indexstate->iss_ScanKeys;
 	runtimeKeyInfo = indexstate->iss_RuntimeKeyInfo;
 	numScanKeys = indexstate->iss_NumScanKeys;
-	if (ScanDirectionIsBackward(node->indxorderdir))
-		indexstate->iss_IndexPtr = numIndices;
-	else
-		indexstate->iss_IndexPtr = -1;
 
 	if (econtext)
 	{
@@ -359,28 +344,27 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
 		ResetExprContext(econtext);
 	}
 
-	/* If this is re-scanning of PlanQual ... */
-	if (estate->es_evTuple != NULL &&
-		estate->es_evTuple[node->scan.scanrelid - 1] != NULL)
-	{
-		estate->es_evTupleNull[node->scan.scanrelid - 1] = false;
-		return;
-	}
-
 	/*
-	 * get the index qualifications and recalculate the appropriate values
+	 * If we are doing runtime key calculations (ie, the index keys depend
+	 * on data from an outer scan), compute the new key values
 	 */
-	indxqual = node->indxqual;
-	for (i = 0; i < numIndices; i++)
+	if (runtimeKeyInfo)
 	{
-		qual = lfirst(indxqual);
-		indxqual = lnext(indxqual);
-		n_keys = numScanKeys[i];
-		scan_keys = (ScanKey) scanKeys[i];
+		List	   *indxqual;
 
-		if (runtimeKeyInfo)
+		indxqual = node->indxqual;
+		for (i = 0; i < numIndices; i++)
 		{
+			List	   *qual = lfirst(indxqual);
+			int			n_keys;
+			ScanKey		scan_keys;
+			int		   *run_keys;
+
+			indxqual = lnext(indxqual);
+			n_keys = numScanKeys[i];
+			scan_keys = scanKeys[i];
 			run_keys = runtimeKeyInfo[i];
+
 			for (j = 0; j < n_keys; j++)
 			{
 				/*
@@ -398,7 +382,11 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
 				 */
 				if (run_keys[j] != NO_OP)
 				{
-					clause = nth(j, qual);
+					Expr	   *clause = nth(j, qual);
+					Node	   *scanexpr;
+					Datum		scanvalue;
+					bool		isNull;
+
 					scanexpr = (run_keys[j] == RIGHT_OP) ?
 						(Node *) get_rightop(clause) :
 						(Node *) get_leftop(clause);
@@ -415,13 +403,31 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
 				}
 			}
 		}
-		scan = scanDescs[i];
-		skey = scanKeys[i];
-		index_rescan(scan, direction, skey);
-	}
 
-	if (runtimeKeyInfo)
 		indexstate->iss_RuntimeKeysReady = true;
+	}
+
+	/* If this is re-scanning of PlanQual ... */
+	if (estate->es_evTuple != NULL &&
+		estate->es_evTuple[node->scan.scanrelid - 1] != NULL)
+	{
+		estate->es_evTupleNull[node->scan.scanrelid - 1] = false;
+		return;
+	}
+
+	/* reset index scans */
+	if (ScanDirectionIsBackward(node->indxorderdir))
+		indexstate->iss_IndexPtr = numIndices;
+	else
+		indexstate->iss_IndexPtr = -1;
+
+	for (i = 0; i < numIndices; i++)
+	{
+		IndexScanDesc scan = scanDescs[i];
+		ScanKey		skey = scanKeys[i];
+
+		index_rescan(scan, direction, skey);
+	}
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c
index fb2e3d53d37..08685571cab 100644
--- a/src/backend/executor/nodeTidscan.c
+++ b/src/backend/executor/nodeTidscan.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.21 2001/10/28 06:25:43 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.22 2002/02/11 20:10:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -108,6 +108,11 @@ TidNext(TidScan *node)
 		if (estate->es_evTupleNull[node->scan.scanrelid - 1])
 			return slot;		/* return empty slot */
 
+		/*
+		 * XXX shouldn't we check here to make sure tuple matches TID list?
+		 * In runtime-key case this is not certain, is it?
+		 */
+
 		ExecStoreTuple(estate->es_evTuple[node->scan.scanrelid - 1],
 					   slot, InvalidBuffer, false);
 
@@ -250,9 +255,8 @@ ExecTidReScan(TidScan *node, ExprContext *exprCtxt, Plan *parent)
 	TidScanState *tidstate;
 	ItemPointerData *tidList;
 
-	tidstate = node->tidstate;
 	estate = node->scan.plan.state;
-	tidstate->tss_TidPtr = -1;
+	tidstate = node->tidstate;
 	tidList = tidstate->tss_TidList;
 
 	/* If we are being passed an outer tuple, save it for runtime key calc */
@@ -260,6 +264,13 @@ ExecTidReScan(TidScan *node, ExprContext *exprCtxt, Plan *parent)
 		node->scan.scanstate->cstate.cs_ExprContext->ecxt_outertuple =
 			exprCtxt->ecxt_outertuple;
 
+	/* do runtime calc of target TIDs, if needed */
+	if (node->needRescan)
+		tidstate->tss_NumTids =
+			TidListCreate(node->tideval,
+						  node->scan.scanstate->cstate.cs_ExprContext,
+						  tidList);
+
 	/* If this is re-scanning of PlanQual ... */
 	if (estate->es_evTuple != NULL &&
 		estate->es_evTuple[node->scan.scanrelid - 1] != NULL)
@@ -268,9 +279,7 @@ ExecTidReScan(TidScan *node, ExprContext *exprCtxt, Plan *parent)
 		return;
 	}
 
-	tidstate->tss_NumTids = TidListCreate(node->tideval,
-							 node->scan.scanstate->cstate.cs_ExprContext,
-										  tidList);
+	tidstate->tss_TidPtr = -1;
 
 	/*
 	 * perhaps return something meaningful
@@ -432,7 +441,9 @@ ExecInitTidScan(TidScan *node, EState *estate, Plan *parent)
 	tidList = (ItemPointerData *) palloc(length(node->tideval) * sizeof(ItemPointerData));
 	numTids = 0;
 	if (!node->needRescan)
-		numTids = TidListCreate(node->tideval, scanstate->cstate.cs_ExprContext, tidList);
+		numTids = TidListCreate(node->tideval,
+								scanstate->cstate.cs_ExprContext,
+								tidList);
 	tidPtr = -1;
 
 	CXT1_printf("ExecInitTidScan: context is %d\n", CurrentMemoryContext);
-- 
GitLab