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

Commit 78351f4

Browse files
committed
Fix for backward cursors with ORDER BY.
1 parent 9acf938 commit 78351f4

File tree

2 files changed

+113
-25
lines changed

2 files changed

+113
-25
lines changed

src/backend/utils/sort/psort.c

+111-24
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/utils/sort/Attic/psort.c,v 1.25 1997/09/26 20:05:47 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/utils/sort/Attic/psort.c,v 1.26 1997/10/15 06:36:08 vadim Exp $
1111
*
1212
* NOTES
1313
* Sorts the first relation into the second relation.
@@ -80,7 +80,12 @@ static int _psort_cmp (HeapTuple *ltup, HeapTuple *rtup);
8080

8181
#define TEMPDIR "./"
8282

83-
static long shortzero = 0; /* used to delimit runs */
83+
/*
84+
* tlenzero used to delimit runs; both vars below must have
85+
* the same size as HeapTuple->t_len
86+
*/
87+
static unsigned int tlenzero = 0;
88+
static unsigned int tlendummy;
8489

8590
static TupleDesc PsortTupDesc;
8691
static ScanKey PsortKeys; /* used by _psort_cmp */
@@ -150,6 +155,7 @@ psort_begin(Sort * node, int nkeys, ScanKey key)
150155
PS(node)->tupcount = 0;
151156

152157
PS(node)->using_tape_files = false;
158+
PS(node)->all_fetched = false;
153159
PS(node)->psort_grab_file = NULL;
154160
PS(node)->memtuples = NULL;
155161

@@ -219,21 +225,24 @@ inittapes(Sort * node)
219225
* GETTUP - reads the tuple
220226
*
221227
* Note:
222-
* LEN field must be a short; FP is a stream
228+
* LEN field must be as HeapTuple->t_len; FP is a stream
223229
*/
224230

225231

226232
#define PUTTUP(NODE, TUP, FP) do {\
227233
((Psortstate *)NODE->psortstate)->BytesWritten += (TUP)->t_len; \
228-
fwrite((char *)TUP, (TUP)->t_len, 1, FP);} while (0)
229-
#define ENDRUN(FP) fwrite((char *)&shortzero, sizeof (shortzero), 1, FP)
230-
#define GETLEN(LEN, FP) fread((char *)&(LEN), sizeof (shortzero), 1, FP)
234+
fwrite((char *)TUP, (TUP)->t_len, 1, FP); \
235+
fwrite((char *)&((TUP)->t_len), sizeof (tlendummy), 1, FP); \
236+
} while (0)
237+
#define ENDRUN(FP) fwrite((char *)&tlenzero, sizeof (tlenzero), 1, FP)
238+
#define GETLEN(LEN, FP) fread((char *)&(LEN), sizeof (tlenzero), 1, FP)
231239
#define ALLOCTUP(LEN) ((HeapTuple)palloc((unsigned)LEN))
232240
#define GETTUP(NODE, TUP, LEN, FP) do {\
233241
IncrProcessed(); \
234-
((Psortstate *)NODE->psortstate)->BytesRead += (LEN) - sizeof (shortzero); \
235-
fread((char *)(TUP) + sizeof (shortzero), (LEN) - sizeof (shortzero), 1, FP);} \
236-
while (0)
242+
((Psortstate *)NODE->psortstate)->BytesRead += (LEN) - sizeof (tlenzero); \
243+
fread((char *)(TUP) + sizeof (tlenzero), (LEN) - sizeof (tlenzero), 1, FP); \
244+
fread((char *)&tlendummy, sizeof (tlendummy), 1, FP); \
245+
} while (0)
237246
#define SETTUPLEN(TUP, LEN) (TUP)->t_len = LEN
238247

239248
/*
@@ -629,11 +638,11 @@ merge(Sort * node, struct tape * dest)
629638
register struct tape *lasttp; /* (TAPE[P]) */
630639
register struct tape *tp;
631640
struct leftist *tuples;
632-
FILE *destfile;
633-
int times; /* runs left to merge */
634-
int outdummy; /* complete dummy runs */
635-
short fromtape;
636-
long tuplen;
641+
FILE *destfile;
642+
int times; /* runs left to merge */
643+
int outdummy; /* complete dummy runs */
644+
short fromtape;
645+
unsigned int tuplen;
637646

