Remove now-dead sort modules.
authorTom Lane
Sun, 17 Oct 1999 22:19:07 +0000 (22:19 +0000)
committerTom Lane
Sun, 17 Oct 1999 22:19:07 +0000 (22:19 +0000)
src/backend/utils/sort/lselect.c [deleted file]
src/backend/utils/sort/psort.c [deleted file]
src/include/lib/qsort.h [deleted file]
src/include/utils/lselect.h [deleted file]
src/include/utils/psort.h [deleted file]

diff --git a/src/backend/utils/sort/lselect.c b/src/backend/utils/sort/lselect.c
deleted file mode 100644 (file)
index 7f521b8..0000000
+++ /dev/null
@@ -1,355 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * lselect.c
- *   leftist tree selection algorithm (linked priority queue--Knuth, Vol.3,
- *   pp.150-52)
- *
- * Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/sort/Attic/lselect.c,v 1.19 1999/07/17 20:18:16 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-
-#include "postgres.h"
-
-
-#include "access/heapam.h"
-#include "utils/lselect.h"
-
-/*
- *     lmerge          - merges two leftist trees into one
- *
- *     Note:
- *             Enforcing the rule that pt->lt_dist >= qt->lt_dist may
- *             simplifify much of the code.  Removing recursion will not
- *             speed up code significantly.
- */
-struct leftist *
-lmerge(struct leftist * pt, struct leftist * qt, LeftistContext context)
-{
-   struct leftist *root,
-              *majorLeftist,
-              *minorLeftist;
-   int         dist;
-
-   if (tuplecmp(pt->lt_tuple, qt->lt_tuple, context))
-   {
-       root = pt;
-       majorLeftist = qt;
-   }
-   else
-   {
-       root = qt;
-       majorLeftist = pt;
-   }
-   if (root->lt_left == NULL)
-       root->lt_left = majorLeftist;
-   else
-   {
-       if ((minorLeftist = root->lt_right) != NULL)
-           majorLeftist = lmerge(majorLeftist, minorLeftist, context);
-       if ((dist = root->lt_left->lt_dist) < majorLeftist->lt_dist)
-       {
-           root->lt_dist = 1 + dist;
-           root->lt_right = root->lt_left;
-           root->lt_left = majorLeftist;
-       }
-       else
-       {
-           root->lt_dist = 1 + majorLeftist->lt_dist;
-           root->lt_right = majorLeftist;
-       }
-   }
-   return root;
-}
-
-static struct leftist *
-linsert(struct leftist * root, struct leftist * new1, LeftistContext context)
-{
-   struct leftist *left,
-              *right;
-
-   if (!tuplecmp(root->lt_tuple, new1->lt_tuple, context))
-   {
-       new1->lt_left = root;
-       return new1;
-   }
-   left = root->lt_left;
-   right = root->lt_right;
-   if (right == NULL)
-   {
-       if (left == NULL)
-           root->lt_left = new1;
-       else
-       {
-           root->lt_right = new1;
-           root->lt_dist = 2;
-       }
-       return root;
-   }
-   right = linsert(right, new1, context);
-   if (right->lt_dist < left->lt_dist)
-   {
-       root->lt_dist = 1 + left->lt_dist;
-       root->lt_left = right;
-       root->lt_right = left;
-   }
-   else
-   {
-       root->lt_dist = 1 + right->lt_dist;
-       root->lt_right = right;
-   }
-   return root;
-}
-
-/*
- *     gettuple        - returns tuple at top of tree (Tuples)
- *
- *     Returns:
- *             tuple at top of tree, NULL if failed ALLOC()
- *             *devnum is set to the devnum of tuple returned
- *             *treep is set to the new tree
- *
- *     Note:
- *             *treep must not be NULL
- *             NULL is currently never returned BUG
- */
-HeapTuple
-gettuple(struct leftist ** treep,
-        short *devnum,         /* device from which tuple came */
-        LeftistContext context)
-{
-   struct leftist *tp;
-   HeapTuple   tup;
-
-   tp = *treep;
-   tup = tp->lt_tuple;
-   *devnum = tp->lt_devnum;
-   if (tp->lt_dist == 1)       /* lt_left == NULL */
-       *treep = tp->lt_left;
-   else
-       *treep = lmerge(tp->lt_left, tp->lt_right, context);
-
-   pfree(tp);
-   return tup;
-}
-
-/*
- *     puttuple        - inserts new tuple into tree
- *
- *     Returns:
- *             NULL iff failed ALLOC()
- *
- *     Note:
- *             Currently never returns NULL BUG
- */
-void
-puttuple(struct leftist ** treep,
-        HeapTuple newtuple,
-        short devnum,
-        LeftistContext context)
-{
-   struct leftist *new1;
-   struct leftist *tp;
-
-   new1 = (struct leftist *) palloc((unsigned) sizeof(struct leftist));
-   new1->lt_dist = 1;
-   new1->lt_devnum = devnum;
-   new1->lt_tuple = newtuple;
-   new1->lt_left = NULL;
-   new1->lt_right = NULL;
-   if ((tp = *treep) == NULL)
-       *treep = new1;
-   else
-       *treep = linsert(tp, new1, context);
-   return;
-}
-
-
-/*
- *     tuplecmp        - Compares two tuples with respect CmpList
- *
- *     Returns:
- *             1 if left < right ;0 otherwise
- *     Assumtions:
- */
-int
-tuplecmp(HeapTuple ltup, HeapTuple rtup, LeftistContext context)
-{
-   int         nkey;
-   int         result = 0;
-
-   if (ltup == (HeapTuple) NULL)
-       return 0;
-   if (rtup == (HeapTuple) NULL)
-       return 1;
-   for (nkey = 0; nkey < context->nKeys; nkey++)
-   {
-       ScanKey     thisKey = & context->scanKeys[nkey];
-       Datum       lattr,
-                   rattr;
-       bool        lisnull,
-                   risnull;
-
-       lattr = heap_getattr(ltup, thisKey->sk_attno,
-                            context->tupDesc, &lisnull);
-       rattr = heap_getattr(rtup, thisKey->sk_attno,
-                            context->tupDesc, &risnull);
-       if (lisnull)
-       {
-           if (risnull)
-               continue;       /* treat two nulls as equal */
-           return 0;           /* else, a null sorts after all else */
-       }
-       if (risnull)
-           return 1;
-       if (thisKey->sk_flags & SK_COMMUTE)
-       {
-           if (!(result =
-                 (long) (*fmgr_faddr(&thisKey->sk_func)) (rattr, lattr)))
-               result =
-                   -(long) (*fmgr_faddr(&thisKey->sk_func)) (lattr, rattr);
-       }
-       else
-       {
-           if (!(result =
-                 (long) (*fmgr_faddr(&thisKey->sk_func)) (lattr, rattr)))
-               result =
-                   -(long) (*fmgr_faddr(&thisKey->sk_func)) (rattr, lattr);
-       }
-       if (result)
-           break;
-   }
-   return result == 1;
-}
-
-#ifdef EBUG
-void
-checktree(struct leftist * tree, LeftistContext context)
-{
-   int         lnodes;
-   int         rnodes;
-
-   if (tree == NULL)
-   {
-       puts("Null tree.");
-       return;
-   }
-   lnodes = checktreer(tree->lt_left, 1, context);
-   rnodes = checktreer(tree->lt_right, 1, context);
-   if (lnodes < 0)
-   {
-       lnodes = -lnodes;
-       puts("0:\tBad left side.");
-   }
-   if (rnodes < 0)
-   {
-       rnodes = -rnodes;
-       puts("0:\tBad right side.");
-   }
-   if (lnodes == 0)
-   {
-       if (rnodes != 0)
-           puts("0:\tLeft and right reversed.");
-       if (tree->lt_dist != 1)
-           puts("0:\tDistance incorrect.");
-   }
-   else if (rnodes == 0)
-   {
-       if (tree->lt_dist != 1)
-           puts("0:\tDistance incorrect.");
-   }
-   else if (tree->lt_left->lt_dist < tree->lt_right->lt_dist)
-   {
-       puts("0:\tLeft and right reversed.");
-       if (tree->lt_dist != 1 + tree->lt_left->lt_dist)
-           puts("0:\tDistance incorrect.");
-   }
-   else if (tree->lt_dist != 1 + tree->lt_right->lt_dist)
-       puts("0:\tDistance incorrect.");
-   if (lnodes > 0)
-       if (tuplecmp(tree->lt_left->lt_tuple, tree->lt_tuple, context))
-           printf("%d:\tLeft child < parent.\n");
-   if (rnodes > 0)
-       if (tuplecmp(tree->lt_right->lt_tuple, tree->lt_tuple, context))
-           printf("%d:\tRight child < parent.\n");
-   printf("Tree has %d nodes\n", 1 + lnodes + rnodes);
-}
-
-int
-checktreer(struct leftist * tree, int level, LeftistContext context)
-{
-   int         lnodes,
-               rnodes;
-   int         error = 0;
-
-   if (tree == NULL)
-       return 0;
-   lnodes = checktreer(tree->lt_left, level + 1, context);
-   rnodes = checktreer(tree->lt_right, level + 1, context);
-   if (lnodes < 0)
-   {
-       error = 1;
-       lnodes = -lnodes;
-       printf("%d:\tBad left side.\n", level);
-   }
-   if (rnodes < 0)
-   {
-       error = 1;
-       rnodes = -rnodes;
-       printf("%d:\tBad right side.\n", level);
-   }
-   if (lnodes == 0)
-   {
-       if (rnodes != 0)
-       {
-           error = 1;
-           printf("%d:\tLeft and right reversed.\n", level);
-       }
-       if (tree->lt_dist != 1)
-       {
-           error = 1;
-           printf("%d:\tDistance incorrect.\n", level);
-       }
-   }
-   else if (rnodes == 0)
-   {
-       if (tree->lt_dist != 1)
-       {
-           error = 1;
-           printf("%d:\tDistance incorrect.\n", level);
-       }
-   }
-   else if (tree->lt_left->lt_dist < tree->lt_right->lt_dist)
-   {
-       error = 1;
-       printf("%d:\tLeft and right reversed.\n", level);
-       if (tree->lt_dist != 1 + tree->lt_left->lt_dist)
-           printf("%d:\tDistance incorrect.\n", level);
-   }
-   else if (tree->lt_dist != 1 + tree->lt_right->lt_dist)
-   {
-       error = 1;
-       printf("%d:\tDistance incorrect.\n", level);
-   }
-   if (lnodes > 0)
-       if (tuplecmp(tree->lt_left->lt_tuple, tree->lt_tuple, context))
-       {
-           error = 1;
-           printf("%d:\tLeft child < parent.\n");
-       }
-   if (rnodes > 0)
-       if (tuplecmp(tree->lt_right->lt_tuple, tree->lt_tuple, context))
-       {
-           error = 1;
-           printf("%d:\tRight child < parent.\n");
-       }
-   if (error)
-       return -1 + -lnodes + -rnodes;
-   return 1 + lnodes + rnodes;
-}
-
-#endif
diff --git a/src/backend/utils/sort/psort.c b/src/backend/utils/sort/psort.c
deleted file mode 100644 (file)
index 67cdfc2..0000000
+++ /dev/null
@@ -1,1025 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * psort.c
- *   Polyphase merge sort.
- *
- * See Knuth, volume 3, for more than you want to know about this algorithm.
- *
- * NOTES
- *
- * This needs to be generalized to handle index tuples as well as heap tuples,
- * so that the near-duplicate code in nbtsort.c can be eliminated.  Also,
- * I think it's got memory leak problems.
- *
- * Copyright (c) 1994, Regents of the University of California
- *
- * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/sort/Attic/psort.c,v 1.58 1999/10/16 19:49:27 tgl Exp $
- *
- *-------------------------------------------------------------------------
- */
-
-#include 
-
-#include "postgres.h"
-
-#include "access/heapam.h"
-#include "access/relscan.h"
-#include "executor/execdebug.h"
-#include "executor/executor.h"
-#include "miscadmin.h"
-#include "utils/logtape.h"
-#include "utils/lselect.h"
-#include "utils/psort.h"
-
-#define MAXTAPES       7       /* See Knuth Fig. 70, p273 */
-
-struct tape
-{
-   int         tp_dummy;       /* (D) */
-   int         tp_fib;         /* (A) */
-   int         tp_tapenum;     /* (TAPE) */
-   struct tape *tp_prev;
-};
-
-/*
- * Private state of a Psort operation.  The "psortstate" field in a Sort node
- * points to one of these.  This replaces a lot of global variables that used
- * to be here...
- */
-typedef struct Psortstate
-{
-   LeftistContextData treeContext;
-
-   int         TapeRange;      /* number of tapes less 1 (T) */
-   int         Level;          /* Knuth's l */
-   int         TotalDummy;     /* sum of tp_dummy across all tapes */
-   struct tape Tape[MAXTAPES];
-
-   LogicalTapeSet *tapeset;    /* logtape.c object for tapes in a temp file */
-
-   int         BytesRead;      /* I/O statistics (useless) */
-   int         BytesWritten;
-   int         tupcount;
-
-   struct leftist *Tuples;     /* current tuple tree */
-
-   int         psort_grab_tape; /* tape number of finished output data */
-   long        psort_current;  /* array index (only used if not tape) */
-   /* psort_saved(_offset) holds marked position for mark and restore */
-   long        psort_saved;    /* could be tape block#, or array index */
-   int         psort_saved_offset; /* lower bits of psort_saved, if tape */
-   bool        using_tape_files;
-   bool        all_fetched;    /* this is for cursors */
-
-   HeapTuple  *memtuples;
-} Psortstate;
-
-/*
- * PS - Macro to access and cast psortstate from a Sort node
- */
-#define PS(N) ((Psortstate *)(N)->psortstate)
-
-static bool createfirstrun(Sort *node);
-static bool createrun(Sort *node, int desttapenum);
-static void dumptuples(Sort *node, int desttapenum);
-static void initialrun(Sort *node);
-static void inittapes(Sort *node);
-static void merge(Sort *node, struct tape * dest);
-static int mergeruns(Sort *node);
-static int _psort_cmp(HeapTuple *ltup, HeapTuple *rtup);
-
-/* these are used by _psort_cmp, and are set just before calling qsort() */
-static TupleDesc PsortTupDesc;
-static ScanKey PsortKeys;
-static int PsortNkeys;
-
-/*
- * tlenzero is used to write a zero to delimit runs, tlendummy is used
- * to read in length words that we don't care about.
- *
- * both vars must have the same size as HeapTuple->t_len
- */
-static unsigned int tlenzero = 0;
-static unsigned int tlendummy;
-
-
-/*
- *     psort_begin
- *
- * polyphase merge sort entry point. Sorts the subplan
- * into memory or a temporary file. After
- * this is called, calling the interface function
- * psort_grabtuple iteratively will get you the sorted
- * tuples. psort_end releases storage when done.
- *
- * Allocates and initializes sort node's psort state.
- */
-bool
-psort_begin(Sort *node, int nkeys, ScanKey key)
-{
-   AssertArg(nkeys >= 1);
-   AssertArg(key[0].sk_attno != 0);
-   AssertArg(key[0].sk_procedure != 0);
-
-   node->psortstate = (void *) palloc(sizeof(struct Psortstate));
-
-   PS(node)->treeContext.tupDesc = ExecGetTupType(outerPlan((Plan *) node));
-   PS(node)->treeContext.nKeys = nkeys;
-   PS(node)->treeContext.scanKeys = key;
-   PS(node)->treeContext.sortMem = SortMem * 1024;
-
-   PS(node)->tapeset = NULL;
-
-   PS(node)->BytesRead = 0;
-   PS(node)->BytesWritten = 0;
-   PS(node)->tupcount = 0;
-
-   PS(node)->Tuples = NULL;
-
-   PS(node)->using_tape_files = false;
-   PS(node)->all_fetched = false;
-   PS(node)->psort_grab_tape = -1;
-
-   PS(node)->memtuples = NULL;
-
-   initialrun(node);
-
-   if (PS(node)->tupcount == 0)
-       return false;
-
-   if (PS(node)->using_tape_files && PS(node)->psort_grab_tape == -1)
-       PS(node)->psort_grab_tape = mergeruns(node);
-
-   PS(node)->psort_current = 0L;
-   PS(node)->psort_saved = 0L;
-   PS(node)->psort_saved_offset = 0;
-
-   return true;
-}
-
-/*
- *     inittapes       - initializes the tapes
- *                     - (polyphase merge Alg.D(D1)--Knuth, Vol.3, p.270)
- *
- * This is called only if we have found we don't have room to sort in memory.
- */
-static void
-inittapes(Sort *node)
-{
-   int         i;
-   struct tape *tp;
-
-   Assert(node != (Sort *) NULL);
-   Assert(PS(node) != (Psortstate *) NULL);
-
-   PS(node)->tapeset = LogicalTapeSetCreate(MAXTAPES);
-
-   tp = PS(node)->Tape;
-   for (i = 0; i < MAXTAPES; i++)
-   {
-       tp->tp_dummy = 1;
-       tp->tp_fib = 1;
-       tp->tp_tapenum = i;
-       tp->tp_prev = tp - 1;
-       tp++;
-   }
-   PS(node)->TapeRange = --tp - PS(node)->Tape;
-   tp->tp_dummy = 0;
-   tp->tp_fib = 0;
-   PS(node)->Tape[0].tp_prev = tp;
-
-   PS(node)->Level = 1;
-   PS(node)->TotalDummy = PS(node)->TapeRange;
-
-   PS(node)->using_tape_files = true;
-}
-
-/*
- *     PUTTUP          - writes the next tuple
- *     ENDRUN          - mark end of run
- *     TRYGETLEN       - reads the length of the next tuple, if any
- *     GETLEN          - reads the length of the next tuple, must be one
- *     ALLOCTUP        - returns space for the new tuple
- *     GETTUP          - reads the tuple
- *
- *     Note:
- *             LEN field must be as HeapTuple->t_len; FP is a stream
- */
-
-
-#define PUTTUP(NODE, TUP, TAPE) \
-( \
-   (TUP)->t_len += HEAPTUPLESIZE, \
-   PS(NODE)->BytesWritten += (TUP)->t_len, \
-   LogicalTapeWrite(PS(NODE)->tapeset, (TAPE), (void*)(TUP), (TUP)->t_len), \
-   LogicalTapeWrite(PS(NODE)->tapeset, (TAPE), (void*)&((TUP)->t_len), sizeof(tlendummy)), \
-   (TUP)->t_len -= HEAPTUPLESIZE \
-)
-
-#define ENDRUN(NODE, TAPE) \
-   LogicalTapeWrite(PS(NODE)->tapeset, (TAPE), (void *)&tlenzero, sizeof(tlenzero))
-
-#define TRYGETLEN(NODE, LEN, TAPE) \
-   (LogicalTapeRead(PS(NODE)->tapeset, (TAPE), \
-                    (void *) &(LEN), sizeof(tlenzero)) == sizeof(tlenzero) \
-    && (LEN) != 0)
-
-#define GETLEN(NODE, LEN, TAPE) \
-   do { \
-       if (! TRYGETLEN(NODE, LEN, TAPE)) \
-           elog(ERROR, "psort: unexpected end of data"); \
-   } while(0)
-
-static void GETTUP(Sort *node, HeapTuple tup, unsigned int len, int tape)
-{
-   IncrProcessed();
-   PS(node)->BytesRead += len;
-   if (LogicalTapeRead(PS(node)->tapeset, tape,
-                       ((char *) tup) + sizeof(tlenzero),
-                       len - sizeof(tlenzero)) != len - sizeof(tlenzero))
-       elog(ERROR, "psort: unexpected end of data");
-   tup->t_len = len - HEAPTUPLESIZE;
-   tup->t_data = (HeapTupleHeader) ((char *) tup + HEAPTUPLESIZE);
-   if (LogicalTapeRead(PS(node)->tapeset, tape,
-                       (void *) &tlendummy,
-                       sizeof(tlendummy)) != sizeof(tlendummy))
-       elog(ERROR, "psort: unexpected end of data");
-}
-
-#define ALLOCTUP(LEN)  ((HeapTuple) palloc(LEN))
-#define FREE(x)            pfree((char *) (x))
-
- /*
-  * USEMEM         - record use of memory FREEMEM         - record
-  * freeing of memory FULLMEM        - 1 iff a tuple will fit
-  */
-
-#define USEMEM(NODE,AMT)       PS(node)->treeContext.sortMem -= (AMT)
-#define FREEMEM(NODE,AMT)      PS(node)->treeContext.sortMem += (AMT)
-#define LACKMEM(NODE)          (PS(node)->treeContext.sortMem <= BLCKSZ)       /* not accurate */
-#define TRACEMEM(FUNC)
-#define TRACEOUT(FUNC, TUP)
-
-/*
- *     initialrun      - distributes tuples from the relation
- *                     - (replacement selection(R2-R3)--Knuth, Vol.3, p.257)
- *                     - (polyphase merge Alg.D(D2-D4)--Knuth, Vol.3, p.271)
- *
- *     Explanation:
- *             Tuples are distributed to the tapes as in Algorithm D.
- *             A "tuple" with t_size == 0 is used to mark the end of a run.
- *
- *     Note:
- *             The replacement selection algorithm has been modified
- *             to go from R1 directly to R3 skipping R2 the first time.
- *
- *             Maybe should use closer(rdesc) before return
- *             Perhaps should adjust the number of tapes if less than n.
- *             used--v. likely to have problems in mergeruns().
- *             Must know if should open/close files before each
- *             call to  psort()?   If should--messy??
- *
- *     Possible optimization:
- *             put the first xxx runs in quickly--problem here since
- *             I (perhaps prematurely) combined the 2 algorithms.
- *             Also, perhaps allocate tapes when needed. Split into 2 funcs.
- */
-static void
-initialrun(Sort *node)
-{
-   struct tape *tp;
-   int         baseruns;       /* D:(a) */
-   int         extrapasses;    /* EOF */
-   int         tapenum;
-
-   Assert(node != (Sort *) NULL);
-   Assert(PS(node) != (Psortstate *) NULL);
-
-   tp = PS(node)->Tape;
-
-   if (createfirstrun(node))
-   {
-       Assert(PS(node)->using_tape_files);
-       extrapasses = 0;
-   }
-   else
-   {
-       /* all tuples fetched */
-       if (!PS(node)->using_tape_files)        /* empty or sorted in
-                                                * memory */
-           return;
-
-       /*
-        * if PS(node)->Tuples == NULL then we have single (sorted) run
-        * which can be used as result grab file! So, we may avoid
-        * mergeruns - it will just copy this run to new file.
-        */
-       if (PS(node)->Tuples == NULL)
-       {
-           PS(node)->psort_grab_tape = PS(node)->Tape[0].tp_tapenum;
-           /* freeze and rewind the finished output tape */
-           LogicalTapeFreeze(PS(node)->tapeset, PS(node)->psort_grab_tape);
-           return;
-       }
-       extrapasses = 2;
-   }
-
-   for (;;)
-   {
-       tp->tp_dummy--;
-       PS(node)->TotalDummy--;
-       if (tp->tp_dummy < (tp + 1)->tp_dummy)
-           tp++;
-       else
-       {
-           if (tp->tp_dummy != 0)
-               tp = PS(node)->Tape;
-           else
-           {
-               PS(node)->Level++;
-               baseruns = PS(node)->Tape[0].tp_fib;
-               for (tp = PS(node)->Tape;
-                    tp - PS(node)->Tape < PS(node)->TapeRange; tp++)
-               {
-                   PS(node)->TotalDummy += (tp->tp_dummy = baseruns
-                                            + (tp + 1)->tp_fib
-                                            - tp->tp_fib);
-                   tp->tp_fib = baseruns
-                       + (tp + 1)->tp_fib;
-               }
-               tp = PS(node)->Tape;    /* D4 */
-           }                   /* D3 */
-       }
-       if (extrapasses)
-       {
-           if (--extrapasses)
-           {
-               dumptuples(node, tp->tp_tapenum);
-               ENDRUN(node, tp->tp_tapenum);
-               continue;
-           }
-           else
-               break;
-       }
-       if (createrun(node, tp->tp_tapenum) == false)
-           extrapasses = 1 + (PS(node)->Tuples != NULL);
-       /* D2 */
-   }
-   /* End of step D2: rewind all output tapes to prepare for merging */
-   for (tapenum = 0; tapenum < PS(node)->TapeRange; tapenum++)
-       LogicalTapeRewind(PS(node)->tapeset, tapenum, false);
-}
-
-/*
- *     createfirstrun      - tries to sort tuples in memory using qsort
- *                     until LACKMEM; if not enough memory then switches
- *                     to tape method
- *
- *     Returns:
- *             FALSE iff process through end of relation
- *             Tuples contains the tuples for the following run upon exit
- */
-static bool
-createfirstrun(Sort *node)
-{
-   HeapTuple   tup;
-   bool        foundeor = false;
-   HeapTuple  *memtuples;
-   int         t_last = -1;
-   int         t_free = 1000;
-   TupleTableSlot *cr_slot;
-
-   Assert(node != (Sort *) NULL);
-   Assert(PS(node) != (Psortstate *) NULL);
-   Assert(!PS(node)->using_tape_files);
-   Assert(PS(node)->memtuples == NULL);
-   Assert(PS(node)->tupcount == 0);
-   if (LACKMEM(node))
-       elog(ERROR, "psort: LACKMEM before createfirstrun");
-
-   memtuples = palloc(t_free * sizeof(HeapTuple));
-
-   for (;;)
-   {
-       if (LACKMEM(node))
-           break;
-
-       /*
-        * 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;
-           break;
-       }
-
-       tup = heap_copytuple(cr_slot->val);
-       ExecClearTuple(cr_slot);
-
-       IncrProcessed();
-       USEMEM(node, tup->t_len);
-       TRACEMEM(createfirstrun);
-       if (t_free <= 0)
-       {
-           t_free = 1000;
-           memtuples = repalloc(memtuples,
-                             (t_last + t_free + 1) * sizeof(HeapTuple));
-       }
-       t_last++;
-       t_free--;
-       memtuples[t_last] = tup;
-   }
-
-   if (t_last < 0)             /* empty */
-   {
-       Assert(foundeor);
-       pfree(memtuples);
-       return false;
-   }
-   t_last++;
-   PS(node)->tupcount = t_last;
-   PsortTupDesc = PS(node)->treeContext.tupDesc;
-   PsortKeys = PS(node)->treeContext.scanKeys;
-   PsortNkeys = PS(node)->treeContext.nKeys;
-   qsort(memtuples, t_last, sizeof(HeapTuple),
-         (int (*) (const void *, const void *)) _psort_cmp);
-
-   if (LACKMEM(node))          /* in-memory sort is impossible */
-   {
-       int         t;
-
-       Assert(!foundeor);
-       inittapes(node);
-       /* put tuples into leftist tree for createrun */
-       for (t = t_last - 1; t >= 0; t--)
-           puttuple(&PS(node)->Tuples, memtuples[t], 0, &PS(node)->treeContext);
-       pfree(memtuples);
-       foundeor = ! createrun(node, PS(node)->Tape->tp_tapenum);
-   }
-   else
-   {
-       Assert(foundeor);
-       PS(node)->memtuples = memtuples;
-   }
-
-   return !foundeor;
-}
-
-/*
- *     createrun
- *
- * Create the next run and write it to desttapenum, grabbing the tuples by
- * executing the subplan passed in
- *
- *     Uses:
- *             Tuples, which should contain any tuples for this run
- *
- *     Returns:
- *             FALSE iff process through end of relation
- *             Tuples contains the tuples for the following run upon exit
- */
-static bool
-createrun(Sort *node, int desttapenum)
-{
-   HeapTuple   lasttuple;
-   HeapTuple   tup;
-   TupleTableSlot *cr_slot;
-   HeapTuple  *memtuples;
-   int         t_last = -1;
-   int         t_free = 1000;
-   bool        foundeor = false;
-   short       junk;
-
-   Assert(node != (Sort *) NULL);
-   Assert(PS(node) != (Psortstate *) NULL);
-   Assert(PS(node)->using_tape_files);
-
-   lasttuple = NULL;
-   memtuples = palloc(t_free * sizeof(HeapTuple));
-
-   for (;;)
-   {
-       while (LACKMEM(node) && PS(node)->Tuples != NULL)
-       {
-           if (lasttuple != NULL)
-           {
-               FREEMEM(node, lasttuple->t_len);
-               FREE(lasttuple);
-               TRACEMEM(createrun);
-           }
-           lasttuple = gettuple(&PS(node)->Tuples, &junk,
-                                &PS(node)->treeContext);
-           PUTTUP(node, lasttuple, desttapenum);
-           TRACEOUT(createrun, lasttuple);
-       }
-
-       if (LACKMEM(node))
-           break;
-
-       /*
-        * 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;
-           break;
-       }
-       else
-       {
-           tup = heap_copytuple(cr_slot->val);
-           ExecClearTuple(cr_slot);
-           PS(node)->tupcount++;
-       }
-
-       IncrProcessed();
-       USEMEM(node, tup->t_len);
-       TRACEMEM(createrun);
-       if (lasttuple != NULL && tuplecmp(tup, lasttuple,
-                                         &PS(node)->treeContext))
-       {
-           if (t_free <= 0)
-           {
-               t_free = 1000;
-               memtuples = repalloc(memtuples,
-                             (t_last + t_free + 1) * sizeof(HeapTuple));
-           }
-           t_last++;
-           t_free--;
-           memtuples[t_last] = tup;
-       }
-       else
-           puttuple(&PS(node)->Tuples, tup, 0, &PS(node)->treeContext);
-   }
-   if (lasttuple != NULL)
-   {
-       FREEMEM(node, lasttuple->t_len);
-       FREE(lasttuple);
-       TRACEMEM(createrun);
-   }
-   dumptuples(node, desttapenum);
-   ENDRUN(node, desttapenum);      /* delimit the end of the run */
-
-   t_last++;
-   /* put tuples for the next run into leftist tree */
-   if (t_last >= 1)
-   {
-       int         t;
-
-       PsortTupDesc = PS(node)->treeContext.tupDesc;
-       PsortKeys = PS(node)->treeContext.scanKeys;
-       PsortNkeys = PS(node)->treeContext.nKeys;
-       qsort(memtuples, t_last, sizeof(HeapTuple),
-             (int (*) (const void *, const void *)) _psort_cmp);
-       for (t = t_last - 1; t >= 0; t--)
-           puttuple(&PS(node)->Tuples, memtuples[t], 0, &PS(node)->treeContext);
-   }
-
-   pfree(memtuples);
-
-   return !foundeor;
-}
-
-/*
- *     mergeruns       - merges all runs from input tapes
- *                       (polyphase merge Alg.D(D6)--Knuth, Vol.3, p271)
- *
- *     Returns:
- *             tape number of finished tape containing all tuples in order
- */
-static int
-mergeruns(Sort *node)
-{
-   struct tape *tp;
-
-   Assert(node != (Sort *) NULL);
-   Assert(PS(node) != (Psortstate *) NULL);
-   Assert(PS(node)->using_tape_files);
-
-   tp = PS(node)->Tape + PS(node)->TapeRange;
-   merge(node, tp);
-   while (--PS(node)->Level != 0)
-   {
-       /* rewind output tape to use as new input */
-       LogicalTapeRewind(PS(node)->tapeset, tp->tp_tapenum, false);
-       tp = tp->tp_prev;
-       /* rewind new output tape and prepare it for write pass */
-       LogicalTapeRewind(PS(node)->tapeset, tp->tp_tapenum, true);
-       merge(node, tp);
-   }
-   /* freeze and rewind the final output tape */
-   LogicalTapeFreeze(PS(node)->tapeset, tp->tp_tapenum);
-   return tp->tp_tapenum;
-}
-
-/*
- *     merge           - handles a single merge of the tape
- *                       (polyphase merge Alg.D(D5)--Knuth, Vol.3, p271)
- */
-static void
-merge(Sort *node, struct tape * dest)
-{
-   HeapTuple   tup;
-   struct tape *lasttp;        /* (TAPE[P]) */
-   struct tape *tp;
-   struct leftist *tuples;
-   int         desttapenum;
-   int         times;          /* runs left to merge */
-   int         outdummy;       /* complete dummy runs */
-   short       fromtape;
-   unsigned int tuplen;
-
-   Assert(node != (Sort *) NULL);
-   Assert(PS(node) != (Psortstate *) NULL);
-   Assert(PS(node)->using_tape_files);
-
-   lasttp = dest->tp_prev;
-   times = lasttp->tp_fib;
-   for (tp = lasttp; tp != dest; tp = tp->tp_prev)
-       tp->tp_fib -= times;
-   tp->tp_fib += times;
-   /* Tape[].tp_fib (A[]) is set to proper exit values */
-
-   if (PS(node)->TotalDummy < PS(node)->TapeRange)     /* no complete dummy
-                                                        * runs */
-       outdummy = 0;
-   else
-   {
-       outdummy = PS(node)->TotalDummy;        /* a large positive number */
-       for (tp = lasttp; tp != dest; tp = tp->tp_prev)
-           if (outdummy > tp->tp_dummy)
-               outdummy = tp->tp_dummy;
-       for (tp = lasttp; tp != dest; tp = tp->tp_prev)
-           tp->tp_dummy -= outdummy;
-       tp->tp_dummy += outdummy;
-       PS(node)->TotalDummy -= outdummy * PS(node)->TapeRange;
-       /* do not add the outdummy runs yet */
-       times -= outdummy;
-   }
-   desttapenum = dest->tp_tapenum;
-   while (times-- != 0)
-   {                           /* merge one run */
-       tuples = NULL;
-       if (PS(node)->TotalDummy == 0)
-           for (tp = dest->tp_prev; tp != dest; tp = tp->tp_prev)
-           {
-               GETLEN(node, tuplen, tp->tp_tapenum);
-               tup = ALLOCTUP(tuplen);
-               USEMEM(node, tuplen);
-               TRACEMEM(merge);
-               GETTUP(node, tup, tuplen, tp->tp_tapenum);
-               puttuple(&tuples, tup, tp - PS(node)->Tape,
-                        &PS(node)->treeContext);
-           }
-       else
-       {
-           for (tp = dest->tp_prev; tp != dest; tp = tp->tp_prev)
-           {
-               if (tp->tp_dummy != 0)
-               {
-                   tp->tp_dummy--;
-                   PS(node)->TotalDummy--;
-               }
-               else
-               {
-                   GETLEN(node, tuplen, tp->tp_tapenum);
-                   tup = ALLOCTUP(tuplen);
-                   USEMEM(node, tuplen);
-                   TRACEMEM(merge);
-                   GETTUP(node, tup, tuplen, tp->tp_tapenum);
-                   puttuple(&tuples, tup, tp - PS(node)->Tape,
-                            &PS(node)->treeContext);
-               }
-           }
-       }
-       while (tuples != NULL)
-       {
-           /* possible optimization by using count in tuples */
-           tup = gettuple(&tuples, &fromtape, &PS(node)->treeContext);
-           PUTTUP(node, tup, desttapenum);
-           FREEMEM(node, tup->t_len);
-           FREE(tup);
-           TRACEMEM(merge);
-           if (TRYGETLEN(node, tuplen, PS(node)->Tape[fromtape].tp_tapenum))
-           {
-               tup = ALLOCTUP(tuplen);
-               USEMEM(node, tuplen);
-               TRACEMEM(merge);
-               GETTUP(node, tup, tuplen, PS(node)->Tape[fromtape].tp_tapenum);
-               puttuple(&tuples, tup, fromtape, &PS(node)->treeContext);
-           }
-       }
-       ENDRUN(node, desttapenum);
-   }
-   PS(node)->TotalDummy += outdummy;
-}
-
-/*
- * dumptuples  - stores all the tuples remaining in tree to dest tape
- */
-static void
-dumptuples(Sort *node, int desttapenum)
-{
-   LeftistContext context = &PS(node)->treeContext;
-   struct leftist **treep = &PS(node)->Tuples;
-   struct leftist *tp;
-   struct leftist *newp;
-   HeapTuple   tup;
-
-   Assert(PS(node)->using_tape_files);
-
-   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);
-       pfree(tp);
-       PUTTUP(node, tup, desttapenum);
-       FREEMEM(node, tup->t_len);
-       FREE(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, bool *should_free)
-{
-   HeapTuple   tup;
-
-   Assert(node != (Sort *) NULL);
-   Assert(PS(node) != (Psortstate *) NULL);
-
-   if (PS(node)->using_tape_files == true)
-   {
-       unsigned int tuplen;
-
-       *should_free = true;
-       if (ScanDirectionIsForward(node->plan.state->es_direction))
-       {
-           if (PS(node)->all_fetched)
-               return NULL;
-           if (TRYGETLEN(node, tuplen, PS(node)->psort_grab_tape))
-           {
-               tup = ALLOCTUP(tuplen);
-               GETTUP(node, tup, tuplen, PS(node)->psort_grab_tape);
-               return tup;
-           }
-           else
-           {
-               PS(node)->all_fetched = true;
-               return NULL;
-           }
-       }
-       /* Backward.
-        *
-        * if all tuples are fetched already then we return last tuple,
-        * else - tuple before last returned.
-        */
-       if (PS(node)->all_fetched)
-       {
-           /*
-            * Assume seek position is pointing just past the zero tuplen
-            * at the end of file; back up and fetch last tuple's ending
-            * length word.  If seek fails we must have a completely empty
-            * file.
-            */
-           if (! LogicalTapeBackspace(PS(node)->tapeset,
-                                      PS(node)->psort_grab_tape,
-                                      2 * sizeof(tlendummy)))
-               return NULL;
-           GETLEN(node, tuplen, PS(node)->psort_grab_tape);
-           PS(node)->all_fetched = false;
-       }
-       else
-       {
-           /*
-            * Back up and fetch prev tuple's ending length word.
-            * If seek fails, assume we are at start of file.
-            */
-           if (! LogicalTapeBackspace(PS(node)->tapeset,
-                                      PS(node)->psort_grab_tape,
-                                      sizeof(tlendummy)))
-               return NULL;
-           GETLEN(node, tuplen, PS(node)->psort_grab_tape);
-           /*
-            * Back up to get ending length word of tuple before it.
-            */
-           if (! LogicalTapeBackspace(PS(node)->tapeset,
-                                      PS(node)->psort_grab_tape,
-                                      tuplen + 2*sizeof(tlendummy)))
-           {
-               /* If fail, presumably the prev tuple is the first in the file.
-                * Back up so that it becomes next to read in forward direction
-                * (not obviously right, but that is what in-memory case does)
-                */
-               if (! LogicalTapeBackspace(PS(node)->tapeset,
-                                          PS(node)->psort_grab_tape,
-                                          tuplen + sizeof(tlendummy)))
-                   elog(ERROR, "psort_grabtuple: too big last tuple len in backward scan");
-               return NULL;
-           }
-           GETLEN(node, tuplen, PS(node)->psort_grab_tape);
-       }
-
-       /*
-        * Now we have the length of the prior tuple, back up and read it.
-        * Note: GETTUP expects we are positioned after the initial length
-        * word of the tuple, so back up to that point.
-        */
-       if (! LogicalTapeBackspace(PS(node)->tapeset,
-                                  PS(node)->psort_grab_tape,
-                                  tuplen))
-           elog(ERROR, "psort_grabtuple: too big tuple len in backward scan");
-       tup = ALLOCTUP(tuplen);
-       GETTUP(node, tup, tuplen, PS(node)->psort_grab_tape);
-       return tup;
-   }
-   else
-   {
-       *should_free = false;
-       if (ScanDirectionIsForward(node->plan.state->es_direction))
-       {
-           if (PS(node)->psort_current < PS(node)->tupcount)
-               return PS(node)->memtuples[PS(node)->psort_current++];
-           else
-           {
-               PS(node)->all_fetched = true;
-               return NULL;
-           }
-       }
-       /* Backward */
-       if (PS(node)->psort_current <= 0)
-           return NULL;
-
-       /*
-        * if all tuples are fetched already then we return last tuple,
-        * else - tuple before last returned.
-        */
-       if (PS(node)->all_fetched)
-           PS(node)->all_fetched = false;
-       else
-       {
-           PS(node)->psort_current--;  /* last returned tuple */
-           if (PS(node)->psort_current <= 0)
-               return NULL;
-       }
-       return PS(node)->memtuples[PS(node)->psort_current - 1];
-   }
-}
-
-/*
- *     psort_markpos   - saves current position in the merged sort file
- *
- * XXX I suspect these need to save & restore the all_fetched flag as well!
- */
-void
-psort_markpos(Sort *node)
-{
-   Assert(node != (Sort *) NULL);
-   Assert(PS(node) != (Psortstate *) NULL);
-
-   if (PS(node)->using_tape_files == true)
-       LogicalTapeTell(PS(node)->tapeset,
-                       PS(node)->psort_grab_tape,
-                       & PS(node)->psort_saved,
-                       & PS(node)->psort_saved_offset);
-   else
-       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)
-   {
-       if (! LogicalTapeSeek(PS(node)->tapeset,
-                             PS(node)->psort_grab_tape,
-                             PS(node)->psort_saved,
-                             PS(node)->psort_saved_offset))
-           elog(ERROR, "psort_restorepos failed");
-   }
-   else
-       PS(node)->psort_current = PS(node)->psort_saved;
-}
-
-/*
- * psort_end
- *
- * Release resources and clean up.
- */
-void
-psort_end(Sort *node)
-{
-   /* node->cleaned is probably redundant? */
-   if (!node->cleaned && PS(node) != (Psortstate *) NULL)
-   {
-       if (PS(node)->tapeset)
-           LogicalTapeSetClose(PS(node)->tapeset);
-       if (PS(node)->memtuples)
-           pfree(PS(node)->memtuples);
-
-       /* XXX what about freeing leftist tree and tuples in memory? */
-
-       NDirectFileRead += (int) ceil((double) PS(node)->BytesRead / BLCKSZ);
-       NDirectFileWrite += (int) ceil((double) PS(node)->BytesWritten / BLCKSZ);
-
-       pfree((void *) node->psortstate);
-       node->psortstate = NULL;
-       node->cleaned = TRUE;
-   }
-}
-
-void
-psort_rescan(Sort *node)
-{
-
-   /*
-    * If subnode is to be rescanned then free our previous results
-    */
-   if (((Plan *) node)->lefttree->chgParam != NULL)
-   {
-       psort_end(node);
-       node->cleaned = false;  /* huh? */
-   }
-   else if (PS(node) != (Psortstate *) NULL)
-   {
-       PS(node)->all_fetched = false;
-       PS(node)->psort_current = 0;
-       PS(node)->psort_saved = 0L;
-       PS(node)->psort_saved_offset = 0;
-       if (PS(node)->using_tape_files == true)
-           LogicalTapeRewind(PS(node)->tapeset,
-                             PS(node)->psort_grab_tape,
-                             false);
-   }
-
-}
-
-static int
-_psort_cmp(HeapTuple *ltup, HeapTuple *rtup)
-{
-   Datum       lattr,
-               rattr;
-   int         nkey;
-   int         result = 0;
-   bool        isnull1,
-               isnull2;
-
-   for (nkey = 0; nkey < PsortNkeys && !result; nkey++)
-   {
-       lattr = heap_getattr(*ltup,
-                            PsortKeys[nkey].sk_attno,
-                            PsortTupDesc,
-                            &isnull1);
-       rattr = heap_getattr(*rtup,
-                            PsortKeys[nkey].sk_attno,
-                            PsortTupDesc,
-                            &isnull2);
-       if (isnull1)
-       {
-           if (!isnull2)
-               result = 1;
-       }
-       else if (isnull2)
-           result = -1;
-
-       else if (PsortKeys[nkey].sk_flags & SK_COMMUTE)
-       {
-           if (!(result = -(long) (*fmgr_faddr(&PsortKeys[nkey].sk_func)) (rattr, lattr)))
-               result = (long) (*fmgr_faddr(&PsortKeys[nkey].sk_func)) (lattr, rattr);
-       }
-       else if (!(result = -(long) (*fmgr_faddr(&PsortKeys[nkey].sk_func)) (lattr, rattr)))
-           result = (long) (*fmgr_faddr(&PsortKeys[nkey].sk_func)) (rattr, lattr);
-   }
-   return result;
-}
diff --git a/src/include/lib/qsort.h b/src/include/lib/qsort.h
deleted file mode 100644 (file)
index d7bd348..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * qsort.h
- *
- *
- *
- * Copyright (c) 1994, Regents of the University of California
- *
- * $Id: qsort.h,v 1.7 1999/02/13 23:21:32 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-#ifndef QSORT_H
-#define QSORT_H
-
-
-extern void pg_qsort(void *bot,
-        size_t nmemb,
-        size_t size,
-        int (*compar) (void *, void *));
-
-#endif  /* QSORT_H */
diff --git a/src/include/utils/lselect.h b/src/include/utils/lselect.h
deleted file mode 100644 (file)
index 4598c2a..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * lselect.h
- *   definitions for the replacement selection algorithm.
- *
- *
- * Copyright (c) 1994, Regents of the University of California
- *
- * $Id: lselect.h,v 1.14 1999/07/17 20:18:36 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-#ifndef LSELECT_H
-#define LSELECT_H
-
-#include "utils/syscache.h"
-
-struct leftist
-{
-   short       lt_dist;        /* distance to leaf/empty node */
-   short       lt_devnum;      /* device number of tuple */
-   HeapTuple   lt_tuple;
-   struct leftist *lt_left;
-   struct leftist *lt_right;
-};
-
-/* 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,
-      LeftistContext context);
-extern HeapTuple gettuple(struct leftist ** treep, short *devnum,
-        LeftistContext context);
-extern void puttuple(struct leftist ** treep, HeapTuple newtuple, short devnum,
-        LeftistContext context);
-extern int tuplecmp(HeapTuple ltup, HeapTuple rtup, LeftistContext context);
-
-#ifdef EBUG
-extern void checktree(struct leftist * tree, LeftistContext context);
-extern int checktreer(struct leftist * tree, int level, LeftistContext context);
-
-#endif  /* EBUG */
-
-#endif  /* LSELECT_H */
diff --git a/src/include/utils/psort.h b/src/include/utils/psort.h
deleted file mode 100644 (file)
index 5f7a638..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * psort.h
- *   Polyphase merge sort.
- *
- * Copyright (c) 1994, Regents of the University of California
- *
- * $Id: psort.h,v 1.23 1999/10/16 19:49:28 tgl Exp $
- *
- *-------------------------------------------------------------------------
- */
-#ifndef PSORT_H
-#define PSORT_H
-
-#include "access/htup.h"
-#include "access/skey.h"
-#include "nodes/plannodes.h"
-
-extern bool psort_begin(Sort *node, int nkeys, ScanKey key);
-extern HeapTuple psort_grabtuple(Sort *node, bool *should_free);
-extern void psort_markpos(Sort *node);
-extern void psort_restorepos(Sort *node);
-extern void psort_end(Sort *node);
-extern void psort_rescan(Sort *node);
-
-#endif  /* PSORT_H */