Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
f5f366e1
Commit
f5f366e1
authored
Aug 06, 1997
by
Bruce Momjian
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Allow internal sorts to be stored in memory rather than in files.
parent
3bea7b13
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
630 additions
and
513 deletions
+630
-513
src/backend/executor/nodeMergejoin.c
src/backend/executor/nodeMergejoin.c
+15
-1
src/backend/executor/nodeSort.c
src/backend/executor/nodeSort.c
+70
-191
src/backend/tcop/postgres.c
src/backend/tcop/postgres.c
+15
-3
src/backend/utils/sort/lselect.c
src/backend/utils/sort/lselect.c
+46
-89
src/backend/utils/sort/psort.c
src/backend/utils/sort/psort.c
+398
-183
src/include/nodes/execnodes.h
src/include/nodes/execnodes.h
+2
-2
src/include/nodes/plannodes.h
src/include/nodes/plannodes.h
+3
-1
src/include/utils/lselect.h
src/include/utils/lselect.h
+20
-11
src/include/utils/psort.h
src/include/utils/psort.h
+49
-16
src/man/postgres.1
src/man/postgres.1
+10
-14
src/man/postmaster.1
src/man/postmaster.1
+2
-2
No files found.
src/backend/executor/nodeMergejoin.c
View file @
f5f366e1
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
*
*
*
*
* IDENTIFICATION
* 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)
...
@@ -374,6 +374,18 @@ ExecMergeTupleDump(ExprContext *econtext, MergeJoinState *mergestate)
printf
(
"********
\n
"
);
printf
(
"********
\n
"
);
}
}
static
void
CleanUpSort
(
Plan
*
plan
)
{
if
(
plan
==
NULL
)
return
;
if
(
plan
->
type
==
T_Sort
)
{
Sort
*
sort
=
(
Sort
*
)
plan
;
psort_end
(
sort
);
}
}
/* ----------------------------------------------------------------
/* ----------------------------------------------------------------
* ExecMergeJoin
* ExecMergeJoin
*
*
...
@@ -676,6 +688,8 @@ ExecMergeJoin(MergeJoin *node)
...
@@ -676,6 +688,8 @@ ExecMergeJoin(MergeJoin *node)
*/
*/
if
(
TupIsNull
(
outerTupleSlot
))
{
if
(
TupIsNull
(
outerTupleSlot
))
{
MJ_printf
(
"ExecMergeJoin: **** outer tuple is nil ****
\n
"
);
MJ_printf
(
"ExecMergeJoin: **** outer tuple is nil ****
\n
"
);
CleanUpSort
(
node
->
join
.
lefttree
->
lefttree
);
CleanUpSort
(
node
->
join
.
righttree
->
lefttree
);
return
NULL
;
return
NULL
;
}
}
...
...
src/backend/executor/nodeSort.c
View file @
f5f366e1
/*-------------------------------------------------------------------------
/*-------------------------------------------------------------------------
*
*
* nodeSort.c--
* 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
* Copyright (c) 1994, Regents of the University of California
*
*
*
*
* IDENTIFICATION
* 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)
...
@@ -86,10 +86,9 @@ FormSortKeys(Sort *sortnode)
* ExecSort
* ExecSort
*
*
* old comments
* old comments
* Retrieves tuples fron the outer subtree and insert them into a
* Sorts tuples from the outer subtree of the node in psort,
* temporary relation. The temporary relation is then sorted and
* which saves the results in a temporary file or memory. After the
* the sorted relation is stored in the relation whose ID is indicated
* initial call, returns a tuple from the file with each call.
* in the 'tempid' field of this node.
* Assumes that heap access method is used.
* Assumes that heap access method is used.
*
*
* Conditions:
* Conditions:
...
@@ -108,13 +107,8 @@ ExecSort(Sort *node)
...
@@ -108,13 +107,8 @@ ExecSort(Sort *node)
ScanDirection
dir
;
ScanDirection
dir
;
int
keycount
;
int
keycount
;
ScanKey
sortkeys
;
ScanKey
sortkeys
;
Relation
tempRelation
;
Relation
currentRelation
;
HeapScanDesc
currentScanDesc
;
HeapTuple
heapTuple
;
HeapTuple
heapTuple
;
TupleTableSlot
*
slot
;
TupleTableSlot
*
slot
;
Buffer
buffer
;
int
tupCount
=
0
;
/* ----------------
/* ----------------
* get state info from node
* get state info from node
...
@@ -128,10 +122,8 @@ ExecSort(Sort *node)
...
@@ -128,10 +122,8 @@ ExecSort(Sort *node)
dir
=
estate
->
es_direction
;
dir
=
estate
->
es_direction
;
/* ----------------
/* ----------------
* the first time we call this, we retrieve all tuples
* the first time we call this, psort sorts this into a file.
* from the subplan into a temporary relation and then
* Subsequent calls return tuples from psort.
* we sort the relation. Subsequent calls return tuples
* from the temporary relation.
* ----------------
* ----------------
*/
*/
...
@@ -146,76 +138,21 @@ ExecSort(Sort *node)
...
@@ -146,76 +138,21 @@ ExecSort(Sort *node)
estate
->
es_direction
=
ForwardScanDirection
;
estate
->
es_direction
=
ForwardScanDirection
;
/* ----------------
/* ----------------
* if we couldn't create the temp or current relations then
* prepare information for psort_begin()
* 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
* ----------------
* ----------------
*/
*/
outerNode
=
outerPlan
((
Plan
*
)
node
);
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
;
keycount
=
node
->
keycount
;
sortkeys
=
(
ScanKey
)
sortstate
->
sort_Keys
;
sortkeys
=
(
ScanKey
)
sortstate
->
sort_Keys
;
SO1_printf
(
"ExecSort: %s
\n
"
,
SO1_printf
(
"ExecSort: %s
\n
"
,
"calling psort"
);
"calling psort_begin"
);
/*
* 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 */
if
(
!
psort_begin
(
node
,
/* this node */
currentRelation
,
/* new relation */
keycount
,
/* number keys */
keycount
,
/* number keys */
sortkeys
);
/* keys */
sortkeys
))
/* keys */
{
if
(
currentRelation
==
NULL
)
{
/* Psort says, there are no tuples to be sorted */
elog
(
DEBUG
,
"ExecSort: sorted relation is NULL! aborting..."
);
return
NULL
;
return
NULL
;
}
}
...
@@ -225,67 +162,56 @@ ExecSort(Sort *node)
...
@@ -225,67 +162,56 @@ ExecSort(Sort *node)
*/
*/
estate
->
es_direction
=
dir
;
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
* make sure the tuple descriptor is up to date
* ----------------
* ----------------
*/
*/
slot
=
sortstate
->
csstate
.
css_ScanTupleSlot
;
slot
=
(
TupleTableSlot
*
)
sortstate
->
csstate
.
cstate
.
cs_ResultTupleSlot
;
/* *** get_cs_ResultTupleSlot((CommonState) sortstate); */
slot
->
ttc_tupleDescriptor
=
RelationGetTupleDescriptor
(
currentRelation
);
slot
->
ttc_tupleDescriptor
=
ExecGetTupType
(
outerNode
);
#ifdef 0
slot
->
ttc_execTupDescriptor
=
ExecGetExecTupDesc
(
outerNode
);
#endif
/* ----------------
/* ----------------
* finally set the sorted flag to true
* finally set the sorted flag to true
* ----------------
* ----------------
*/
*/
sortstate
->
sort_Flag
=
true
;
sortstate
->
sort_Flag
=
true
;
SO1_printf
(
stderr
,
"ExecSort: sorting done.
\n
"
);
}
}
else
{
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
"
,
SO1_printf
(
"ExecSort: %s
\n
"
,
"retriev
e
ing tuple from sorted relation"
);
"retrieving tuple from sorted relation"
);
/* ----------------
/* ----------------
* at this point we know we have a sorted relation so
* at this point we grab a tuple from psort
* we preform a simple scan on it with amgetnext()..
* ----------------
* ----------------
*/
*/
currentScanDesc
=
sortstate
->
csstate
.
css_currentScanDesc
;
heapTuple
=
psort_grabtuple
(
node
);
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
if
(
heapTuple
==
NULL
)
{
the slot also points to it (as well as the scan descriptor). If we
/* psort_end(node); */
don't, ExecStoreTuple will decrease the pin count on the next iteration.
return
(
ExecClearTuple
(
slot
));
- 01/09/93 */
}
if
(
buffer
!=
InvalidBuffer
)
IncrBufferRefCount
(
buffer
);
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 */
return ExecStoreTuple(heapTuple, /* tuple to store */
slot, /* slot to store in */
slot, /* slot to store in */
buffer
,
/* this tuple's buffer */
InvalidBuffer, /* no buffer */
false
);
/* don't free stuff from amgetnext */
true); /* free the palloc'd tuple */
#endif
}
}
/* ----------------------------------------------------------------
/* ----------------------------------------------------------------
...
@@ -302,11 +228,6 @@ ExecInitSort(Sort *node, EState *estate, Plan *parent)
...
@@ -302,11 +228,6 @@ ExecInitSort(Sort *node, EState *estate, Plan *parent)
SortState
*
sortstate
;
SortState
*
sortstate
;
Plan
*
outerPlan
;
Plan
*
outerPlan
;
ScanKey
sortkeys
;
ScanKey
sortkeys
;
TupleDesc
tupType
;
Oid
tempOid
;
Oid
sortOid
;
Relation
tempDesc
;
Relation
sortedDesc
;
SO1_printf
(
"ExecInitSort: %s
\n
"
,
SO1_printf
(
"ExecInitSort: %s
\n
"
,
"initializing sort node"
);
"initializing sort node"
);
...
@@ -324,7 +245,7 @@ ExecInitSort(Sort *node, EState *estate, Plan *parent)
...
@@ -324,7 +245,7 @@ ExecInitSort(Sort *node, EState *estate, Plan *parent)
sortstate
=
makeNode
(
SortState
);
sortstate
=
makeNode
(
SortState
);
sortstate
->
sort_Flag
=
0
;
sortstate
->
sort_Flag
=
0
;
sortstate
->
sort_Keys
=
NULL
;
sortstate
->
sort_Keys
=
NULL
;
sortstate
->
sort_TempRelation
=
NULL
;
node
->
cleaned
=
FALSE
;
node
->
sortstate
=
sortstate
;
node
->
sortstate
=
sortstate
;
...
@@ -348,8 +269,8 @@ ExecInitSort(Sort *node, EState *estate, Plan *parent)
...
@@ -348,8 +269,8 @@ ExecInitSort(Sort *node, EState *estate, Plan *parent)
* relation.
* relation.
* ----------------
* ----------------
*/
*/
ExecInitScanTupleSlot
(
estate
,
&
sortstate
->
csstate
);
ExecInitResultTupleSlot
(
estate
,
&
sortstate
->
csstate
.
cstate
);
ExecInitResultTupleSlot
(
estate
,
&
sortstate
->
csstate
.
cstate
);
ExecInitScanTupleSlot
(
estate
,
&
sortstate
->
csstate
);
/* ----------------
/* ----------------
* initializes child nodes
* initializes child nodes
...
@@ -371,41 +292,10 @@ ExecInitSort(Sort *node, EState *estate, Plan *parent)
...
@@ -371,41 +292,10 @@ ExecInitSort(Sort *node, EState *estate, Plan *parent)
* info because this node doesn't do projections.
* info because this node doesn't do projections.
* ----------------
* ----------------
*/
*/
ExecAssignResultTypeFromOuterPlan
((
Plan
*
)
node
,
&
sortstate
->
csstate
.
cstate
);
ExecAssignScanTypeFromOuterPlan
((
Plan
*
)
node
,
&
sortstate
->
csstate
);
ExecAssignScanTypeFromOuterPlan
((
Plan
*
)
node
,
&
sortstate
->
csstate
);
sortstate
->
csstate
.
cstate
.
cs_ProjInfo
=
NULL
;
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
"
,
SO1_printf
(
"ExecInitSort: %s
\n
"
,
"sort node initialized"
);
"sort node initialized"
);
...
@@ -429,15 +319,12 @@ ExecCountSlotsSort(Sort *node)
...
@@ -429,15 +319,12 @@ ExecCountSlotsSort(Sort *node)
* ExecEndSort(node)
* ExecEndSort(node)
*
*
* old comments
* old comments
* destroys the temporary relation.
* ----------------------------------------------------------------
* ----------------------------------------------------------------
*/
*/
void
void
ExecEndSort
(
Sort
*
node
)
ExecEndSort
(
Sort
*
node
)
{
{
SortState
*
sortstate
;
SortState
*
sortstate
;
Relation
tempRelation
;
Relation
sortedRelation
;
Plan
*
outerPlan
;
Plan
*
outerPlan
;
/* ----------------
/* ----------------
...
@@ -448,18 +335,6 @@ ExecEndSort(Sort *node)
...
@@ -448,18 +335,6 @@ ExecEndSort(Sort *node)
"shutting down sort node"
);
"shutting down sort node"
);
sortstate
=
node
->
sortstate
;
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
* shut down the subplan
...
@@ -474,19 +349,23 @@ ExecEndSort(Sort *node)
...
@@ -474,19 +349,23 @@ ExecEndSort(Sort *node)
*/
*/
ExecClearTuple
(
sortstate
->
csstate
.
css_ScanTupleSlot
);
ExecClearTuple
(
sortstate
->
csstate
.
css_ScanTupleSlot
);
/* Clean up after psort */
psort_end
(
node
);
SO1_printf
(
"ExecEndSort: %s
\n
"
,
SO1_printf
(
"ExecEndSort: %s
\n
"
,
"sort node shutdown"
);
"sort node shutdown"
);
}
}
/* ----------------------------------------------------------------
/* ----------------------------------------------------------------
* ExecSortMarkPos
* ExecSortMarkPos
*
* Calls psort to save the current position in the sorted file.
* ----------------------------------------------------------------
* ----------------------------------------------------------------
*/
*/
void
void
ExecSortMarkPos
(
Sort
*
node
)
ExecSortMarkPos
(
Sort
*
node
)
{
{
SortState
*
sortstate
;
SortState
*
sortstate
;
HeapScanDesc
sdesc
;
/* ----------------
/* ----------------
* if we haven't sorted yet, just return
* if we haven't sorted yet, just return
...
@@ -496,20 +375,21 @@ ExecSortMarkPos(Sort *node)
...
@@ -496,20 +375,21 @@ ExecSortMarkPos(Sort *node)
if
(
sortstate
->
sort_Flag
==
false
)
if
(
sortstate
->
sort_Flag
==
false
)
return
;
return
;
sdesc
=
sortstate
->
csstate
.
css_currentScanDesc
;
psort_markpos
(
node
)
;
heap_markpos
(
sdesc
);
return
;
return
;
}
}
/* ----------------------------------------------------------------
/* ----------------------------------------------------------------
* ExecSortRestrPos
* ExecSortRestrPos
*
* Calls psort to restore the last saved sort file position.
* ----------------------------------------------------------------
* ----------------------------------------------------------------
*/
*/
void
void
ExecSortRestrPos
(
Sort
*
node
)
ExecSortRestrPos
(
Sort
*
node
)
{
{
SortState
*
sortstate
;
SortState
*
sortstate
;
HeapScanDesc
sdesc
;
/* ----------------
/* ----------------
* if we haven't sorted yet, just return.
* if we haven't sorted yet, just return.
...
@@ -523,6 +403,5 @@ ExecSortRestrPos(Sort *node)
...
@@ -523,6 +403,5 @@ ExecSortRestrPos(Sort *node)
* restore the scan to the previously marked position
* restore the scan to the previously marked position
* ----------------
* ----------------
*/
*/
sdesc
=
sortstate
->
csstate
.
css_currentScanDesc
;
psort_restorepos
(
node
);
heap_restrpos
(
sdesc
);
}
}
src/backend/tcop/postgres.c
View file @
f5f366e1
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.3
6 1997/07/29 16:14:40 thomas
Exp $
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.3
7 1997/08/06 03:41:41 momjian
Exp $
*
*
* NOTES
* NOTES
* this is the "main" module of the postgres backend and
* this is the "main" module of the postgres backend and
...
@@ -108,6 +108,7 @@ extern int lockingOff;
...
@@ -108,6 +108,7 @@ extern int lockingOff;
extern
int
NBuffers
;
extern
int
NBuffers
;
int
fsyncOff
=
0
;
int
fsyncOff
=
0
;
int
SortMem
=
512
;
int
dontExecute
=
0
;
int
dontExecute
=
0
;
static
int
ShowStats
;
static
int
ShowStats
;
...
@@ -1039,6 +1040,15 @@ PostgresMain(int argc, char *argv[])
...
@@ -1039,6 +1040,15 @@ PostgresMain(int argc, char *argv[])
flagQ
=
1
;
flagQ
=
1
;
break
;
break
;
case
'S'
:
/* ----------------
* S - amount of sort memory to use in 1k bytes
* ----------------
*/
SortMem
=
atoi
(
optarg
);
break
;
#ifdef NOT_USED
case
'S'
:
case
'S'
:
/* ----------------
/* ----------------
* S - assume stable main memory
* S - assume stable main memory
...
@@ -1048,6 +1058,7 @@ PostgresMain(int argc, char *argv[])
...
@@ -1048,6 +1058,7 @@ PostgresMain(int argc, char *argv[])
flagS
=
1
;
flagS
=
1
;
SetTransactionFlushEnabled
(
false
);
SetTransactionFlushEnabled
(
false
);
break
;
break
;
#endif
case
's'
:
case
's'
:
/* ----------------
/* ----------------
...
@@ -1173,6 +1184,7 @@ PostgresMain(int argc, char *argv[])
...
@@ -1173,6 +1184,7 @@ PostgresMain(int argc, char *argv[])
printf
(
"
\t
timings = %c
\n
"
,
ShowStats
?
't'
:
'f'
);
printf
(
"
\t
timings = %c
\n
"
,
ShowStats
?
't'
:
'f'
);
printf
(
"
\t
dates = %s
\n
"
,
EuroDates
?
"European"
:
"Normal"
);
printf
(
"
\t
dates = %s
\n
"
,
EuroDates
?
"European"
:
"Normal"
);
printf
(
"
\t
bufsize = %d
\n
"
,
NBuffers
);
printf
(
"
\t
bufsize = %d
\n
"
,
NBuffers
);
printf
(
"
\t
sortmem = %d
\n
"
,
SortMem
);
printf
(
"
\t
query echo = %c
\n
"
,
EchoQuery
?
't'
:
'f'
);
printf
(
"
\t
query echo = %c
\n
"
,
EchoQuery
?
't'
:
'f'
);
printf
(
"
\t
multiplexed backend? = %c
\n
"
,
multiplexedBackend
?
't'
:
'f'
);
printf
(
"
\t
multiplexed backend? = %c
\n
"
,
multiplexedBackend
?
't'
:
'f'
);
...
@@ -1280,7 +1292,7 @@ PostgresMain(int argc, char *argv[])
...
@@ -1280,7 +1292,7 @@ PostgresMain(int argc, char *argv[])
*/
*/
if
(
IsUnderPostmaster
==
false
)
{
if
(
IsUnderPostmaster
==
false
)
{
puts
(
"
\n
POSTGRES backend interactive interface"
);
puts
(
"
\n
POSTGRES backend interactive interface"
);
puts
(
"$Revision: 1.3
6 $ $Date: 1997/07/29 16:14:40
$"
);
puts
(
"$Revision: 1.3
7 $ $Date: 1997/08/06 03:41:41
$"
);
}
}
/* ----------------
/* ----------------
...
...
src/backend/utils/sort/lselect.c
View file @
f5f366e1
...
@@ -8,7 +8,7 @@
...
@@ -8,7 +8,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/sort/Attic/lselect.c,v 1.
3 1997/05/20 11:35:48 vadim
Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/sort/Attic/lselect.c,v 1.
4 1997/08/06 03:41:47 momjian
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -26,37 +26,14 @@
...
@@ -26,37 +26,14 @@
#include "utils/psort.h"
#include "utils/psort.h"
#include "utils/lselect.h"
#include "utils/lselect.h"
extern
Relation
SortRdesc
;
/* later static */
/*
* PUTTUP - writes the next tuple
* ENDRUN - mark end of run
* GETLEN - reads the length of the next tuple
* ALLOCTUP - returns space for the new tuple
* SETTUPLEN - stores the length into the tuple
* GETTUP - reads the tuple
*
* Note:
* LEN field must be a short; FP is a stream
*/
#define PUTTUP(TUP, FP) fwrite((char *)TUP, (TUP)->t_len, 1, FP)
#define PUTTUP(TUP, FP) fwrite((char *)TUP, (TUP)->t_len, 1, FP)
#define ENDRUN(FP) fwrite((char *)&shortzero, sizeof (shortzero), 1, FP)
#define GETLEN(LEN, FP) fread(&(LEN), sizeof (shortzero), 1, FP)
#define ALLOCTUP(LEN) ((HeapTuple)palloc((unsigned)LEN))
#define GETTUP(TUP, LEN, FP)\
fread((char *)(TUP) + sizeof (shortzero), 1, (LEN) - sizeof (shortzero), FP)
#define SETTUPLEN(TUP, LEN) (TUP)->t_len = LEN
/*
/*
* USEMEM - record use of memory
* USEMEM - record use of memory
* FREEMEM - record freeing of memory
* FREEMEM - record freeing of memory
* FULLMEM - 1 iff a tuple will fit
*/
*/
#define USEMEM(context,AMT) context->sortMem -= (AMT)
#define USEMEM(AMT) SortMemory -= (AMT)
#define FREEMEM(context,AMT) context->sortMem += (AMT)
#define FREEMEM(AMT) SortMemory += (AMT)
#define LACKMEM() (SortMemory <= BLCKSZ)
/* not accurate */
/*
/*
* lmerge - merges two leftist trees into one
* lmerge - merges two leftist trees into one
...
@@ -67,12 +44,12 @@ extern Relation SortRdesc; /* later static */
...
@@ -67,12 +44,12 @@ extern Relation SortRdesc; /* later static */
* speed up code significantly.
* speed up code significantly.
*/
*/
struct
leftist
*
struct
leftist
*
lmerge
(
struct
leftist
*
pt
,
struct
leftist
*
qt
)
lmerge
(
struct
leftist
*
pt
,
struct
leftist
*
qt
,
LeftistContext
context
)
{
{
register
struct
leftist
*
root
,
*
majorLeftist
,
*
minorLeftist
;
register
struct
leftist
*
root
,
*
majorLeftist
,
*
minorLeftist
;
int
dist
;
int
dist
;
if
(
tuplecmp
(
pt
->
lt_tuple
,
qt
->
lt_tuple
))
{
if
(
tuplecmp
(
pt
->
lt_tuple
,
qt
->
lt_tuple
,
context
))
{
root
=
pt
;
root
=
pt
;
majorLeftist
=
qt
;
majorLeftist
=
qt
;
}
else
{
}
else
{
...
@@ -83,7 +60,7 @@ lmerge(struct leftist *pt, struct leftist *qt)
...
@@ -83,7 +60,7 @@ lmerge(struct leftist *pt, struct leftist *qt)
root
->
lt_left
=
majorLeftist
;
root
->
lt_left
=
majorLeftist
;
else
{
else
{
if
((
minorLeftist
=
root
->
lt_right
)
!=
NULL
)
if
((
minorLeftist
=
root
->
lt_right
)
!=
NULL
)
majorLeftist
=
lmerge
(
majorLeftist
,
minorLeftist
);
majorLeftist
=
lmerge
(
majorLeftist
,
minorLeftist
,
context
);
if
((
dist
=
root
->
lt_left
->
lt_dist
)
<
majorLeftist
->
lt_dist
)
{
if
((
dist
=
root
->
lt_left
->
lt_dist
)
<
majorLeftist
->
lt_dist
)
{
root
->
lt_dist
=
1
+
dist
;
root
->
lt_dist
=
1
+
dist
;
root
->
lt_right
=
root
->
lt_left
;
root
->
lt_right
=
root
->
lt_left
;
...
@@ -97,11 +74,11 @@ lmerge(struct leftist *pt, struct leftist *qt)
...
@@ -97,11 +74,11 @@ lmerge(struct leftist *pt, struct leftist *qt)
}
}
static
struct
leftist
*
static
struct
leftist
*
linsert
(
struct
leftist
*
root
,
struct
leftist
*
new1
)
linsert
(
struct
leftist
*
root
,
struct
leftist
*
new1
,
LeftistContext
context
)
{
{
register
struct
leftist
*
left
,
*
right
;
register
struct
leftist
*
left
,
*
right
;
if
(
!
tuplecmp
(
root
->
lt_tuple
,
new1
->
lt_tuple
))
{
if
(
!
tuplecmp
(
root
->
lt_tuple
,
new1
->
lt_tuple
,
context
))
{
new1
->
lt_left
=
root
;
new1
->
lt_left
=
root
;
return
(
new1
);
return
(
new1
);
}
}
...
@@ -116,7 +93,7 @@ linsert(struct leftist *root, struct leftist *new1)
...
@@ -116,7 +93,7 @@ linsert(struct leftist *root, struct leftist *new1)
}
}
return
(
root
);
return
(
root
);
}
}
right
=
linsert
(
right
,
new1
);
right
=
linsert
(
right
,
new1
,
context
);
if
(
right
->
lt_dist
<
left
->
lt_dist
)
{
if
(
right
->
lt_dist
<
left
->
lt_dist
)
{
root
->
lt_dist
=
1
+
left
->
lt_dist
;
root
->
lt_dist
=
1
+
left
->
lt_dist
;
root
->
lt_left
=
right
;
root
->
lt_left
=
right
;
...
@@ -142,7 +119,8 @@ linsert(struct leftist *root, struct leftist *new1)
...
@@ -142,7 +119,8 @@ linsert(struct leftist *root, struct leftist *new1)
*/
*/
HeapTuple
HeapTuple
gettuple
(
struct
leftist
**
treep
,
gettuple
(
struct
leftist
**
treep
,
short
*
devnum
)
/* device from which tuple came */
short
*
devnum
,
/* device from which tuple came */
LeftistContext
context
)
{
{
register
struct
leftist
*
tp
;
register
struct
leftist
*
tp
;
HeapTuple
tup
;
HeapTuple
tup
;
...
@@ -153,9 +131,9 @@ gettuple(struct leftist **treep,
...
@@ -153,9 +131,9 @@ gettuple(struct leftist **treep,
if
(
tp
->
lt_dist
==
1
)
/* lt_left == NULL */
if
(
tp
->
lt_dist
==
1
)
/* lt_left == NULL */
*
treep
=
tp
->
lt_left
;
*
treep
=
tp
->
lt_left
;
else
else
*
treep
=
lmerge
(
tp
->
lt_left
,
tp
->
lt_right
);
*
treep
=
lmerge
(
tp
->
lt_left
,
tp
->
lt_right
,
context
);
FREEMEM
(
sizeof
(
struct
leftist
));
FREEMEM
(
context
,
sizeof
(
struct
leftist
));
FREE
(
tp
);
FREE
(
tp
);
return
(
tup
);
return
(
tup
);
}
}
...
@@ -169,14 +147,17 @@ gettuple(struct leftist **treep,
...
@@ -169,14 +147,17 @@ gettuple(struct leftist **treep,
* Note:
* Note:
* Currently never returns NULL BUG
* Currently never returns NULL BUG
*/
*/
int
void
puttuple
(
struct
leftist
**
treep
,
HeapTuple
newtuple
,
int
devnum
)
puttuple
(
struct
leftist
**
treep
,
HeapTuple
newtuple
,
short
devnum
,
LeftistContext
context
)
{
{
register
struct
leftist
*
new1
;
register
struct
leftist
*
new1
;
register
struct
leftist
*
tp
;
register
struct
leftist
*
tp
;
new1
=
(
struct
leftist
*
)
palloc
((
unsigned
)
sizeof
(
struct
leftist
));
new1
=
(
struct
leftist
*
)
palloc
((
unsigned
)
sizeof
(
struct
leftist
));
USEMEM
(
sizeof
(
struct
leftist
));
USEMEM
(
context
,
sizeof
(
struct
leftist
));
new1
->
lt_dist
=
1
;
new1
->
lt_dist
=
1
;
new1
->
lt_devnum
=
devnum
;
new1
->
lt_devnum
=
devnum
;
new1
->
lt_tuple
=
newtuple
;
new1
->
lt_tuple
=
newtuple
;
...
@@ -185,38 +166,11 @@ puttuple(struct leftist **treep, HeapTuple newtuple, int devnum)
...
@@ -185,38 +166,11 @@ puttuple(struct leftist **treep, HeapTuple newtuple, int devnum)
if
((
tp
=
*
treep
)
==
NULL
)
if
((
tp
=
*
treep
)
==
NULL
)
*
treep
=
new1
;
*
treep
=
new1
;
else
else
*
treep
=
linsert
(
tp
,
new1
);
*
treep
=
linsert
(
tp
,
new1
,
context
);
return
(
1
)
;
return
;
}
}
/*
* dumptuples - stores all the tuples in tree into file
*/
void
dumptuples
(
FILE
*
file
)
{
register
struct
leftist
*
tp
;
register
struct
leftist
*
newp
;
HeapTuple
tup
;
tp
=
Tuples
;
while
(
tp
!=
NULL
)
{
tup
=
tp
->
lt_tuple
;
if
(
tp
->
lt_dist
==
1
)
/* lt_right == NULL */
newp
=
tp
->
lt_left
;
else
newp
=
lmerge
(
tp
->
lt_left
,
tp
->
lt_right
);
FREEMEM
(
sizeof
(
struct
leftist
));
FREE
(
tp
);
PUTTUP
(
tup
,
file
);
FREEMEM
(
tup
->
t_len
);
FREE
(
tup
);
tp
=
newp
;
}
Tuples
=
NULL
;
}
/*
/*
* tuplecmp - Compares two tuples with respect CmpList
* tuplecmp - Compares two tuples with respect CmpList
*
*
...
@@ -225,7 +179,7 @@ dumptuples(FILE *file)
...
@@ -225,7 +179,7 @@ dumptuples(FILE *file)
* Assumtions:
* Assumtions:
*/
*/
int
int
tuplecmp
(
HeapTuple
ltup
,
HeapTuple
rtup
)
tuplecmp
(
HeapTuple
ltup
,
HeapTuple
rtup
,
LeftistContext
context
)
{
{
register
char
*
lattr
,
*
rattr
;
register
char
*
lattr
,
*
rattr
;
int
nkey
=
0
;
int
nkey
=
0
;
...
@@ -238,24 +192,27 @@ tuplecmp(HeapTuple ltup, HeapTuple rtup)
...
@@ -238,24 +192,27 @@ tuplecmp(HeapTuple ltup, HeapTuple rtup)
return
(
0
);
return
(
0
);
if
(
rtup
==
(
HeapTuple
)
NULL
)
if
(
rtup
==
(
HeapTuple
)
NULL
)
return
(
1
);
return
(
1
);
while
(
nkey
<
Nk
eys
&&
!
result
)
{
while
(
nkey
<
context
->
nK
eys
&&
!
result
)
{
lattr
=
heap_getattr
(
ltup
,
InvalidBuffer
,
lattr
=
heap_getattr
(
ltup
,
InvalidBuffer
,
Key
[
nkey
].
sk_attno
,
context
->
scanKeys
[
nkey
].
sk_attno
,
RelationGetTupleDescriptor
(
SortRdesc
),
context
->
tupDesc
,
&
isnull
);
&
isnull
);
if
(
isnull
)
if
(
isnull
)
return
(
0
);
return
(
0
);
rattr
=
heap_getattr
(
rtup
,
InvalidBuffer
,
rattr
=
heap_getattr
(
rtup
,
InvalidBuffer
,
Key
[
nkey
].
sk_attno
,
context
->
scanKeys
[
nkey
].
sk_attno
,
RelationGetTupleDescriptor
(
SortRdesc
)
,
context
->
tupDesc
,
&
isnull
);
&
isnull
);
if
(
isnull
)
if
(
isnull
)
return
(
1
);
return
(
1
);
if
(
Key
[
nkey
].
sk_flags
&
SK_COMMUTE
)
{
if
(
context
->
scanKeys
[
nkey
].
sk_flags
&
SK_COMMUTE
)
{
if
(
!
(
result
=
(
long
)
(
*
Key
[
nkey
].
sk_func
)
(
rattr
,
lattr
)))
if
(
!
(
result
=
result
=
-
(
long
)
(
*
Key
[
nkey
].
sk_func
)
(
lattr
,
rattr
);
(
long
)
(
*
context
->
scanKeys
[
nkey
].
sk_func
)
(
rattr
,
lattr
)))
}
else
if
(
!
(
result
=
(
long
)
(
*
Key
[
nkey
].
sk_func
)
(
lattr
,
rattr
)))
result
=
result
=
-
(
long
)
(
*
Key
[
nkey
].
sk_func
)
(
rattr
,
lattr
);
-
(
long
)
(
*
context
->
scanKeys
[
nkey
].
sk_func
)
(
lattr
,
rattr
);
}
else
if
(
!
(
result
=
(
long
)
(
*
context
->
scanKeys
[
nkey
].
sk_func
)
(
lattr
,
rattr
)))
result
=
-
(
long
)
(
*
context
->
scanKeys
[
nkey
].
sk_func
)
(
rattr
,
lattr
);
nkey
++
;
nkey
++
;
}
}
return
(
result
==
1
);
return
(
result
==
1
);
...
@@ -263,7 +220,7 @@ tuplecmp(HeapTuple ltup, HeapTuple rtup)
...
@@ -263,7 +220,7 @@ tuplecmp(HeapTuple ltup, HeapTuple rtup)
#ifdef EBUG
#ifdef EBUG
void
void
checktree
(
struct
leftist
*
tree
)
checktree
(
struct
leftist
*
tree
,
LeftistContext
context
)
{
{
int
lnodes
;
int
lnodes
;
int
rnodes
;
int
rnodes
;
...
@@ -272,8 +229,8 @@ checktree(struct leftist *tree)
...
@@ -272,8 +229,8 @@ checktree(struct leftist *tree)
puts
(
"Null tree."
);
puts
(
"Null tree."
);
return
;
return
;
}
}
lnodes
=
checktreer
(
tree
->
lt_left
,
1
);
lnodes
=
checktreer
(
tree
->
lt_left
,
1
,
context
);
rnodes
=
checktreer
(
tree
->
lt_right
,
1
);
rnodes
=
checktreer
(
tree
->
lt_right
,
1
,
context
);
if
(
lnodes
<
0
)
{
if
(
lnodes
<
0
)
{
lnodes
=
-
lnodes
;
lnodes
=
-
lnodes
;
puts
(
"0:
\t
Bad left side."
);
puts
(
"0:
\t
Bad left side."
);
...
@@ -297,24 +254,24 @@ checktree(struct leftist *tree)
...
@@ -297,24 +254,24 @@ checktree(struct leftist *tree)
}
else
if
(
tree
->
lt_dist
!=
1
+
tree
->
lt_right
->
lt_dist
)
}
else
if
(
tree
->
lt_dist
!=
1
+
tree
->
lt_right
->
lt_dist
)
puts
(
"0:
\t
Distance incorrect."
);
puts
(
"0:
\t
Distance incorrect."
);
if
(
lnodes
>
0
)
if
(
lnodes
>
0
)
if
(
tuplecmp
(
tree
->
lt_left
->
lt_tuple
,
tree
->
lt_tuple
))
if
(
tuplecmp
(
tree
->
lt_left
->
lt_tuple
,
tree
->
lt_tuple
,
context
))
printf
(
"%d:
\t
Left child < parent.
\n
"
);
printf
(
"%d:
\t
Left child < parent.
\n
"
);
if
(
rnodes
>
0
)
if
(
rnodes
>
0
)
if
(
tuplecmp
(
tree
->
lt_right
->
lt_tuple
,
tree
->
lt_tuple
))
if
(
tuplecmp
(
tree
->
lt_right
->
lt_tuple
,
tree
->
lt_tuple
,
context
))
printf
(
"%d:
\t
Right child < parent.
\n
"
);
printf
(
"%d:
\t
Right child < parent.
\n
"
);
printf
(
"Tree has %d nodes
\n
"
,
1
+
lnodes
+
rnodes
);
printf
(
"Tree has %d nodes
\n
"
,
1
+
lnodes
+
rnodes
);
}
}
int
int
checktreer
(
struct
leftist
*
tree
,
int
level
)
checktreer
(
struct
leftist
*
tree
,
int
level
,
LeftistContext
context
)
{
{
int
lnodes
,
rnodes
;
int
lnodes
,
rnodes
;
int
error
=
0
;
int
error
=
0
;
if
(
tree
==
NULL
)
if
(
tree
==
NULL
)
return
(
0
);
return
(
0
);
lnodes
=
checktreer
(
tree
->
lt_left
,
level
+
1
);
lnodes
=
checktreer
(
tree
->
lt_left
,
level
+
1
,
context
);
rnodes
=
checktreer
(
tree
->
lt_right
,
level
+
1
);
rnodes
=
checktreer
(
tree
->
lt_right
,
level
+
1
,
context
);
if
(
lnodes
<
0
)
{
if
(
lnodes
<
0
)
{
error
=
1
;
error
=
1
;
lnodes
=
-
lnodes
;
lnodes
=
-
lnodes
;
...
@@ -349,12 +306,12 @@ checktreer(struct leftist *tree, int level)
...
@@ -349,12 +306,12 @@ checktreer(struct leftist *tree, int level)
printf
(
"%d:
\t
Distance incorrect.
\n
"
,
level
);
printf
(
"%d:
\t
Distance incorrect.
\n
"
,
level
);
}
}
if
(
lnodes
>
0
)
if
(
lnodes
>
0
)
if
(
tuplecmp
(
tree
->
lt_left
->
lt_tuple
,
tree
->
lt_tuple
))
{
if
(
tuplecmp
(
tree
->
lt_left
->
lt_tuple
,
tree
->
lt_tuple
,
context
))
{
error
=
1
;
error
=
1
;
printf
(
"%d:
\t
Left child < parent.
\n
"
);
printf
(
"%d:
\t
Left child < parent.
\n
"
);
}
}
if
(
rnodes
>
0
)
if
(
rnodes
>
0
)
if
(
tuplecmp
(
tree
->
lt_right
->
lt_tuple
,
tree
->
lt_tuple
))
{
if
(
tuplecmp
(
tree
->
lt_right
->
lt_tuple
,
tree
->
lt_tuple
,
context
))
{
error
=
1
;
error
=
1
;
printf
(
"%d:
\t
Right child < parent.
\n
"
);
printf
(
"%d:
\t
Right child < parent.
\n
"
);
}
}
...
...
src/backend/utils/sort/psort.c
View file @
f5f366e1
...
@@ -7,11 +7,25 @@
...
@@ -7,11 +7,25 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/sort/Attic/psort.c,v 1.
5 1997/07/24 20:18:07
momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/sort/Attic/psort.c,v 1.
6 1997/08/06 03:41:55
momjian Exp $
*
*
* NOTES
* NOTES
* Sorts the first relation into the second relation. The sort may
* Sorts the first relation into the second relation.
* not be called twice simultaneously.
*
* The old psort.c's routines formed a temporary relation from the merged
* sort files. This version keeps the files around instead of generating the
* relation from them, and provides interface functions to the file so that
* you can grab tuples, mark a position in the file, restore a position in the
* file. You must now explicitly call an interface function to end the sort,
* psort_end, when you are done.
* Now most of the global variables are stuck in the Sort nodes, and
* accessed from there (they are passed to all the psort routines) so that
* each sort running has its own separate state. This is facilitated by having
* the Sort nodes passed in to all the interface functions.
* The one global variable that all the sorts still share is SortMemory.
* You should now be allowed to run two or more psorts concurrently,
* so long as the memory they eat up is not greater than SORTMEM, the initial
* value of SortMemory. -Rex 2.15.1995
*
*
* Use the tape-splitting method (Knuth, Vol. III, pp281-86) in the future.
* Use the tape-splitting method (Knuth, Vol. III, pp281-86) in the future.
*
*
...
@@ -21,7 +35,6 @@
...
@@ -21,7 +35,6 @@
*/
*/
#include <stdio.h>
#include <stdio.h>
#include <math.h>
#include <math.h>
#include <unistd.h>
#include "postgres.h"
#include "postgres.h"
...
@@ -35,120 +48,150 @@
...
@@ -35,120 +48,150 @@
#include "storage/buf.h"
#include "storage/buf.h"
#include "storage/bufmgr.h"
/* for BLCKSZ */
#include "storage/bufmgr.h"
/* for BLCKSZ */
#include "utils/portal.h"
/* for {Start,End}PortalAllocMode */
#include "utils/portal.h"
/* for {Start,End}PortalAllocMode */
#include "utils/elog.h"
#include "utils/rel.h"
#include "utils/rel.h"
#include "utils/psort.h"
#include "nodes/execnodes.h"
#include "nodes/plannodes.h"
#include "executor/executor.h"
#include "utils/lselect.h"
#include "utils/lselect.h"
#include "utils/psort.h"
#include "storage/fd.h"
#include "storage/fd.h"
#ifndef HAVE_MEMMOVE
# include <regex/utils.h>
#else
# include <string.h>
#endif
#define TEMPDIR "./"
#define TEMPDIR "./"
int
Nkeys
;
extern
int
SortMem
;
/* defined as postgres option */
ScanKey
Key
;
int
SortMemory
;
static
int
TapeRange
;
/* number of tapes - 1 (T) */
static
int
Level
;
/* (l) */
static
int
TotalDummy
;
/* summation of tp_dummy */
static
struct
tape
Tape
[
MAXTAPES
];
static
long
shortzero
=
0
;
/* used to delimit runs */
static
long
shortzero
=
0
;
/* used to delimit runs */
static
struct
tuple
*
LastTuple
=
NULL
;
/* last output */
static
int
BytesRead
;
/* to keep track of # of IO */
/*
static
int
BytesWritten
;
* old psort global variables
*
* (These are the global variables from the old psort. They are still used,
* but are now accessed from Sort nodes using the PS macro. Note that while
* these variables will be accessed by PS(node)->whatever, they will still
* be called by their original names within the comments! -Rex 2.10.1995)
*
* LeftistContextData treeContext;
*
* static int TapeRange; // number of tapes - 1 (T) //
* static int Level; // (l) //
* static int TotalDummy; // summation of tp_dummy //
* static struct tape *Tape;
*
* static int BytesRead; // to keep track of # of IO //
* static int BytesWritten;
*
* struct leftist *Tuples; // current tuples in memory //
*
* FILE *psort_grab_file; // this holds tuples grabbed
* from merged sort runs //
* long psort_current; // current file position //
* long psort_saved; // file position saved for
* mark and restore //
*/
Relation
SortRdesc
;
/* current tuples in memory */
/*
struct
leftist
*
Tuples
;
/* current tuples in memory */
* PS - Macro to access and cast psortstate from a Sort node
*/
#define PS(N) ((Psortstate *)N->psortstate)
/*
/*
* psort - polyphase merge sort entry point
* psort_begin - polyphase merge sort entry point. Sorts the subplan
* into a temporary file psort_grab_file. After
* this is called, calling the interface function
* psort_grabtuple iteratively will get you the sorted
* tuples. psort_end then finishes the sort off, after
* all the tuples have been grabbed.
*
* Allocates and initializes sort node's psort state.
*/
*/
void
bool
psort
(
Relation
oldrel
,
Relation
newrel
,
int
nkeys
,
ScanKey
key
)
psort
_begin
(
Sort
*
node
,
int
nkeys
,
ScanKey
key
)
{
{
bool
empty
;
/* to answer: is child node empty? */
node
->
psortstate
=
(
struct
Psortstate
*
)
palloc
(
sizeof
(
struct
Psortstate
));
if
(
node
->
psortstate
==
NULL
)
return
false
;
AssertArg
(
nkeys
>=
1
);
AssertArg
(
nkeys
>=
1
);
AssertArg
(
key
[
0
].
sk_attno
!=
0
);
AssertArg
(
key
[
0
].
sk_attno
!=
0
);
AssertArg
(
key
[
0
].
sk_procedure
!=
0
);
AssertArg
(
key
[
0
].
sk_procedure
!=
0
);
Nkeys
=
nkeys
;
PS
(
node
)
->
BytesRead
=
0
;
Key
=
key
;
PS
(
node
)
->
BytesWritten
=
0
;
SortMemory
=
0
;
PS
(
node
)
->
treeContext
.
tupDesc
=
SortRdesc
=
oldrel
;
ExecGetTupType
(
outerPlan
((
Plan
*
)
node
));
BytesRead
=
0
;
PS
(
node
)
->
treeContext
.
nKeys
=
nkeys
;
BytesWritten
=
0
;
PS
(
node
)
->
treeContext
.
scanKeys
=
key
;
/*
PS
(
node
)
->
treeContext
.
sortMem
=
SortMem
;
* may not be the best place.
*
* Pass 0 for the "limit" as the argument is currently ignored.
* Previously, only one arg was passed. -mer 12 Nov. 1991
*/
StartPortalAllocMode
(
StaticAllocMode
,
(
Size
)
0
);
initpsort
();
initialrun
(
oldrel
);
/* call finalrun(newrel, mergerun()) instead */
endpsort
(
newrel
,
mergeruns
());
EndPortalAllocMode
();
NDirectFileRead
+=
(
int
)
ceil
((
double
)
BytesRead
/
BLCKSZ
);
NDirectFileWrite
+=
(
int
)
ceil
((
double
)
BytesWritten
/
BLCKSZ
);
}
/*
PS
(
node
)
->
Tuples
=
NULL
;
* TAPENO - number of tape in Tape
PS
(
node
)
->
tupcount
=
0
;
*/
PS
(
node
)
->
using_tape_files
=
false
;
PS
(
node
)
->
memtuples
=
NULL
;
initialrun
(
node
,
&
empty
);
if
(
empty
)
return
false
;
#define TAPENO(NODE) (NODE - Tape)
if
(
PS
(
node
)
->
using_tape_files
)
#define TUPLENO(TUP) ((TUP == NULL) ? -1 : (int) TUP->t_iid)
PS
(
node
)
->
psort_grab_file
=
mergeruns
(
node
);
PS
(
node
)
->
psort_current
=
0
;
PS
(
node
)
->
psort_saved
=
0
;
return
true
;
}
/*
/*
* init
psort
- initializes the tapes
* init
tapes
- initializes the tapes
* - (polyphase merge Alg.D(D1)--Knuth, Vol.3, p.270)
* - (polyphase merge Alg.D(D1)--Knuth, Vol.3, p.270)
* Returns:
* Returns:
* number of allocated tapes
* number of allocated tapes
*/
*/
void
void
init
psort
(
)
init
tapes
(
Sort
*
node
)
{
{
register
int
i
;
register
int
i
;
register
struct
tape
*
tp
;
register
struct
tape
*
tp
;
Assert
(
node
!=
(
Sort
*
)
NULL
);
Assert
(
PS
(
node
)
!=
(
Psortstate
*
)
NULL
);
/*
/*
ASSERT(ntapes >= 3 && ntapes <= MAXTAPES,
ASSERT(ntapes >= 3 && ntapes <= MAXTAPES,
"init
psort
: Invalid number of tapes to initialize.\n");
"init
tapes
: Invalid number of tapes to initialize.\n");
*/
*/
tp
=
Tape
;
tp
=
PS
(
node
)
->
Tape
;
for
(
i
=
0
;
i
<
MAXTAPES
&&
(
tp
->
tp_file
=
gettape
())
!=
NULL
;
i
++
)
{
for
(
i
=
0
;
i
<
MAXTAPES
&&
(
tp
->
tp_file
=
gettape
())
!=
NULL
;
i
++
)
{
tp
->
tp_dummy
=
1
;
tp
->
tp_dummy
=
1
;
tp
->
tp_fib
=
1
;
tp
->
tp_fib
=
1
;
tp
->
tp_prev
=
tp
-
1
;
tp
->
tp_prev
=
tp
-
1
;
tp
++
;
tp
++
;
}
}
TapeRange
=
--
tp
-
Tape
;
PS
(
node
)
->
TapeRange
=
--
tp
-
PS
(
node
)
->
Tape
;
tp
->
tp_dummy
=
0
;
tp
->
tp_dummy
=
0
;
tp
->
tp_fib
=
0
;
tp
->
tp_fib
=
0
;
Tape
[
0
].
tp_prev
=
tp
;
PS
(
node
)
->
Tape
[
0
].
tp_prev
=
tp
;
if
(
TapeRange
<=
1
)
if
(
PS
(
node
)
->
TapeRange
<=
1
)
elog
(
WARN
,
"init
psort
: Could only allocate %d < 3 tapes
\n
"
,
elog
(
WARN
,
"init
tapes
: Could only allocate %d < 3 tapes
\n
"
,
TapeRange
+
1
);
PS
(
node
)
->
TapeRange
+
1
);
Level
=
1
;
PS
(
node
)
->
Level
=
1
;
TotalDummy
=
TapeRange
;
PS
(
node
)
->
TotalDummy
=
PS
(
node
)
->
TapeRange
;
SortMemory
=
SORTMEM
;
PS
(
node
)
->
using_tape_files
=
true
;
LastTuple
=
NULL
;
Tuples
=
NULL
;
}
}
/*
/*
* resetpsort - resets (
frees) m
alloc'd memory for an aborted Xaction
* resetpsort - resets (
pfrees) p
alloc'd memory for an aborted Xaction
*
*
* Not implemented yet.
* Not implemented yet.
*/
*/
...
@@ -170,16 +213,18 @@ resetpsort()
...
@@ -170,16 +213,18 @@ resetpsort()
* LEN field must be a short; FP is a stream
* LEN field must be a short; FP is a stream
*/
*/
#define PUTTUP(TUP, FP)\
BytesWritten += (TUP)->t_len; \
#define PUTTUP(NODE, TUP, FP) if (1) {\
fwrite((char *)TUP, (TUP)->t_len, 1, FP)
((Psortstate *)NODE->psortstate)->BytesWritten += (TUP)->t_len; \
fwrite((char *)TUP, (TUP)->t_len, 1, FP);} else
#define ENDRUN(FP) fwrite((char *)&shortzero, sizeof (shortzero), 1, FP)
#define ENDRUN(FP) fwrite((char *)&shortzero, sizeof (shortzero), 1, FP)
#define GETLEN(LEN, FP) fread((char *)&(LEN), sizeof (shortzero), 1, FP)
#define GETLEN(LEN, FP) fread((char *)&(LEN), sizeof (shortzero), 1, FP)
#define ALLOCTUP(LEN) ((HeapTuple)palloc((unsigned)LEN))
#define ALLOCTUP(LEN) ((HeapTuple)palloc((unsigned)LEN))
#define GETTUP(
TUP, LEN, FP)
\
#define GETTUP(
NODE, TUP, LEN, FP) if (1) {
\
IncrProcessed(); \
IncrProcessed(); \
BytesRead += (LEN) - sizeof (shortzero); \
((Psortstate *)NODE->psortstate)->BytesRead += (LEN) - sizeof (shortzero); \
fread((char *)(TUP) + sizeof (shortzero), (LEN) - sizeof (shortzero), 1, FP)
fread((char *)(TUP) + sizeof (shortzero), (LEN) - sizeof (shortzero), 1, FP);} \
else
#define SETTUPLEN(TUP, LEN) (TUP)->t_len = LEN
#define SETTUPLEN(TUP, LEN) (TUP)->t_len = LEN
/*
/*
...
@@ -188,9 +233,9 @@ resetpsort()
...
@@ -188,9 +233,9 @@ resetpsort()
* FULLMEM - 1 iff a tuple will fit
* FULLMEM - 1 iff a tuple will fit
*/
*/
#define USEMEM(
AMT) SortMemory
-= (AMT)
#define USEMEM(
NODE,AMT) PS(node)->treeContext.sortMem
-= (AMT)
#define FREEMEM(
AMT) SortMemory
+= (AMT)
#define FREEMEM(
NODE,AMT) PS(node)->treeContext.sortMem
+= (AMT)
#define LACKMEM(
) (SortMemory <= BLCKSZ)
/* not accurate */
#define LACKMEM(
NODE) (PS(node)->treeContext.sortMem <= MAXBLCKSZ)
/* not accurate */
#define TRACEMEM(FUNC)
#define TRACEMEM(FUNC)
#define TRACEOUT(FUNC, TUP)
#define TRACEOUT(FUNC, TUP)
...
@@ -219,61 +264,66 @@ resetpsort()
...
@@ -219,61 +264,66 @@ resetpsort()
* Also, perhaps allocate tapes when needed. Split into 2 funcs.
* Also, perhaps allocate tapes when needed. Split into 2 funcs.
*/
*/
void
void
initialrun
(
Relation
rdesc
)
initialrun
(
Sort
*
node
,
bool
*
empty
)
{
{
/* register struct tuple *tup; */
/* register struct tuple *tup; */
register
struct
tape
*
tp
;
register
struct
tape
*
tp
;
HeapScanDesc
sdesc
;
int
baseruns
;
/* D:(a) */
int
baseruns
;
/* D:(a) */
int
more
passes
;
/* EOF */
int
extra
passes
;
/* EOF */
sdesc
=
heap_beginscan
(
rdesc
,
0
,
NowTimeQual
,
0
,
Assert
(
node
!=
(
Sort
*
)
NULL
);
(
ScanKey
)
NULL
);
Assert
(
PS
(
node
)
!=
(
Psortstate
*
)
NULL
);
tp
=
Tape
;
if
((
bool
)
createrun
(
sdesc
,
tp
->
tp_file
)
!=
false
)
tp
=
PS
(
node
)
->
Tape
;
morepasses
=
0
;
if
((
bool
)
createrun
(
node
,
tp
->
tp_file
,
empty
)
!=
false
)
{
if
(
!
PS
(
node
)
->
using_tape_files
)
inittapes
(
node
);
extrapasses
=
0
;
}
else
else
morepasses
=
1
+
(
Tuples
!=
NULL
);
/* (T != N) ? 2 : 1
*/
return
;
/* if rows fit in memory, we never access tape stuff
*/
for
(
;
;
)
{
for
(
;
;
)
{
tp
->
tp_dummy
--
;
tp
->
tp_dummy
--
;
TotalDummy
--
;
PS
(
node
)
->
TotalDummy
--
;
if
(
tp
->
tp_dummy
<
(
tp
+
1
)
->
tp_dummy
)
if
(
tp
->
tp_dummy
<
(
tp
+
1
)
->
tp_dummy
)
tp
++
;
tp
++
;
else
if
(
tp
->
tp_dummy
!=
0
)
else
if
(
tp
->
tp_dummy
!=
0
)
tp
=
Tape
;
tp
=
PS
(
node
)
->
Tape
;
else
{
else
{
Level
++
;
PS
(
node
)
->
Level
++
;
baseruns
=
Tape
[
0
].
tp_fib
;
baseruns
=
PS
(
node
)
->
Tape
[
0
].
tp_fib
;
for
(
tp
=
Tape
;
tp
-
Tape
<
TapeRange
;
tp
++
)
{
for
(
tp
=
PS
(
node
)
->
Tape
;
TotalDummy
+=
tp
-
PS
(
node
)
->
Tape
<
PS
(
node
)
->
TapeRange
;
tp
++
)
{
PS
(
node
)
->
TotalDummy
+=
(
tp
->
tp_dummy
=
baseruns
(
tp
->
tp_dummy
=
baseruns
+
(
tp
+
1
)
->
tp_fib
+
(
tp
+
1
)
->
tp_fib
-
tp
->
tp_fib
);
-
tp
->
tp_fib
);
tp
->
tp_fib
=
baseruns
tp
->
tp_fib
=
baseruns
+
(
tp
+
1
)
->
tp_fib
;
+
(
tp
+
1
)
->
tp_fib
;
}
}
tp
=
Tape
;
/* D4 */
tp
=
PS
(
node
)
->
Tape
;
/* D4 */
}
/* D3 */
}
/* D3 */
if
(
more
passes
)
if
(
extra
passes
)
if
(
--
more
passes
)
{
if
(
--
extra
passes
)
{
dumptuples
(
tp
->
tp_fil
e
);
dumptuples
(
nod
e
);
ENDRUN
(
tp
->
tp_file
);
ENDRUN
(
tp
->
tp_file
);
continue
;
continue
;
}
else
}
else
break
;
break
;
if
((
bool
)
createrun
(
sdesc
,
tp
->
tp_file
)
==
false
)
morepasses
=
1
+
(
Tuples
!=
NULL
);
if
((
bool
)
createrun
(
node
,
tp
->
tp_file
,
empty
)
==
false
)
extrapasses
=
1
+
(
PS
(
node
)
->
Tuples
!=
NULL
);
/* D2 */
/* D2 */
}
}
for
(
tp
=
Tape
+
TapeRange
;
tp
>=
Tape
;
tp
--
)
for
(
tp
=
PS
(
node
)
->
Tape
+
PS
(
node
)
->
TapeRange
;
tp
>=
PS
(
node
)
->
Tape
;
tp
--
)
rewind
(
tp
->
tp_file
);
/* D. */
rewind
(
tp
->
tp_file
);
/* D. */
heap_endscan
(
sdesc
);
}
}
/*
/*
* createrun - places the next run on file
* createrun - places the next run on file, grabbing the tuples by
* executing the subplan passed in
*
*
* Uses:
* Uses:
* Tuples, which should contain any tuples for this run
* Tuples, which should contain any tuples for this run
...
@@ -283,7 +333,7 @@ initialrun(Relation rdesc)
...
@@ -283,7 +333,7 @@ initialrun(Relation rdesc)
* Tuples contains the tuples for the following run upon exit
* Tuples contains the tuples for the following run upon exit
*/
*/
bool
bool
createrun
(
HeapScanDesc
sdesc
,
FILE
*
file
)
createrun
(
Sort
*
node
,
FILE
*
file
,
bool
*
empty
)
{
{
register
HeapTuple
lasttuple
;
register
HeapTuple
lasttuple
;
register
HeapTuple
btup
,
tup
;
register
HeapTuple
btup
,
tup
;
...
@@ -292,46 +342,73 @@ createrun(HeapScanDesc sdesc, FILE *file)
...
@@ -292,46 +342,73 @@ createrun(HeapScanDesc sdesc, FILE *file)
bool
foundeor
;
bool
foundeor
;
short
junk
;
short
junk
;
int
cr_tuples
=
0
;
/* Count tuples grabbed from plannode */
TupleTableSlot
*
cr_slot
;
Assert
(
node
!=
(
Sort
*
)
NULL
);
Assert
(
PS
(
node
)
!=
(
Psortstate
*
)
NULL
);
lasttuple
=
NULL
;
lasttuple
=
NULL
;
nextrun
=
NULL
;
nextrun
=
NULL
;
foundeor
=
false
;
foundeor
=
false
;
for
(
;
;
)
{
for
(
;
;
)
{
while
(
LACKMEM
(
)
&&
Tuples
!=
NULL
)
{
while
(
LACKMEM
(
node
)
&&
PS
(
node
)
->
Tuples
!=
NULL
)
{
if
(
lasttuple
!=
NULL
)
{
if
(
lasttuple
!=
NULL
)
{
FREEMEM
(
lasttuple
->
t_len
);
FREEMEM
(
node
,
lasttuple
->
t_len
);
FREE
(
lasttuple
);
FREE
(
lasttuple
);
TRACEMEM
(
createrun
);
TRACEMEM
(
createrun
);
}
}
lasttuple
=
tup
=
gettuple
(
&
Tuples
,
&
junk
);
lasttuple
=
tup
=
gettuple
(
&
PS
(
node
)
->
Tuples
,
&
junk
,
PUTTUP
(
tup
,
file
);
&
PS
(
node
)
->
treeContext
);
if
(
!
PS
(
node
)
->
using_tape_files
)
inittapes
(
node
);
PUTTUP
(
node
,
tup
,
PS
(
node
)
->
Tape
->
tp_file
);
TRACEOUT
(
createrun
,
tup
);
TRACEOUT
(
createrun
,
tup
);
}
}
if
(
LACKMEM
())
if
(
LACKMEM
(
node
))
break
;
break
;
btup
=
heap_getnext
(
sdesc
,
0
,
&
b
);
if
(
!
HeapTupleIsValid
(
btup
))
{
/* About to call ExecProcNode, it can mess up the state if it
* eventually calls another Sort node. So must stow it away here for
* the meantime. -Rex 2.2.1995
*/
cr_slot
=
ExecProcNode
(
outerPlan
((
Plan
*
)
node
),
(
Plan
*
)
node
);
if
(
TupIsNull
(
cr_slot
))
{
foundeor
=
true
;
foundeor
=
true
;
break
;
break
;
}
}
else
{
tup
=
tuplecopy
(
cr_slot
->
val
);
ExecClearTuple
(
cr_slot
);
PS
(
node
)
->
tupcount
++
;
cr_tuples
++
;
}
IncrProcessed
();
IncrProcessed
();
tup
=
tuplecopy
(
btup
,
sdesc
->
rs_rd
,
b
);
USEMEM
(
node
,
tup
->
t_len
);
USEMEM
(
tup
->
t_len
);
TRACEMEM
(
createrun
);
TRACEMEM
(
createrun
);
if
(
lasttuple
!=
NULL
&&
tuplecmp
(
tup
,
lasttuple
))
if
(
lasttuple
!=
NULL
&&
tuplecmp
(
tup
,
lasttuple
,
puttuple
(
&
nextrun
,
tup
,
0
);
&
PS
(
node
)
->
treeContext
))
puttuple
(
&
nextrun
,
tup
,
0
,
&
PS
(
node
)
->
treeContext
);
else
else
puttuple
(
&
Tuples
,
tup
,
0
);
puttuple
(
&
PS
(
node
)
->
Tuples
,
tup
,
0
,
&
PS
(
node
)
->
treeContext
);
ReleaseBuffer
(
b
);
}
}
if
(
lasttuple
!=
NULL
)
{
if
(
lasttuple
!=
NULL
)
{
FREEMEM
(
lasttuple
->
t_len
);
FREEMEM
(
node
,
lasttuple
->
t_len
);
FREE
(
lasttuple
);
FREE
(
lasttuple
);
TRACEMEM
(
createrun
);
TRACEMEM
(
createrun
);
}
}
dumptuples
(
file
);
dumptuples
(
node
);
if
(
PS
(
node
)
->
using_tape_files
)
ENDRUN
(
file
);
ENDRUN
(
file
);
/* delimit the end of the run */
/* delimit the end of the run */
Tuples
=
nextrun
;
PS
(
node
)
->
Tuples
=
nextrun
;
/* if we did not see any tuples, mark empty */
*
empty
=
(
cr_tuples
>
0
)
?
false
:
true
;
return
((
bool
)
!
foundeor
);
/* XXX - works iff bool is {0,1} */
return
((
bool
)
!
foundeor
);
/* XXX - works iff bool is {0,1} */
}
}
...
@@ -339,10 +416,10 @@ createrun(HeapScanDesc sdesc, FILE *file)
...
@@ -339,10 +416,10 @@ createrun(HeapScanDesc sdesc, FILE *file)
* tuplecopy - see also tuple.c:palloctup()
* tuplecopy - see also tuple.c:palloctup()
*
*
* This should eventually go there under that name? And this will
* This should eventually go there under that name? And this will
* then use
m
alloc directly (see version -r1.2).
* then use
p
alloc directly (see version -r1.2).
*/
*/
HeapTuple
HeapTuple
tuplecopy
(
HeapTuple
tup
,
Relation
rdesc
,
Buffer
b
)
tuplecopy
(
HeapTuple
tup
)
{
{
HeapTuple
rettup
;
HeapTuple
rettup
;
...
@@ -362,18 +439,22 @@ tuplecopy(HeapTuple tup, Relation rdesc, Buffer b)
...
@@ -362,18 +439,22 @@ tuplecopy(HeapTuple tup, Relation rdesc, Buffer b)
* file of tuples in order
* file of tuples in order
*/
*/
FILE
*
FILE
*
mergeruns
()
mergeruns
(
Sort
*
node
)
{
{
register
struct
tape
*
tp
;
register
struct
tape
*
tp
;
tp
=
Tape
+
TapeRange
;
Assert
(
node
!=
(
Sort
*
)
NULL
);
merge
(
tp
);
Assert
(
PS
(
node
)
!=
(
Psortstate
*
)
NULL
);
Assert
(
PS
(
node
)
->
using_tape_files
==
true
);
tp
=
PS
(
node
)
->
Tape
+
PS
(
node
)
->
TapeRange
;
merge
(
node
,
tp
);
rewind
(
tp
->
tp_file
);
rewind
(
tp
->
tp_file
);
while
(
--
Level
!=
0
)
{
while
(
--
PS
(
node
)
->
Level
!=
0
)
{
tp
=
tp
->
tp_prev
;
tp
=
tp
->
tp_prev
;
rewind
(
tp
->
tp_file
);
rewind
(
tp
->
tp_file
);
/* resettape(tp->tp_file); -not sufficient */
/* resettape(tp->tp_file); -not sufficient */
merge
(
tp
);
merge
(
node
,
tp
);
rewind
(
tp
->
tp_file
);
rewind
(
tp
->
tp_file
);
}
}
return
(
tp
->
tp_file
);
return
(
tp
->
tp_file
);
...
@@ -384,7 +465,7 @@ mergeruns()
...
@@ -384,7 +465,7 @@ mergeruns()
* (polyphase merge Alg.D(D5)--Knuth, Vol.3, p271)
* (polyphase merge Alg.D(D5)--Knuth, Vol.3, p271)
*/
*/
void
void
merge
(
struct
tape
*
dest
)
merge
(
Sort
*
node
,
struct
tape
*
dest
)
{
{
register
HeapTuple
tup
;
register
HeapTuple
tup
;
register
struct
tape
*
lasttp
;
/* (TAPE[P]) */
register
struct
tape
*
lasttp
;
/* (TAPE[P]) */
...
@@ -396,6 +477,10 @@ merge(struct tape *dest)
...
@@ -396,6 +477,10 @@ merge(struct tape *dest)
short
fromtape
;
short
fromtape
;
long
tuplen
;
long
tuplen
;
Assert
(
node
!=
(
Sort
*
)
NULL
);
Assert
(
PS
(
node
)
!=
(
Psortstate
*
)
NULL
);
Assert
(
PS
(
node
)
->
using_tape_files
==
true
);
lasttp
=
dest
->
tp_prev
;
lasttp
=
dest
->
tp_prev
;
times
=
lasttp
->
tp_fib
;
times
=
lasttp
->
tp_fib
;
for
(
tp
=
lasttp
;
tp
!=
dest
;
tp
=
tp
->
tp_prev
)
for
(
tp
=
lasttp
;
tp
!=
dest
;
tp
=
tp
->
tp_prev
)
...
@@ -403,95 +488,217 @@ merge(struct tape *dest)
...
@@ -403,95 +488,217 @@ merge(struct tape *dest)
tp
->
tp_fib
+=
times
;
tp
->
tp_fib
+=
times
;
/* Tape[].tp_fib (A[]) is set to proper exit values */
/* Tape[].tp_fib (A[]) is set to proper exit values */
if
(
TotalDummy
<
TapeRange
)
/* no complete dummy runs */
if
(
PS
(
node
)
->
TotalDummy
<
PS
(
node
)
->
TapeRange
)
/* no complete dummy runs */
outdummy
=
0
;
outdummy
=
0
;
else
{
else
{
outdummy
=
TotalDummy
;
/* a large positive number */
outdummy
=
PS
(
node
)
->
TotalDummy
;
/* a large positive number */
for
(
tp
=
lasttp
;
tp
!=
dest
;
tp
=
tp
->
tp_prev
)
for
(
tp
=
lasttp
;
tp
!=
dest
;
tp
=
tp
->
tp_prev
)
if
(
outdummy
>
tp
->
tp_dummy
)
if
(
outdummy
>
tp
->
tp_dummy
)
outdummy
=
tp
->
tp_dummy
;
outdummy
=
tp
->
tp_dummy
;
for
(
tp
=
lasttp
;
tp
!=
dest
;
tp
=
tp
->
tp_prev
)
for
(
tp
=
lasttp
;
tp
!=
dest
;
tp
=
tp
->
tp_prev
)
tp
->
tp_dummy
-=
outdummy
;
tp
->
tp_dummy
-=
outdummy
;
tp
->
tp_dummy
+=
outdummy
;
tp
->
tp_dummy
+=
outdummy
;
TotalDummy
-=
outdummy
*
TapeRange
;
PS
(
node
)
->
TotalDummy
-=
outdummy
*
PS
(
node
)
->
TapeRange
;
/* do not add the outdummy runs yet */
/* do not add the outdummy runs yet */
times
-=
outdummy
;
times
-=
outdummy
;
}
}
destfile
=
dest
->
tp_file
;
destfile
=
dest
->
tp_file
;
while
(
times
--
!=
0
)
{
/* merge one run */
while
(
times
--
!=
0
)
{
/* merge one run */
tuples
=
NULL
;
tuples
=
NULL
;
if
(
TotalDummy
==
0
)
if
(
PS
(
node
)
->
TotalDummy
==
0
)
for
(
tp
=
dest
->
tp_prev
;
tp
!=
dest
;
tp
=
tp
->
tp_prev
)
{
for
(
tp
=
dest
->
tp_prev
;
tp
!=
dest
;
tp
=
tp
->
tp_prev
)
{
GETLEN
(
tuplen
,
tp
->
tp_file
);
GETLEN
(
tuplen
,
tp
->
tp_file
);
tup
=
ALLOCTUP
(
tuplen
);
tup
=
ALLOCTUP
(
tuplen
);
USEMEM
(
tuplen
);
USEMEM
(
node
,
tuplen
);
TRACEMEM
(
merge
);
TRACEMEM
(
merge
);
SETTUPLEN
(
tup
,
tuplen
);
SETTUPLEN
(
tup
,
tuplen
);
GETTUP
(
tup
,
tuplen
,
tp
->
tp_file
);
GETTUP
(
node
,
tup
,
tuplen
,
tp
->
tp_file
);
puttuple
(
&
tuples
,
tup
,
TAPENO
(
tp
));
puttuple
(
&
tuples
,
tup
,
tp
-
PS
(
node
)
->
Tape
,
&
PS
(
node
)
->
treeContext
);
}
}
else
{
else
{
for
(
tp
=
dest
->
tp_prev
;
tp
!=
dest
;
tp
=
tp
->
tp_prev
)
{
for
(
tp
=
dest
->
tp_prev
;
tp
!=
dest
;
tp
=
tp
->
tp_prev
)
{
if
(
tp
->
tp_dummy
!=
0
)
{
if
(
tp
->
tp_dummy
!=
0
)
{
tp
->
tp_dummy
--
;
tp
->
tp_dummy
--
;
TotalDummy
--
;
PS
(
node
)
->
TotalDummy
--
;
}
else
{
}
else
{
GETLEN
(
tuplen
,
tp
->
tp_file
);
GETLEN
(
tuplen
,
tp
->
tp_file
);
tup
=
ALLOCTUP
(
tuplen
);
tup
=
ALLOCTUP
(
tuplen
);
USEMEM
(
tuplen
);
USEMEM
(
node
,
tuplen
);
TRACEMEM
(
merge
);
TRACEMEM
(
merge
);
SETTUPLEN
(
tup
,
tuplen
);
SETTUPLEN
(
tup
,
tuplen
);
GETTUP
(
tup
,
tuplen
,
tp
->
tp_file
);
GETTUP
(
node
,
tup
,
tuplen
,
tp
->
tp_file
);
puttuple
(
&
tuples
,
tup
,
TAPENO
(
tp
));
puttuple
(
&
tuples
,
tup
,
tp
-
PS
(
node
)
->
Tape
,
&
PS
(
node
)
->
treeContext
);
}
}
}
}
}
}
while
(
tuples
!=
NULL
)
{
while
(
tuples
!=
NULL
)
{
/* possible optimization by using count in tuples */
/* possible optimization by using count in tuples */
tup
=
gettuple
(
&
tuples
,
&
fromtape
);
tup
=
gettuple
(
&
tuples
,
&
fromtape
,
&
PS
(
node
)
->
treeContext
);
PUTTUP
(
tup
,
destfile
);
PUTTUP
(
node
,
tup
,
destfile
);
FREEMEM
(
tup
->
t_len
);
FREEMEM
(
node
,
tup
->
t_len
);
FREE
(
tup
);
FREE
(
tup
);
TRACEMEM
(
merge
);
TRACEMEM
(
merge
);
GETLEN
(
tuplen
,
Tape
[
fromtape
].
tp_file
);
GETLEN
(
tuplen
,
PS
(
node
)
->
Tape
[
fromtape
].
tp_file
);
if
(
tuplen
==
0
)
if
(
tuplen
==
0
)
;
;
else
{
else
{
tup
=
ALLOCTUP
(
tuplen
);
tup
=
ALLOCTUP
(
tuplen
);
USEMEM
(
tuplen
);
USEMEM
(
node
,
tuplen
);
TRACEMEM
(
merge
);
TRACEMEM
(
merge
);
SETTUPLEN
(
tup
,
tuplen
);
SETTUPLEN
(
tup
,
tuplen
);
GETTUP
(
tup
,
tuplen
,
Tape
[
fromtape
].
tp_file
);
GETTUP
(
node
,
tup
,
tuplen
,
PS
(
node
)
->
Tape
[
fromtape
].
tp_file
);
puttuple
(
&
tuples
,
tup
,
fromtape
);
puttuple
(
&
tuples
,
tup
,
fromtape
,
&
PS
(
node
)
->
treeContext
);
}
}
}
}
ENDRUN
(
destfile
);
ENDRUN
(
destfile
);
}
}
TotalDummy
+=
outdummy
;
PS
(
node
)
->
TotalDummy
+=
outdummy
;
}
}
/*
/*
*
endpsort - creates the new relation and unlinks the tape files
*
dumptuples - stores all the tuples in tree into file
*/
*/
void
void
endpsort
(
Relation
rdesc
,
FILE
*
file
)
dumptuples
(
Sort
*
node
)
{
register
struct
leftist
*
tp
;
register
struct
leftist
*
newp
;
struct
leftist
**
treep
=
&
PS
(
node
)
->
Tuples
;
LeftistContext
context
=
&
PS
(
node
)
->
treeContext
;
HeapTuple
tup
;
int
memtupindex
=
0
;
if
(
!
PS
(
node
)
->
using_tape_files
)
{
Assert
(
PS
(
node
)
->
memtuples
==
NULL
);
PS
(
node
)
->
memtuples
=
palloc
(
PS
(
node
)
->
tupcount
*
sizeof
(
HeapTuple
));
}
tp
=
*
treep
;
while
(
tp
!=
NULL
)
{
tup
=
tp
->
lt_tuple
;
if
(
tp
->
lt_dist
==
1
)
/* lt_right == NULL */
newp
=
tp
->
lt_left
;
else
newp
=
lmerge
(
tp
->
lt_left
,
tp
->
lt_right
,
context
);
FREEMEM
(
node
,
sizeof
(
struct
leftist
));
FREE
(
tp
);
if
(
PS
(
node
)
->
using_tape_files
)
{
PUTTUP
(
node
,
tup
,
PS
(
node
)
->
Tape
->
tp_file
);
FREEMEM
(
node
,
tup
->
t_len
);
FREE
(
tup
);
}
else
PS
(
node
)
->
memtuples
[
memtupindex
++
]
=
tup
;
tp
=
newp
;
}
*
treep
=
NULL
;
}
/*
* psort_grabtuple - gets a tuple from the sorted file and returns it.
* If there are no tuples left, returns NULL.
* Should not call psort_end unless this has returned
* a NULL indicating the last tuple has been processed.
*/
HeapTuple
psort_grabtuple
(
Sort
*
node
)
{
{
register
struct
tape
*
tp
;
register
HeapTuple
tup
;
register
HeapTuple
tup
;
long
tuplen
;
long
tuplen
;
if
(
!
feof
(
file
))
Assert
(
node
!=
(
Sort
*
)
NULL
);
while
(
GETLEN
(
tuplen
,
file
)
&&
tuplen
!=
0
)
{
Assert
(
PS
(
node
)
!=
(
Psortstate
*
)
NULL
);
tup
=
ALLOCTUP
(
tuplen
);
SortMemory
+=
tuplen
;
if
(
PS
(
node
)
->
using_tape_files
==
true
)
{
if
(
!
feof
(
PS
(
node
)
->
psort_grab_file
))
{
if
(
GETLEN
(
tuplen
,
PS
(
node
)
->
psort_grab_file
)
&&
tuplen
!=
0
)
{
tup
=
(
HeapTuple
)
palloc
((
unsigned
)
tuplen
);
SETTUPLEN
(
tup
,
tuplen
);
SETTUPLEN
(
tup
,
tuplen
);
GETTUP
(
tup
,
tuplen
,
file
);
GETTUP
(
node
,
tup
,
tuplen
,
PS
(
node
)
->
psort_grab_file
);
heap_insert
(
rdesc
,
tup
);
FREE
(
tup
);
/* Update current merged sort file position */
SortMemory
-=
tuplen
;
PS
(
node
)
->
psort_current
+=
tuplen
;
return
tup
;
}
}
for
(
tp
=
Tape
+
TapeRange
;
tp
>=
Tape
;
tp
--
)
else
return
NULL
;
}
else
return
NULL
;
}
else
{
if
(
PS
(
node
)
->
psort_current
<
PS
(
node
)
->
tupcount
)
return
PS
(
node
)
->
memtuples
[
PS
(
node
)
->
psort_current
++
];
else
return
NULL
;
}
}
/*
* psort_markpos - saves current position in the merged sort file
*/
void
psort_markpos
(
Sort
*
node
)
{
Assert
(
node
!=
(
Sort
*
)
NULL
);
Assert
(
PS
(
node
)
!=
(
Psortstate
*
)
NULL
);
PS
(
node
)
->
psort_saved
=
PS
(
node
)
->
psort_current
;
}
/*
* psort_restorepos- restores current position in merged sort file to
* last saved position
*/
void
psort_restorepos
(
Sort
*
node
)
{
Assert
(
node
!=
(
Sort
*
)
NULL
);
Assert
(
PS
(
node
)
!=
(
Psortstate
*
)
NULL
);
if
(
PS
(
node
)
->
using_tape_files
==
true
)
fseek
(
PS
(
node
)
->
psort_grab_file
,
PS
(
node
)
->
psort_saved
,
SEEK_SET
);
PS
(
node
)
->
psort_current
=
PS
(
node
)
->
psort_saved
;
}
/*
* psort_end - unlinks the tape files, and cleans up. Should not be
* called unless psort_grabtuple has returned a NULL.
*/
void
psort_end
(
Sort
*
node
)
{
register
struct
tape
*
tp
;
if
(
!
node
->
cleaned
)
{
Assert
(
node
!=
(
Sort
*
)
NULL
);
/* Assert(PS(node) != (Psortstate *) NULL); */
/*
* I'm changing this because if we are sorting a relation
* with no tuples, psortstate is NULL.
*/
if
(
PS
(
node
)
!=
(
Psortstate
*
)
NULL
)
{
if
(
PS
(
node
)
->
using_tape_files
==
true
)
for
(
tp
=
PS
(
node
)
->
Tape
+
PS
(
node
)
->
TapeRange
;
tp
>=
PS
(
node
)
->
Tape
;
tp
--
)
destroytape
(
tp
->
tp_file
);
destroytape
(
tp
->
tp_file
);
else
if
(
PS
(
node
)
->
memtuples
)
pfree
(
PS
(
node
)
->
memtuples
);
NDirectFileRead
+=
(
int
)
ceil
((
double
)
PS
(
node
)
->
BytesRead
/
BLCKSZ
);
NDirectFileWrite
+=
(
int
)
ceil
((
double
)
PS
(
node
)
->
BytesWritten
/
BLCKSZ
);
pfree
((
void
*
)
node
->
psortstate
);
node
->
cleaned
=
TRUE
;
}
}
}
}
/*
/*
...
@@ -525,23 +732,31 @@ gettape()
...
@@ -525,23 +732,31 @@ gettape()
register
struct
tapelst
*
tp
;
register
struct
tapelst
*
tp
;
FILE
*
file
;
FILE
*
file
;
static
int
tapeinit
=
0
;
static
int
tapeinit
=
0
;
char
*
mktemp
();
static
unsigned
int
uniqueFileId
=
0
;
extern
int
errno
;
char
uniqueName
[
MAXPGPATH
];
tp
=
(
struct
tapelst
*
)
palloc
((
unsigned
)
sizeof
(
struct
tapelst
));
tp
=
(
struct
tapelst
*
)
palloc
((
unsigned
)
sizeof
(
struct
tapelst
));
if
(
!
tapeinit
)
{
Tempfile
[
sizeof
(
TEMPDIR
)
-
1
]
=
'/'
;
sprintf
(
uniqueName
,
"%spg_psort.%d.%d"
,
TEMPDIR
,
getpid
(),
uniqueFileId
);
memmove
(
Tempfile
+
sizeof
(
TEMPDIR
),
TAPEEXT
,
sizeof
(
TAPEEXT
));
uniqueFileId
++
;
tapeinit
=
1
;
tapeinit
=
1
;
}
tp
->
tl_name
=
palloc
((
unsigned
)
sizeof
(
Tempfile
));
tp
->
tl_name
=
palloc
((
unsigned
)
sizeof
(
uniqueName
));
/*
/*
* now, copy template with final null into
m
alloc'd space
* now, copy template with final null into
p
alloc'd space
*/
*/
memmove
(
tp
->
tl_name
,
Tempfile
,
sizeof
(
TEMPDIR
)
+
sizeof
(
TAPEEXT
));
mktemp
(
tp
->
tl_name
);
memmove
(
tp
->
tl_name
,
uniqueName
,
strlen
(
uniqueName
));
AllocateFile
();
AllocateFile
();
file
=
fopen
(
tp
->
tl_name
,
"w+"
);
file
=
fopen
(
tp
->
tl_name
,
"w+"
);
if
(
file
==
NULL
)
{
if
(
file
==
NULL
)
{
elog
(
NOTICE
,
"psort: gettape: fopen returned error code %i"
,
errno
);
/* XXX this should not happen */
/* XXX this should not happen */
FreeFile
();
FreeFile
();
FREE
(
tp
->
tl_name
);
FREE
(
tp
->
tl_name
);
...
...
src/include/nodes/execnodes.h
View file @
f5f366e1
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
*
*
* Copyright (c) 1994, Regents of the University of California
* Copyright (c) 1994, Regents of the University of California
*
*
* $Id: execnodes.h,v 1.
6 1996/11/04 08:52:54 scrappy
Exp $
* $Id: execnodes.h,v 1.
7 1997/08/06 03:42:02 momjian
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -605,7 +605,7 @@ typedef struct SortState {
...
@@ -605,7 +605,7 @@ typedef struct SortState {
CommonScanState
csstate
;
/* its first field is NodeTag */
CommonScanState
csstate
;
/* its first field is NodeTag */
bool
sort_Flag
;
bool
sort_Flag
;
ScanKey
sort_Keys
;
ScanKey
sort_Keys
;
Relation
sort_TempRelation
;
bool
cleaned
;
}
SortState
;
}
SortState
;
/* ----------------
/* ----------------
...
...
src/include/nodes/plannodes.h
View file @
f5f366e1
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
*
*
* Copyright (c) 1994, Regents of the University of California
* Copyright (c) 1994, Regents of the University of California
*
*
* $Id: plannodes.h,v 1.
5 1996/11/05 08:18:44 scrappy
Exp $
* $Id: plannodes.h,v 1.
6 1997/08/06 03:42:04 momjian
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -265,6 +265,8 @@ typedef struct Sort {
...
@@ -265,6 +265,8 @@ typedef struct Sort {
Oid
tempid
;
Oid
tempid
;
int
keycount
;
int
keycount
;
SortState
*
sortstate
;
SortState
*
sortstate
;
void
*
psortstate
;
bool
cleaned
;
}
Sort
;
}
Sort
;
/* ----------------
/* ----------------
...
...
src/include/utils/lselect.h
View file @
f5f366e1
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
*
*
* Copyright (c) 1994, Regents of the University of California
* Copyright (c) 1994, Regents of the University of California
*
*
* $Id: lselect.h,v 1.
3 1996/11/04 11:51:19 scrappy
Exp $
* $Id: lselect.h,v 1.
4 1997/08/06 03:42:07 momjian
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -14,7 +14,7 @@
...
@@ -14,7 +14,7 @@
#define LSELECT_H
#define LSELECT_H
#include <stdio.h>
#include <stdio.h>
#include
<access/htup.h>
#include
"access/htup.h"
struct
leftist
{
struct
leftist
{
short
lt_dist
;
/* distance to leaf/empty node */
short
lt_dist
;
/* distance to leaf/empty node */
...
@@ -24,17 +24,26 @@ struct leftist {
...
@@ -24,17 +24,26 @@ struct leftist {
struct
leftist
*
lt_right
;
struct
leftist
*
lt_right
;
};
};
extern
struct
leftist
*
Tuples
;
/* replaces global variables in lselect.c to make it reentrant */
typedef
struct
{
TupleDesc
tupDesc
;
int
nKeys
;
ScanKey
scanKeys
;
int
sortMem
;
/* needed for psort */
}
LeftistContextData
;
typedef
LeftistContextData
*
LeftistContext
;
extern
struct
leftist
*
lmerge
(
struct
leftist
*
pt
,
struct
leftist
*
qt
);
extern
struct
leftist
*
lmerge
(
struct
leftist
*
pt
,
struct
leftist
*
qt
,
extern
HeapTuple
gettuple
(
struct
leftist
**
treep
,
short
*
devnum
);
LeftistContext
context
);
extern
int
puttuple
(
struct
leftist
**
treep
,
HeapTuple
newtuple
,
int
devnum
);
extern
HeapTuple
gettuple
(
struct
leftist
**
treep
,
short
*
devnum
,
extern
void
dumptuples
(
FILE
*
file
);
LeftistContext
context
);
extern
int
tuplecmp
(
HeapTuple
ltup
,
HeapTuple
rtup
);
extern
void
puttuple
(
struct
leftist
**
treep
,
HeapTuple
newtuple
,
short
devnum
,
LeftistContext
context
);
extern
int
tuplecmp
(
HeapTuple
ltup
,
HeapTuple
rtup
,
LeftistContext
context
);
#ifdef EBUG
#ifdef EBUG
extern
void
checktree
(
struct
leftist
*
tree
);
extern
void
checktree
(
struct
leftist
*
tree
,
LeftistContext
context
);
extern
int
checktreer
(
struct
leftist
*
tree
,
int
level
);
extern
int
checktreer
(
struct
leftist
*
tree
,
int
level
,
LeftistContext
context
);
#endif
/* EBUG */
#endif
/* EBUG */
#endif
/* LSELECT_H */
#endif
/* LSELECT_H */
src/include/utils/psort.h
View file @
f5f366e1
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
*
*
* Copyright (c) 1994, Regents of the University of California
* Copyright (c) 1994, Regents of the University of California
*
*
* $Id: psort.h,v 1.
3 1997/05/20 11:37:33 vadim
Exp $
* $Id: psort.h,v 1.
4 1997/08/06 03:42:13 momjian
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -14,11 +14,13 @@
...
@@ -14,11 +14,13 @@
#define PSORT_H
#define PSORT_H
#include <stdio.h>
#include <stdio.h>
#include <access/relscan.h>
#include "access/relscan.h"
#include "utils/lselect.h"
#include "nodes/plannodes.h"
#define SORTMEM (1 << 18)
/* 1/4 M - any static memory */
#define SORTMEM (1 << 18)
/* 1/4 M - any static memory */
#define MAXTAPES 7
/* 7--See Fig. 70, p273 */
#define MAXTAPES 7
/* 7--See Fig. 70, p273 */
#define TAPEEXT
"pg_psort.XXXXXX"
/* TEMPDIR/TAPEEXT */
#define TAPEEXT
LEN strlen("pg_psort.xxxxx.xxx")
/* TEMPDIR/TAPEEXT */
#define FREE(x) pfree((char *) x)
#define FREE(x) pfree((char *) x)
struct
tape
{
struct
tape
{
...
@@ -35,13 +37,38 @@ struct cmplist {
...
@@ -35,13 +37,38 @@ struct cmplist {
struct
cmplist
*
cp_next
;
/* next in chain */
struct
cmplist
*
cp_next
;
/* next in chain */
};
};
extern
int
Nkeys
;
/* This structure preserves the state of psort between calls from different
extern
ScanKey
key
;
* nodes to its interface functions. Basically, it includes all of the global
extern
int
SortMemory
;
/* free memory */
* variables in psort. In case you were wondering, pointers to these structures
extern
Relation
SortRdesc
;
* are included in Sort node structures. -Rex 2.6.1995
extern
struct
leftist
*
Tuples
;
*/
typedef
struct
Psortstate
{
LeftistContextData
treeContext
;
int
TapeRange
;
int
Level
;
int
TotalDummy
;
struct
tape
Tape
[
MAXTAPES
];
int
BytesRead
;
int
BytesWritten
;
int
tupcount
;
struct
leftist
*
Tuples
;
FILE
*
psort_grab_file
;
long
psort_current
;
/* could be file offset, or array index */
long
psort_saved
;
/* could be file offset, or array index */
bool
using_tape_files
;
HeapTuple
*
memtuples
;
}
Psortstate
;
#ifdef EBUG
#ifdef EBUG
#include <stdio.h>
#include "utils/elog.h"
#include "storage/buf.h"
#include "storage/bufmgr.h"
#define PDEBUG(PROC, S1)\
#define PDEBUG(PROC, S1)\
elog(DEBUG, "%s:%d>> PROC: %s.", __FILE__, __LINE__, S1)
elog(DEBUG, "%s:%d>> PROC: %s.", __FILE__, __LINE__, S1)
...
@@ -69,15 +96,21 @@ if (1) CODE; else
...
@@ -69,15 +96,21 @@ if (1) CODE; else
#endif
#endif
/* psort.c */
/* psort.c */
extern
void
psort
(
Relation
oldrel
,
Relation
newrel
,
int
nkeys
,
ScanKey
key
);
extern
bool
psort_begin
(
Sort
*
node
,
int
nkeys
,
ScanKey
key
);
extern
void
init
psort
(
void
);
extern
void
init
tapes
(
Sort
*
node
);
extern
void
resetpsort
(
void
);
extern
void
resetpsort
(
void
);
extern
void
initialrun
(
Relation
rdesc
);
extern
void
initialrun
(
Sort
*
node
,
bool
*
empty
);
extern
bool
createrun
(
HeapScanDesc
sdesc
,
FILE
*
file
);
extern
bool
createrun
(
Sort
*
node
,
FILE
*
file
,
bool
*
empty
);
extern
HeapTuple
tuplecopy
(
HeapTuple
tup
,
Relation
rdesc
,
Buffer
b
);
extern
HeapTuple
tuplecopy
(
HeapTuple
tup
);
extern
FILE
*
mergeruns
(
void
);
extern
FILE
*
mergeruns
(
Sort
*
node
);
extern
void
merge
(
struct
tape
*
dest
);
extern
void
merge
(
Sort
*
node
,
struct
tape
*
dest
);
extern
void
endpsort
(
Relation
rdesc
,
FILE
*
file
);
extern
void
dumptuples
(
Sort
*
node
);
extern
HeapTuple
psort_grabtuple
(
Sort
*
node
);
extern
void
psort_markpos
(
Sort
*
node
);
extern
void
psort_restorepos
(
Sort
*
node
);
extern
void
psort_end
(
Sort
*
node
);
extern
FILE
*
gettape
(
void
);
extern
FILE
*
gettape
(
void
);
extern
void
resettape
(
FILE
*
file
);
extern
void
resettape
(
FILE
*
file
);
extern
void
destroytape
(
FILE
*
file
);
extern
void
destroytape
(
FILE
*
file
);
...
...
src/man/postgres.1
View file @
f5f366e1
.\" This is -*-nroff-*-
.\" This is -*-nroff-*-
.\" XXX standard disclaimer belongs here....
.\" XXX standard disclaimer belongs here....
.\" $Header: /cvsroot/pgsql/src/man/Attic/postgres.1,v 1.
5 1997/01/26 15:32:20 scrappy
Exp $
.\" $Header: /cvsroot/pgsql/src/man/Attic/postgres.1,v 1.
6 1997/08/06 03:42:18 momjian
Exp $
.TH POSTGRES95 UNIX 12/08/96 Postgres95 Postgres95
.TH POSTGRES95 UNIX 12/08/96 Postgres95 Postgres95
.SH NAME
.SH NAME
postgres \(em the Postgres backend server
postgres \(em the Postgres backend server
...
@@ -79,7 +79,10 @@ is the number of shared-memory buffers that the
...
@@ -79,7 +79,10 @@ is the number of shared-memory buffers that the
.IR "postmaster"
.IR "postmaster"
has allocated for the backend server processes that it starts. If the
has allocated for the backend server processes that it starts. If the
backend is running standalone, this specifies the number of buffers to
backend is running standalone, this specifies the number of buffers to
allocate. This value defaults to 64.
allocate. This value defaults to 64, and each buffer is 8k bytes.
.TP
.BR "-E"
Echo all queries.
.TP
.TP
.BR "-F"
.BR "-F"
Disable automatic fsync() call after each transaction.
Disable automatic fsync() call after each transaction.
...
@@ -96,8 +99,10 @@ useful for interactive use.
...
@@ -96,8 +99,10 @@ useful for interactive use.
.BR "-Q"
.BR "-Q"
Specifies \*(lqquiet\*(rq mode.
Specifies \*(lqquiet\*(rq mode.
.TP
.TP
.BR "-E"
.BR "-S"
Echo all queries.
Specifies the amount of memory to be used by internal sorts before using
disk files for sorting. This value is specified in 1k bytes, and
defaults to 512.
.TP
.TP
.BR "-e"
.BR "-e"
The
The
...
@@ -154,15 +159,6 @@ Turns off the locking system.
...
@@ -154,15 +159,6 @@ Turns off the locking system.
.BR "-N"
.BR "-N"
Disables use of newline as a query delimiter.
Disables use of newline as a query delimiter.
.TP
.TP
.BR "-S"
Indicates that the transaction system can run with the assumption of
stable main memory, thereby avoiding the necessary flushing of data
and log pages to disk at the end of each transaction system. This is
only used for performance comparisons for stable vs. non-stable
storage. Do not use this in other cases, as recovery after a system
crash may be impossible when this option is specified in the absence
of stable main memory.
.TP
.BR "-b"
.BR "-b"
Enables generation of bushy query plan trees (as opposed to left-deep
Enables generation of bushy query plan trees (as opposed to left-deep
query plans trees). These query plans are not intended for actual
query plans trees). These query plans are not intended for actual
...
...
src/man/postmaster.1
View file @
f5f366e1
.\" This is -*-nroff-*-
.\" This is -*-nroff-*-
.\" XXX standard disclaimer belongs here....
.\" XXX standard disclaimer belongs here....
.\" $Header: /cvsroot/pgsql/src/man/Attic/postmaster.1,v 1.
5 1997/02/19 01:31:30
momjian Exp $
.\" $Header: /cvsroot/pgsql/src/man/Attic/postmaster.1,v 1.
6 1997/08/06 03:42:21
momjian Exp $
.TH POSTMASTER UNIX 11/05/95 PostgreSQL PostgreSQL
.TH POSTMASTER UNIX 11/05/95 PostgreSQL PostgreSQL
.SH "NAME"
.SH "NAME"
postmaster \(em run the Postgres postmaster
postmaster \(em run the Postgres postmaster
...
@@ -60,7 +60,7 @@ understands the following command-line options:
...
@@ -60,7 +60,7 @@ understands the following command-line options:
is the number of shared-memory buffers for the
is the number of shared-memory buffers for the
.IR "postmaster"
.IR "postmaster"
to allocate and manage for the backend server processes that it
to allocate and manage for the backend server processes that it
starts. This value defaults to 64.
starts. This value defaults to 64
, and each buffer is 8k bytes
.
.TP
.TP
.BR "-D" " data_dir"
.BR "-D" " data_dir"
Specifies the directory to use as the root of the tree of database
Specifies the directory to use as the root of the tree of database
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment