mirror of
https://github.com/postgres/postgres.git
synced 2025-07-03 20:02:46 +03:00
Allow internal sorts to be stored in memory rather than in files.
This commit is contained in:
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.5 1996/11/10 02:59:54 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.6 1997/08/06 03:41:29 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -374,6 +374,18 @@ ExecMergeTupleDump(ExprContext *econtext, MergeJoinState *mergestate)
|
||||
printf("******** \n");
|
||||
}
|
||||
|
||||
static void
|
||||
CleanUpSort(Plan *plan) {
|
||||
|
||||
if (plan == NULL)
|
||||
return;
|
||||
|
||||
if (plan->type == T_Sort) {
|
||||
Sort *sort = (Sort *)plan;
|
||||
psort_end(sort);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecMergeJoin
|
||||
*
|
||||
@ -676,6 +688,8 @@ ExecMergeJoin(MergeJoin *node)
|
||||
*/
|
||||
if (TupIsNull(outerTupleSlot)) {
|
||||
MJ_printf("ExecMergeJoin: **** outer tuple is nil ****\n");
|
||||
CleanUpSort(node->join.lefttree->lefttree);
|
||||
CleanUpSort(node->join.righttree->lefttree);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* nodeSort.c--
|
||||
* Routines to handle sorting of relations into temporaries.
|
||||
* Routines to handle sorting of relations.
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSort.c,v 1.4 1996/11/08 05:56:17 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSort.c,v 1.5 1997/08/06 03:41:31 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -86,10 +86,9 @@ FormSortKeys(Sort *sortnode)
|
||||
* ExecSort
|
||||
*
|
||||
* old comments
|
||||
* Retrieves tuples fron the outer subtree and insert them into a
|
||||
* temporary relation. The temporary relation is then sorted and
|
||||
* the sorted relation is stored in the relation whose ID is indicated
|
||||
* in the 'tempid' field of this node.
|
||||
* Sorts tuples from the outer subtree of the node in psort,
|
||||
* which saves the results in a temporary file or memory. After the
|
||||
* initial call, returns a tuple from the file with each call.
|
||||
* Assumes that heap access method is used.
|
||||
*
|
||||
* Conditions:
|
||||
@ -108,13 +107,8 @@ ExecSort(Sort *node)
|
||||
ScanDirection dir;
|
||||
int keycount;
|
||||
ScanKey sortkeys;
|
||||
Relation tempRelation;
|
||||
Relation currentRelation;
|
||||
HeapScanDesc currentScanDesc;
|
||||
HeapTuple heapTuple;
|
||||
TupleTableSlot *slot;
|
||||
Buffer buffer;
|
||||
int tupCount = 0;
|
||||
|
||||
/* ----------------
|
||||
* get state info from node
|
||||
@ -128,10 +122,8 @@ ExecSort(Sort *node)
|
||||
dir = estate->es_direction;
|
||||
|
||||
/* ----------------
|
||||
* the first time we call this, we retrieve all tuples
|
||||
* from the subplan into a temporary relation and then
|
||||
* we sort the relation. Subsequent calls return tuples
|
||||
* from the temporary relation.
|
||||
* the first time we call this, psort sorts this into a file.
|
||||
* Subsequent calls return tuples from psort.
|
||||
* ----------------
|
||||
*/
|
||||
|
||||
@ -144,78 +136,23 @@ ExecSort(Sort *node)
|
||||
* ----------------
|
||||
*/
|
||||
estate->es_direction = ForwardScanDirection;
|
||||
|
||||
|
||||
/* ----------------
|
||||
* if we couldn't create the temp or current relations then
|
||||
* we print a warning and return NULL.
|
||||
* ----------------
|
||||
*/
|
||||
tempRelation = sortstate->sort_TempRelation;
|
||||
if (tempRelation == NULL) {
|
||||
elog(DEBUG, "ExecSort: temp relation is NULL! aborting...");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
currentRelation = sortstate->csstate.css_currentRelation;
|
||||
if (currentRelation == NULL) {
|
||||
elog(DEBUG, "ExecSort: current relation is NULL! aborting...");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* retrieve tuples from the subplan and
|
||||
* insert them in the temporary relation
|
||||
* prepare information for psort_begin()
|
||||
* ----------------
|
||||
*/
|
||||
outerNode = outerPlan((Plan *) node);
|
||||
SO1_printf("ExecSort: %s\n",
|
||||
"inserting tuples into tempRelation");
|
||||
|
||||
for (;;) {
|
||||
slot = ExecProcNode(outerNode, (Plan*)node);
|
||||
|
||||
if (TupIsNull(slot))
|
||||
break;
|
||||
|
||||
tupCount++;
|
||||
|
||||
heapTuple = slot->val;
|
||||
|
||||
heap_insert(tempRelation, /* relation desc */
|
||||
heapTuple); /* heap tuple to insert */
|
||||
|
||||
ExecClearTuple(slot);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* now sort the tuples in our temporary relation
|
||||
* into a new sorted relation using psort()
|
||||
*
|
||||
* psort() seems to require that the relations
|
||||
* are created and opened in advance.
|
||||
* -cim 1/25/90
|
||||
* ----------------
|
||||
*/
|
||||
|
||||
keycount = node->keycount;
|
||||
sortkeys = (ScanKey)sortstate->sort_Keys;
|
||||
SO1_printf("ExecSort: %s\n",
|
||||
"calling psort");
|
||||
|
||||
/*
|
||||
* If no tuples were fetched from the proc node return NULL now
|
||||
* psort dumps it if 0 tuples are in the relation and I don't want
|
||||
* to try to debug *that* routine!!
|
||||
*/
|
||||
if (tupCount == 0)
|
||||
return NULL;
|
||||
|
||||
psort(tempRelation, /* old relation */
|
||||
currentRelation, /* new relation */
|
||||
keycount, /* number keys */
|
||||
sortkeys); /* keys */
|
||||
|
||||
if (currentRelation == NULL) {
|
||||
elog(DEBUG, "ExecSort: sorted relation is NULL! aborting...");
|
||||
"calling psort_begin");
|
||||
|
||||
if (!psort_begin(node, /* this node */
|
||||
keycount, /* number keys */
|
||||
sortkeys)) /* keys */
|
||||
{
|
||||
/* Psort says, there are no tuples to be sorted */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -225,67 +162,56 @@ ExecSort(Sort *node)
|
||||
*/
|
||||
estate->es_direction = dir;
|
||||
|
||||
/* ----------------
|
||||
* now initialize the scan descriptor to scan the
|
||||
* sorted relation and update the sortstate information
|
||||
* ----------------
|
||||
*/
|
||||
currentScanDesc = heap_beginscan(currentRelation, /* relation */
|
||||
ScanDirectionIsBackward(dir),
|
||||
/* bkwd flag */
|
||||
NowTimeQual, /* time qual */
|
||||
0, /* num scan keys */
|
||||
NULL); /* scan keys */
|
||||
|
||||
sortstate->csstate.css_currentRelation = currentRelation;
|
||||
sortstate->csstate.css_currentScanDesc = currentScanDesc;
|
||||
|
||||
/* ----------------
|
||||
* make sure the tuple descriptor is up to date
|
||||
* ----------------
|
||||
*/
|
||||
slot = sortstate->csstate.css_ScanTupleSlot;
|
||||
|
||||
slot->ttc_tupleDescriptor =
|
||||
RelationGetTupleDescriptor(currentRelation);
|
||||
|
||||
slot = (TupleTableSlot*)sortstate->csstate.cstate.cs_ResultTupleSlot;
|
||||
/* *** get_cs_ResultTupleSlot((CommonState) sortstate); */
|
||||
|
||||
slot->ttc_tupleDescriptor = ExecGetTupType(outerNode);
|
||||
#ifdef 0
|
||||
slot->ttc_execTupDescriptor = ExecGetExecTupDesc(outerNode);
|
||||
#endif
|
||||
/* ----------------
|
||||
* finally set the sorted flag to true
|
||||
* ----------------
|
||||
*/
|
||||
sortstate->sort_Flag = true;
|
||||
SO1_printf(stderr, "ExecSort: sorting done.\n");
|
||||
}
|
||||
else {
|
||||
slot = sortstate->csstate.css_ScanTupleSlot;
|
||||
slot = (TupleTableSlot*)sortstate->csstate.cstate.cs_ResultTupleSlot;
|
||||
/* *** get_cs_ResultTupleSlot((CommonState) sortstate); */
|
||||
/* slot = sortstate->csstate.css_ScanTupleSlot; orig */
|
||||
}
|
||||
|
||||
SO1_printf("ExecSort: %s\n",
|
||||
"retrieveing tuple from sorted relation");
|
||||
"retrieving tuple from sorted relation");
|
||||
|
||||
/* ----------------
|
||||
* at this point we know we have a sorted relation so
|
||||
* we preform a simple scan on it with amgetnext()..
|
||||
* at this point we grab a tuple from psort
|
||||
* ----------------
|
||||
*/
|
||||
currentScanDesc = sortstate->csstate.css_currentScanDesc;
|
||||
|
||||
heapTuple = heap_getnext(currentScanDesc, /* scan desc */
|
||||
ScanDirectionIsBackward(dir),
|
||||
/* bkwd flag */
|
||||
&buffer); /* return: buffer */
|
||||
|
||||
/* Increase the pin count on the buffer page, because the tuple stored in
|
||||
the slot also points to it (as well as the scan descriptor). If we
|
||||
don't, ExecStoreTuple will decrease the pin count on the next iteration.
|
||||
- 01/09/93 */
|
||||
|
||||
if (buffer != InvalidBuffer)
|
||||
IncrBufferRefCount(buffer);
|
||||
|
||||
return ExecStoreTuple(heapTuple, /* tuple to store */
|
||||
slot, /* slot to store in */
|
||||
buffer, /* this tuple's buffer */
|
||||
false); /* don't free stuff from amgetnext */
|
||||
heapTuple = psort_grabtuple(node);
|
||||
|
||||
if (heapTuple == NULL) {
|
||||
/* psort_end(node); */
|
||||
return (ExecClearTuple(slot));
|
||||
}
|
||||
|
||||
ExecStoreTuple(heapTuple, /* tuple to store */
|
||||
slot, /* slot to store in */
|
||||
InvalidBuffer, /* no buffer */
|
||||
true); /* free the palloc'd tuple */
|
||||
/* printf("ExecSort: (%x)",node);print_slot(slot);printf("\n");*/
|
||||
return slot;
|
||||
#if 0
|
||||
return ExecStoreTuple(heapTuple, /* tuple to store */
|
||||
slot, /* slot to store in */
|
||||
InvalidBuffer, /* no buffer */
|
||||
true); /* free the palloc'd tuple */
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
@ -302,11 +228,6 @@ ExecInitSort(Sort *node, EState *estate, Plan *parent)
|
||||
SortState *sortstate;
|
||||
Plan *outerPlan;
|
||||
ScanKey sortkeys;
|
||||
TupleDesc tupType;
|
||||
Oid tempOid;
|
||||
Oid sortOid;
|
||||
Relation tempDesc;
|
||||
Relation sortedDesc;
|
||||
|
||||
SO1_printf("ExecInitSort: %s\n",
|
||||
"initializing sort node");
|
||||
@ -324,7 +245,7 @@ ExecInitSort(Sort *node, EState *estate, Plan *parent)
|
||||
sortstate = makeNode(SortState);
|
||||
sortstate->sort_Flag = 0;
|
||||
sortstate->sort_Keys = NULL;
|
||||
sortstate->sort_TempRelation = NULL;
|
||||
node->cleaned = FALSE;
|
||||
|
||||
node->sortstate = sortstate;
|
||||
|
||||
@ -348,8 +269,8 @@ ExecInitSort(Sort *node, EState *estate, Plan *parent)
|
||||
* relation.
|
||||
* ----------------
|
||||
*/
|
||||
ExecInitScanTupleSlot(estate, &sortstate->csstate);
|
||||
ExecInitResultTupleSlot(estate, &sortstate->csstate.cstate);
|
||||
ExecInitResultTupleSlot(estate, &sortstate->csstate.cstate);
|
||||
ExecInitScanTupleSlot(estate, &sortstate->csstate);
|
||||
|
||||
/* ----------------
|
||||
* initializes child nodes
|
||||
@ -371,41 +292,10 @@ ExecInitSort(Sort *node, EState *estate, Plan *parent)
|
||||
* info because this node doesn't do projections.
|
||||
* ----------------
|
||||
*/
|
||||
ExecAssignScanTypeFromOuterPlan((Plan *) node, &sortstate->csstate);
|
||||
ExecAssignResultTypeFromOuterPlan((Plan *)node, &sortstate->csstate.cstate);
|
||||
ExecAssignScanTypeFromOuterPlan((Plan *) node, &sortstate->csstate);
|
||||
sortstate->csstate.cstate.cs_ProjInfo = NULL;
|
||||
|
||||
/* ----------------
|
||||
* get type information needed for ExecCreatR
|
||||
* ----------------
|
||||
*/
|
||||
tupType = ExecGetScanType(&sortstate->csstate);
|
||||
|
||||
/* ----------------
|
||||
* ExecCreatR wants its second argument to be an object id of
|
||||
* a relation in the range table or _TEMP_RELATION_ID_
|
||||
* indicating that the relation is not in the range table.
|
||||
*
|
||||
* In the second case ExecCreatR creates a temp relation.
|
||||
* (currently this is the only case we support -cim 10/16/89)
|
||||
* ----------------
|
||||
*/
|
||||
tempOid = node->tempid;
|
||||
sortOid = _TEMP_RELATION_ID_;
|
||||
|
||||
/* ----------------
|
||||
* create the temporary relations
|
||||
* ----------------
|
||||
*/
|
||||
/* len = ExecTargetListLength(node->plan.targetlist); */
|
||||
tempDesc = ExecCreatR(tupType, tempOid);
|
||||
sortedDesc = ExecCreatR(tupType, sortOid);
|
||||
|
||||
/* ----------------
|
||||
* save the relation descriptor in the sortstate
|
||||
* ----------------
|
||||
*/
|
||||
sortstate->sort_TempRelation = tempDesc;
|
||||
sortstate->csstate.css_currentRelation = sortedDesc;
|
||||
SO1_printf("ExecInitSort: %s\n",
|
||||
"sort node initialized");
|
||||
|
||||
@ -429,15 +319,12 @@ ExecCountSlotsSort(Sort *node)
|
||||
* ExecEndSort(node)
|
||||
*
|
||||
* old comments
|
||||
* destroys the temporary relation.
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
ExecEndSort(Sort *node)
|
||||
{
|
||||
SortState *sortstate;
|
||||
Relation tempRelation;
|
||||
Relation sortedRelation;
|
||||
Plan *outerPlan;
|
||||
|
||||
/* ----------------
|
||||
@ -448,18 +335,6 @@ ExecEndSort(Sort *node)
|
||||
"shutting down sort node");
|
||||
|
||||
sortstate = node->sortstate;
|
||||
tempRelation = sortstate->sort_TempRelation;
|
||||
sortedRelation = sortstate->csstate.css_currentRelation;
|
||||
|
||||
heap_destroyr(tempRelation);
|
||||
heap_destroyr(sortedRelation);
|
||||
|
||||
|
||||
/* ----------------
|
||||
* close the sorted relation and shut down the scan.
|
||||
* ----------------
|
||||
*/
|
||||
ExecCloseR((Plan *) node);
|
||||
|
||||
/* ----------------
|
||||
* shut down the subplan
|
||||
@ -473,6 +348,9 @@ ExecEndSort(Sort *node)
|
||||
* ----------------
|
||||
*/
|
||||
ExecClearTuple(sortstate->csstate.css_ScanTupleSlot);
|
||||
|
||||
/* Clean up after psort */
|
||||
psort_end(node);
|
||||
|
||||
SO1_printf("ExecEndSort: %s\n",
|
||||
"sort node shutdown");
|
||||
@ -480,37 +358,39 @@ ExecEndSort(Sort *node)
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecSortMarkPos
|
||||
*
|
||||
* Calls psort to save the current position in the sorted file.
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
ExecSortMarkPos(Sort *node)
|
||||
{
|
||||
SortState *sortstate;
|
||||
HeapScanDesc sdesc;
|
||||
|
||||
SortState *sortstate;
|
||||
|
||||
/* ----------------
|
||||
* if we haven't sorted yet, just return
|
||||
* if we haven't sorted yet, just return
|
||||
* ----------------
|
||||
*/
|
||||
sortstate = node->sortstate;
|
||||
if (sortstate->sort_Flag == false)
|
||||
return;
|
||||
|
||||
sdesc = sortstate->csstate.css_currentScanDesc;
|
||||
heap_markpos(sdesc);
|
||||
psort_markpos(node);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecSortRestrPos
|
||||
*
|
||||
* Calls psort to restore the last saved sort file position.
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
ExecSortRestrPos(Sort *node)
|
||||
{
|
||||
SortState *sortstate;
|
||||
HeapScanDesc sdesc;
|
||||
|
||||
SortState *sortstate;
|
||||
|
||||
/* ----------------
|
||||
* if we haven't sorted yet, just return.
|
||||
* ----------------
|
||||
@ -520,9 +400,8 @@ ExecSortRestrPos(Sort *node)
|
||||
return;
|
||||
|
||||
/* ----------------
|
||||
* restore the scan to the previously marked position
|
||||
* restore the scan to the previously marked position
|
||||
* ----------------
|
||||
*/
|
||||
sdesc = sortstate->csstate.css_currentScanDesc;
|
||||
heap_restrpos(sdesc);
|
||||
psort_restorepos(node);
|
||||
}
|
||||
|
Reference in New Issue
Block a user