Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit dad4cb6

Browse files
committed
Improve tuplestore.c to support multiple concurrent read positions.
This facility replaces the former mark/restore support but is otherwise upward-compatible with previous uses. It's expected to be needed for single evaluation of CTEs and also for window functions, so I'm committing it separately instead of waiting for either one of those patches to be finished. Per discussion with Greg Stark and Hitoshi Harada. Note: I removed nodeFunctionscan's mark/restore support, instead of bothering to update it for this change, because it was dead code anyway.
1 parent 233f135 commit dad4cb6

File tree

7 files changed

+382
-236
lines changed

7 files changed

+382
-236
lines changed

src/backend/executor/execAmi.c

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.97 2008/08/05 21:28:29 tgl Exp $
9+
* $PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.98 2008/10/01 19:51:49 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -239,10 +239,6 @@ ExecMarkPos(PlanState *node)
239239
ExecTidMarkPos((TidScanState *) node);
240240
break;
241241

242-
case T_FunctionScanState:
243-
ExecFunctionMarkPos((FunctionScanState *) node);
244-
break;
245-
246242
case T_ValuesScanState:
247243
ExecValuesMarkPos((ValuesScanState *) node);
248244
break;
@@ -296,10 +292,6 @@ ExecRestrPos(PlanState *node)
296292
ExecTidRestrPos((TidScanState *) node);
297293
break;
298294

299-
case T_FunctionScanState:
300-
ExecFunctionRestrPos((FunctionScanState *) node);
301-
break;
302-
303295
case T_ValuesScanState:
304296
ExecValuesRestrPos((ValuesScanState *) node);
305297
break;
@@ -332,7 +324,7 @@ ExecRestrPos(PlanState *node)
332324
* (However, since the only present use of mark/restore is in mergejoin,
333325
* there is no need to support mark/restore in any plan type that is not
334326
* capable of generating ordered output. So the seqscan, tidscan,
335-
* functionscan, and valuesscan support is actually useless code at present.)
327+
* and valuesscan support is actually useless code at present.)
336328
*/
337329
bool
338330
ExecSupportsMarkRestore(NodeTag plantype)
@@ -342,7 +334,6 @@ ExecSupportsMarkRestore(NodeTag plantype)
342334
case T_SeqScan:
343335
case T_IndexScan:
344336
case T_TidScan:
345-
case T_FunctionScan:
346337
case T_ValuesScan:
347338
case T_Material:
348339
case T_Sort:

src/backend/executor/nodeFunctionscan.c

Lines changed: 4 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.46 2008/02/29 02:49:39 neilc Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.47 2008/10/01 19:51:49 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -131,6 +131,9 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
131131
TypeFuncClass functypclass;
132132
TupleDesc tupdesc = NULL;
133133

134+
/* check for unsupported flags */
135+
Assert(!(eflags & EXEC_FLAG_MARK));
136+
134137
/*
135138
* FunctionScan should not have any children.
136139
*/
@@ -273,42 +276,6 @@ ExecEndFunctionScan(FunctionScanState *node)
273276
node->tuplestorestate = NULL;
274277
}
275278