638647
Assert(node != (Sort *) NULL);
639648
Assert(PS(node) != (Psortstate *) NULL);
@@ -767,42 +776,120 @@ dumptuples(FILE * file, Sort * node)
767776
HeapTuple
768777
psort_grabtuple(Sort * node, bool * should_free)
769778
{
770-
register HeapTuple tup;
771-
long tuplen;
779+
register HeapTuple tup;
772780

773781
Assert(node != (Sort *) NULL);
774782
Assert(PS(node) != (Psortstate *) NULL);
775783

776784
if (PS(node)->using_tape_files == true)
777785
{
778-
if (!feof(PS(node)->psort_grab_file))
786+
unsigned int tuplen;
787+
788+
*should_free = true;
789+
if (ScanDirectionIsForward (node->plan.state->es_direction))
779790
{
791+
if (PS(node)->all_fetched)
792+
return NULL;
780793
if (GETLEN(tuplen, PS(node)->psort_grab_file) && tuplen != 0)
781794
{
782795
tup = (HeapTuple) palloc((unsigned) tuplen);
783796
SETTUPLEN(tup, tuplen);
784797
GETTUP(node, tup, tuplen, PS(node)->psort_grab_file);
785798

786799
/* Update current merged sort file position */
787-
PS(node)->psort_current += tuplen;
788-
*should_free = true;
800+
PS(node)->psort_current += tuplen + sizeof (tlendummy);
789801
return tup;
790802
}
791803
else
804+
{
805+
PS(node)->all_fetched = true;
792806
return NULL;
807+
}
793808
}
794-
else
809+
/* Backward */
810+
if (PS(node)->psort_current <= sizeof (tlendummy))
795811
return NULL;
812+
/*
813+
* if all tuples are fetched already then we return last tuple,
814+
* else - tuple before last returned.
815+
*/
816+
if (PS(node)->all_fetched)
817+
{
818+
/* psort_current is pointing to the zero tuplen at the end of file */
819+
fseek(PS(node)->psort_grab_file,
820+
PS(node)->psort_current - sizeof (tlendummy), SEEK_SET);
821+
GETLEN(tuplen, PS(node)->psort_grab_file);
822+
if (PS(node)->psort_current < tuplen)
823+
elog (FATAL, "psort_grabtuple: too big last tuple len in backward scan");
824+
PS(node)->all_fetched = false;
825+
}
826+
else
827+
{
828+
/* move to position of end tlen of prev tuple */
829+
PS(node)->psort_current -= sizeof (tlendummy);
830+
fseek(PS(node)->psort_grab_file, PS(node)->psort_current, SEEK_SET);
831+
GETLEN(tuplen, PS(node)->psort_grab_file); /* get tlen of prev tuple */
832+
if (tuplen == 0)
833+
elog (FATAL, "psort_grabtuple: tuplen is 0 in backward scan");
834+
if (PS(node)->psort_current <= tuplen + sizeof (tlendummy))
835+
{ /* prev tuple should be first one */
836+
if (PS(node)->psort_current != tuplen)
837+
elog (FATAL, "psort_grabtuple: first tuple expected in backward scan");
838+
PS(node)->psort_current = 0;
839+
fseek(PS(node)->psort_grab_file, PS(node)->psort_current, SEEK_SET);
840+
return NULL;
841+
}
842+
/*
843+
* Get position of prev tuple. This tuple becomes current tuple
844+
* now and we have to return previous one.
845+
*/
846+
PS(node)->psort_current -= tuplen;
847+
/* move to position of end tlen of prev tuple */
848+
fseek(PS(node)->psort_grab_file,
849+
PS(node)->psort_current - sizeof (tlendummy), SEEK_SET);
850+
GETLEN(tuplen, PS(node)->psort_grab_file);
851+
if (PS(node)->psort_current < tuplen + sizeof (tlendummy))
852+
elog (FATAL, "psort_grabtuple: too big tuple len in backward scan");
853+
}
854+
/*
855+
* move to prev (or last) tuple start position + sizeof(t_len)
856+
*/
857+
fseek(PS(node)->psort_grab_file,
858+
PS(node)->psort_current - tuplen, SEEK_SET);
859+
tup = (HeapTuple) palloc((unsigned) tuplen);
860+
SETTUPLEN(tup, tuplen);
861+
GETTUP(node, tup, tuplen, PS(node)->psort_grab_file);
862+
return tup; /* file position is equal to psort_current */
796863
}
797864
else
798865
{
799-
if (PS(node)->psort_current < PS(node)->tupcount)
866+
*should_free = false;
867+
if (ScanDirectionIsForward (node->plan.state->es_direction))
800868
{
801-
*should_free = false;
802-
return (PS(node)->memtuples[PS(node)->psort_current++]);
869+
if (PS(node)->psort_current < PS(node)->tupcount)
870+
return (PS(node)->memtuples[PS(node)->psort_current++]);
871+
else
872+
{
873+
PS(node)->all_fetched = true;
874+
return NULL;
875+
}
803876
}
804-
else
877+
/* Backward */
878+
if (PS(node)->psort_current <= 0)
805879
return NULL;
880+
/*
881+
* if all tuples are fetched already then we return last tuple,
882+
* else - tuple before last returned.
883+
*/
884+
if (PS(node)->all_fetched)
885+
PS(node)->all_fetched = false;
886+
else
887+
{
888+
PS(node)->psort_current--; /* last returned tuple */
889+
if (PS(node)->psort_current <= 0)
890+
return NULL;
891+
}
892+
return (PS(node)->memtuples[PS(node)->psort_current - 1]);
806893
}
807894
}
808895

src/include/utils/psort.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
* Copyright (c) 1994, Regents of the University of California
88
*
9-
* $Id: psort.h,v 1.13 1997/09/18 14:42:35 vadim Exp $
9+
* $Id: psort.h,v 1.14 1997/10/15 06:36:36 vadim Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -62,6 +62,7 @@ typedef struct Psortstate
6262
long psort_current; /* could be file offset, or array index */
6363
long psort_saved; /* could be file offset, or array index */
6464
bool using_tape_files;
65+
bool all_fetched; /* this is for cursors */
6566

6667
HeapTuple *memtuples;
6768
} Psortstate;

0 commit comments

Comments
 (0)