Skip to content
Snippets Groups Projects
Commit 78351f42 authored by Vadim B. Mikheev's avatar Vadim B. Mikheev
Browse files

Fix for backward cursors with ORDER BY.

parent 9acf938c
No related branches found
No related tags found
No related merge requests found
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/sort/Attic/psort.c,v 1.25 1997/09/26 20:05:47 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/sort/Attic/psort.c,v 1.26 1997/10/15 06:36:08 vadim Exp $
* *
* NOTES * NOTES
* Sorts the first relation into the second relation. * Sorts the first relation into the second relation.
...@@ -80,7 +80,12 @@ static int _psort_cmp (HeapTuple *ltup, HeapTuple *rtup); ...@@ -80,7 +80,12 @@ static int _psort_cmp (HeapTuple *ltup, HeapTuple *rtup);
#define TEMPDIR "./" #define TEMPDIR "./"
static long shortzero = 0; /* used to delimit runs */ /*
* tlenzero used to delimit runs; both vars below must have
* the same size as HeapTuple->t_len
*/
static unsigned int tlenzero = 0;
static unsigned int tlendummy;
static TupleDesc PsortTupDesc; static TupleDesc PsortTupDesc;
static ScanKey PsortKeys; /* used by _psort_cmp */ static ScanKey PsortKeys; /* used by _psort_cmp */
...@@ -150,6 +155,7 @@ psort_begin(Sort * node, int nkeys, ScanKey key) ...@@ -150,6 +155,7 @@ psort_begin(Sort * node, int nkeys, ScanKey key)
PS(node)->tupcount = 0; PS(node)->tupcount = 0;
PS(node)->using_tape_files = false; PS(node)->using_tape_files = false;
PS(node)->all_fetched = false;
PS(node)->psort_grab_file = NULL; PS(node)->psort_grab_file = NULL;
PS(node)->memtuples = NULL; PS(node)->memtuples = NULL;
...@@ -219,21 +225,24 @@ inittapes(Sort * node) ...@@ -219,21 +225,24 @@ inittapes(Sort * node)
* GETTUP - reads the tuple * GETTUP - reads the tuple
* *
* Note: * Note:
* LEN field must be a short; FP is a stream * LEN field must be as HeapTuple->t_len; FP is a stream
*/ */
#define PUTTUP(NODE, TUP, FP) do {\ #define PUTTUP(NODE, TUP, FP) do {\
((Psortstate *)NODE->psortstate)->BytesWritten += (TUP)->t_len; \ ((Psortstate *)NODE->psortstate)->BytesWritten += (TUP)->t_len; \
fwrite((char *)TUP, (TUP)->t_len, 1, FP);} while (0) fwrite((char *)TUP, (TUP)->t_len, 1, FP); \
#define ENDRUN(FP) fwrite((char *)&shortzero, sizeof (shortzero), 1, FP) fwrite((char *)&((TUP)->t_len), sizeof (tlendummy), 1, FP); \
#define GETLEN(LEN, FP) fread((char *)&(LEN), sizeof (shortzero), 1, FP) } while (0)
#define ENDRUN(FP) fwrite((char *)&tlenzero, sizeof (tlenzero), 1, FP)
#define GETLEN(LEN, FP) fread((char *)&(LEN), sizeof (tlenzero), 1, FP)
#define ALLOCTUP(LEN) ((HeapTuple)palloc((unsigned)LEN)) #define ALLOCTUP(LEN) ((HeapTuple)palloc((unsigned)LEN))
#define GETTUP(NODE, TUP, LEN, FP) do {\ #define GETTUP(NODE, TUP, LEN, FP) do {\
IncrProcessed(); \ IncrProcessed(); \
((Psortstate *)NODE->psortstate)->BytesRead += (LEN) - sizeof (shortzero); \ ((Psortstate *)NODE->psortstate)->BytesRead += (LEN) - sizeof (tlenzero); \
fread((char *)(TUP) + sizeof (shortzero), (LEN) - sizeof (shortzero), 1, FP);} \ fread((char *)(TUP) + sizeof (tlenzero), (LEN) - sizeof (tlenzero), 1, FP); \
while (0) fread((char *)&tlendummy, sizeof (tlendummy), 1, FP); \
} while (0)
#define SETTUPLEN(TUP, LEN) (TUP)->t_len = LEN #define SETTUPLEN(TUP, LEN) (TUP)->t_len = LEN
/* /*
...@@ -633,7 +642,7 @@ merge(Sort * node, struct tape * dest) ...@@ -633,7 +642,7 @@ merge(Sort * node, struct tape * dest)
int times; /* runs left to merge */ int times; /* runs left to merge */
int outdummy; /* complete dummy runs */ int outdummy; /* complete dummy runs */
short fromtape; short fromtape;
long tuplen; unsigned int tuplen;
Assert(node != (Sort *) NULL); Assert(node != (Sort *) NULL);
Assert(PS(node) != (Psortstate *) NULL); Assert(PS(node) != (Psortstate *) NULL);
...@@ -768,15 +777,19 @@ HeapTuple ...@@ -768,15 +777,19 @@ HeapTuple
psort_grabtuple(Sort * node, bool * should_free) psort_grabtuple(Sort * node, bool * should_free)
{ {
register HeapTuple tup; register HeapTuple tup;
long tuplen;
Assert(node != (Sort *) NULL); Assert(node != (Sort *) NULL);
Assert(PS(node) != (Psortstate *) NULL); Assert(PS(node) != (Psortstate *) NULL);
if (PS(node)->using_tape_files == true) if (PS(node)->using_tape_files == true)
{ {
if (!feof(PS(node)->psort_grab_file)) unsigned int tuplen;
*should_free = true;
if (ScanDirectionIsForward (node->plan.state->es_direction))
{ {
if (PS(node)->all_fetched)
return NULL;
if (GETLEN(tuplen, PS(node)->psort_grab_file) && tuplen != 0) if (GETLEN(tuplen, PS(node)->psort_grab_file) && tuplen != 0)
{ {
tup = (HeapTuple) palloc((unsigned) tuplen); tup = (HeapTuple) palloc((unsigned) tuplen);
...@@ -784,26 +797,100 @@ psort_grabtuple(Sort * node, bool * should_free) ...@@ -784,26 +797,100 @@ psort_grabtuple(Sort * node, bool * should_free)
GETTUP(node, tup, tuplen, PS(node)->psort_grab_file); GETTUP(node, tup, tuplen, PS(node)->psort_grab_file);
/* Update current merged sort file position */ /* Update current merged sort file position */
PS(node)->psort_current += tuplen; PS(node)->psort_current += tuplen + sizeof (tlendummy);
*should_free = true;
return tup; return tup;
} }
else else
{
PS(node)->all_fetched = true;
return NULL; return NULL;
} }
else }
/* Backward */
if (PS(node)->psort_current <= sizeof (tlendummy))
return NULL; return NULL;
/*
* if all tuples are fetched already then we return last tuple,
* else - tuple before last returned.
*/
if (PS(node)->all_fetched)
{
/* psort_current is pointing to the zero tuplen at the end of file */
fseek(PS(node)->psort_grab_file,
PS(node)->psort_current - sizeof (tlendummy), SEEK_SET);
GETLEN(tuplen, PS(node)->psort_grab_file);
if (PS(node)->psort_current < tuplen)
elog (FATAL, "psort_grabtuple: too big last tuple len in backward scan");
PS(node)->all_fetched = false;
} }
else else
{ {
if (PS(node)->psort_current < PS(node)->tupcount) /* move to position of end tlen of prev tuple */
PS(node)->psort_current -= sizeof (tlendummy);
fseek(PS(node)->psort_grab_file, PS(node)->psort_current, SEEK_SET);
GETLEN(tuplen, PS(node)->psort_grab_file); /* get tlen of prev tuple */
if (tuplen == 0)
elog (FATAL, "psort_grabtuple: tuplen is 0 in backward scan");
if (PS(node)->psort_current <= tuplen + sizeof (tlendummy))
{ /* prev tuple should be first one */
if (PS(node)->psort_current != tuplen)
elog (FATAL, "psort_grabtuple: first tuple expected in backward scan");
PS(node)->psort_current = 0;
fseek(PS(node)->psort_grab_file, PS(node)->psort_current, SEEK_SET);
return NULL;
}
/*
* Get position of prev tuple. This tuple becomes current tuple
* now and we have to return previous one.
*/
PS(node)->psort_current -= tuplen;
/* move to position of end tlen of prev tuple */
fseek(PS(node)->psort_grab_file,
PS(node)->psort_current - sizeof (tlendummy), SEEK_SET);
GETLEN(tuplen, PS(node)->psort_grab_file);
if (PS(node)->psort_current < tuplen + sizeof (tlendummy))
elog (FATAL, "psort_grabtuple: too big tuple len in backward scan");
}
/*
* move to prev (or last) tuple start position + sizeof(t_len)
*/
fseek(PS(node)->psort_grab_file,
PS(node)->psort_current - tuplen, SEEK_SET);
tup = (HeapTuple) palloc((unsigned) tuplen);
SETTUPLEN(tup, tuplen);
GETTUP(node, tup, tuplen, PS(node)->psort_grab_file);
return tup; /* file position is equal to psort_current */
}
else
{ {
*should_free = false; *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++]); 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 else
{
PS(node)->psort_current--; /* last returned tuple */
if (PS(node)->psort_current <= 0)
return NULL; return NULL;
} }
return (PS(node)->memtuples[PS(node)->psort_current - 1]);
}
} }
/* /*
......
...@@ -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.13 1997/09/18 14:42:35 vadim Exp $ * $Id: psort.h,v 1.14 1997/10/15 06:36:36 vadim Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -62,6 +62,7 @@ typedef struct Psortstate ...@@ -62,6 +62,7 @@ typedef struct Psortstate
long psort_current; /* could be file offset, or array index */ long psort_current; /* could be file offset, or array index */
long psort_saved; /* could be file offset, or array index */ long psort_saved; /* could be file offset, or array index */
bool using_tape_files; bool using_tape_files;
bool all_fetched; /* this is for cursors */
HeapTuple *memtuples; HeapTuple *memtuples;
} Psortstate; } Psortstate;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment