*
*
* 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
* Sorts the first relation into the second relation.
#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 ScanKey PsortKeys; /* used by _psort_cmp */
PS(node)->tupcount = 0;
PS(node)->using_tape_files = false;
+ PS(node)->all_fetched = false;
PS(node)->psort_grab_file = NULL;
PS(node)->memtuples = NULL;
* GETTUP - reads the tuple
*
* 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 {\
((Psortstate *)NODE->psortstate)->BytesWritten += (TUP)->t_len; \
- fwrite((char *)TUP, (TUP)->t_len, 1, FP);} while (0)
-#define ENDRUN(FP) fwrite((char *)&shortzero, sizeof (shortzero), 1, FP)
-#define GETLEN(LEN, FP) fread((char *)&(LEN), sizeof (shortzero), 1, FP)
+ fwrite((char *)TUP, (TUP)->t_len, 1, FP); \
+ fwrite((char *)&((TUP)->t_len), sizeof (tlendummy), 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 GETTUP(NODE, TUP, LEN, FP) do {\
IncrProcessed(); \
- ((Psortstate *)NODE->psortstate)->BytesRead += (LEN) - sizeof (shortzero); \
- fread((char *)(TUP) + sizeof (shortzero), (LEN) - sizeof (shortzero), 1, FP);} \
- while (0)
+ ((Psortstate *)NODE->psortstate)->BytesRead += (LEN) - sizeof (tlenzero); \
+ fread((char *)(TUP) + sizeof (tlenzero), (LEN) - sizeof (tlenzero), 1, FP); \
+ fread((char *)&tlendummy, sizeof (tlendummy), 1, FP); \
+ } while (0)
#define SETTUPLEN(TUP, LEN) (TUP)->t_len = LEN
/*
register struct tape *lasttp; /* (TAPE[P]) */
register struct tape *tp;
struct leftist *tuples;
- FILE *destfile;
- int times; /* runs left to merge */
- int outdummy; /* complete dummy runs */
- short fromtape;
- long tuplen;
+ FILE *destfile;
+ 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);
HeapTuple
psort_grabtuple(Sort * node, bool * should_free)
{
- register HeapTuple tup;
- long tuplen;
+ register HeapTuple tup;
Assert(node != (Sort *) NULL);
Assert(PS(node) != (Psortstate *) NULL);
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)
{
tup = (HeapTuple) palloc((unsigned) tuplen);
GETTUP(node, tup, tuplen, PS(node)->psort_grab_file);
/* Update current merged sort file position */
- PS(node)->psort_current += tuplen;
- *should_free = true;
+ PS(node)->psort_current += tuplen + sizeof (tlendummy);
return tup;
}
else
+ {
+ PS(node)->all_fetched = true;
return NULL;
+ }
}
- else
+ /* Backward */
+ if (PS(node)->psort_current <= sizeof (tlendummy))
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
+ {
+ /* 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
{
- if (PS(node)->psort_current < PS(node)->tupcount)
+ *should_free = false;
+ if (ScanDirectionIsForward (node->plan.state->es_direction))
{
- *should_free = false;
- return (PS(node)->memtuples[PS(node)->psort_current++]);
+ if (PS(node)->psort_current < PS(node)->tupcount)
+ return (PS(node)->memtuples[PS(node)->psort_current++]);
+ else
+ {
+ PS(node)->all_fetched = true;
+ return NULL;
+ }
}
- else
+ /* 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]);
}
}