276-
/* ----------------------------------------------------------------
277-
* ExecFunctionMarkPos
278-
*
279-
* Calls tuplestore to save the current position in the stored file.
280-
* ----------------------------------------------------------------
281-
*/
282-
void
283-
ExecFunctionMarkPos(FunctionScanState *node)
284-
{
285-
/*
286-
* if we haven't materialized yet, just return.
287-
*/
288-
if (!node->tuplestorestate)
289-
return;
290-
291-
tuplestore_markpos(node->tuplestorestate);
292-
}
293-
294-
/* ----------------------------------------------------------------
295-
* ExecFunctionRestrPos
296-
*
297-
* Calls tuplestore to restore the last saved file position.
298-
* ----------------------------------------------------------------
299-
*/
300-
void
301-
ExecFunctionRestrPos(FunctionScanState *node)
302-
{
303-
/*
304-
* if we haven't materialized yet, just return.
305-
*/
306-
if (!node->tuplestorestate)
307-
return;
308-
309-
tuplestore_restorepos(node->tuplestorestate);
310-
}
311-
312279
/* ----------------------------------------------------------------
313280
* ExecFunctionReScan
314281
*

src/backend/executor/nodeMaterial.c

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/nodeMaterial.c,v 1.62 2008/03/23 00:54:04 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/nodeMaterial.c,v 1.63 2008/10/01 19:51:49 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -51,7 +51,7 @@ ExecMaterial(MaterialState *node)
5151
estate = node->ss.ps.state;
5252
dir = estate->es_direction;
5353
forward = ScanDirectionIsForward(dir);
54-
tuplestorestate = (Tuplestorestate *) node->tuplestorestate;
54+
tuplestorestate = node->tuplestorestate;
5555

5656
/*
5757
* If first time through, and we need a tuplestore, initialize it.
@@ -60,7 +60,19 @@ ExecMaterial(MaterialState *node)
6060
{
6161
tuplestorestate = tuplestore_begin_heap(true, false, work_mem);
6262
tuplestore_set_eflags(tuplestorestate, node->eflags);
63-
node->tuplestorestate = (void *) tuplestorestate;
63+
if (node->eflags & EXEC_FLAG_MARK)
64+
{
65+
/*
66+
* Allocate a second read pointer to serve as the mark.
67+
* We know it must have index 1, so needn't store that.
68+
*/
69+
int ptrn;
70+
71+
ptrn = tuplestore_alloc_read_pointer(tuplestorestate,
72+
node->eflags);
73+
Assert(ptrn == 1);
74+
}
75+
node->tuplestorestate = tuplestorestate;
6476
}
6577

6678
/*
@@ -236,7 +248,7 @@ ExecEndMaterial(MaterialState *node)
236248
* Release tuplestore resources
237249
*/
238250
if (node->tuplestorestate != NULL)
239-
tuplestore_end((Tuplestorestate *) node->tuplestorestate);
251+
tuplestore_end(node->tuplestorestate);
240252
node->tuplestorestate = NULL;
241253

242254
/*
@@ -262,7 +274,10 @@ ExecMaterialMarkPos(MaterialState *node)
262274
if (!node->tuplestorestate)
263275
return;
264276

265-
tuplestore_markpos((Tuplestorestate *) node->tuplestorestate);
277+
/*
278+
* copy the active read pointer to the mark.
279+
*/
280+
tuplestore_copy_read_pointer(node->tuplestorestate, 0, 1);
266281
}
267282

268283
/* ----------------------------------------------------------------
@@ -283,9 +298,9 @@ ExecMaterialRestrPos(MaterialState *node)
283298
return;
284299

285300
/*
286-
* restore the scan to the previously marked position
301+
* copy the mark to the active read pointer.
287302
*/
288-
tuplestore_restorepos((Tuplestorestate *) node->tuplestorestate);
303+
tuplestore_copy_read_pointer(node->tuplestorestate, 1, 0);
289304
}
290305

291306
/* ----------------------------------------------------------------
@@ -322,14 +337,14 @@ ExecMaterialReScan(MaterialState *node, ExprContext *exprCtxt)
322337
if (((PlanState *) node)->lefttree->chgParam != NULL ||
323338
(node->eflags & EXEC_FLAG_REWIND) == 0)
324339
{
325-
tuplestore_end((Tuplestorestate *) node->tuplestorestate);
340+
tuplestore_end(node->tuplestorestate);
326341
node->tuplestorestate = NULL;
327342
if (((PlanState *) node)->lefttree->chgParam == NULL)
328343
ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
329344
node->eof_underlying = false;
330345
}
331346
else
332-
tuplestore_rescan((Tuplestorestate *) node->tuplestorestate);
347+
tuplestore_rescan(node->tuplestorestate);
333348
}
334349
else
335350
{

0 commit comments

Comments
 (0)