|
7 | 7 | *
|
8 | 8 | *
|
9 | 9 | * 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 $ |
11 | 11 | *
|
12 | 12 | * NOTES
|
13 | 13 | * Sorts the first relation into the second relation.
|
@@ -80,7 +80,12 @@ static int _psort_cmp (HeapTuple *ltup, HeapTuple *rtup);
|
80 | 80 |
|
81 | 81 | #define TEMPDIR "./"
|
82 | 82 |
|
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; |
84 | 89 |
|
85 | 90 | static TupleDesc PsortTupDesc;
|
86 | 91 | static ScanKey PsortKeys; /* used by _psort_cmp */
|
@@ -150,6 +155,7 @@ psort_begin(Sort * node, int nkeys, ScanKey key)
|
150 | 155 | PS(node)->tupcount = 0;
|
151 | 156 |
|
152 | 157 | PS(node)->using_tape_files = false;
|
| 158 | + PS(node)->all_fetched = false; |
153 | 159 | PS(node)->psort_grab_file = NULL;
|
154 | 160 | PS(node)->memtuples = NULL;
|
155 | 161 |
|
@@ -219,21 +225,24 @@ inittapes(Sort * node)
|
219 | 225 | * GETTUP - reads the tuple
|
220 | 226 | *
|
221 | 227 | * 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 |
223 | 229 | */
|
224 | 230 |
|
225 | 231 |
|
226 | 232 | #define PUTTUP(NODE, TUP, FP) do {\
|
227 | 233 | ((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) |
231 | 239 | #define ALLOCTUP(LEN) ((HeapTuple)palloc((unsigned)LEN))
|
232 | 240 | #define GETTUP(NODE, TUP, LEN, FP) do {\
|
233 | 241 | 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) |
237 | 246 | #define SETTUPLEN(TUP, LEN) (TUP)->t_len = LEN
|
238 | 247 |
|
239 | 248 | /*
|
@@ -629,11 +638,11 @@ merge(Sort * node, struct tape * dest)
|
629 | 638 | register struct tape *lasttp; /* (TAPE[P]) */
|
630 | 639 | register struct tape *tp;
|
631 | 640 | 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; |
637 | 646 |
|
638 | 647 | Assert(node != (Sort *) NULL);
|
639 | 648 | Assert(PS(node) != (Psortstate *) NULL);
|
@@ -767,42 +776,120 @@ dumptuples(FILE * file, Sort * node)
|
767 | 776 | HeapTuple
|
768 | 777 | psort_grabtuple(Sort * node, bool * should_free)
|
769 | 778 | {
|
770 |
| - register HeapTuple tup; |
771 |
| - long tuplen; |
| 779 | + register HeapTuple tup; |
772 | 780 |
|
773 | 781 | Assert(node != (Sort *) NULL);
|
774 | 782 | Assert(PS(node) != (Psortstate *) NULL);
|
775 | 783 |
|
776 | 784 | if (PS(node)->using_tape_files == true)
|
777 | 785 | {
|
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)) |
779 | 790 | {
|
| 791 | + if (PS(node)->all_fetched) |
| 792 | + return NULL; |
780 | 793 | if (GETLEN(tuplen, PS(node)->psort_grab_file) && tuplen != 0)
|
781 | 794 | {
|
782 | 795 | tup = (HeapTuple) palloc((unsigned) tuplen);
|
783 | 796 | SETTUPLEN(tup, tuplen);
|
784 | 797 | GETTUP(node, tup, tuplen, PS(node)->psort_grab_file);
|
785 | 798 |
|
786 | 799 | /* Update current merged sort file position */
|
787 |
| - PS(node)->psort_current += tuplen; |
788 |
| - *should_free = true; |
| 800 | + PS(node)->psort_current += tuplen + sizeof (tlendummy); |
789 | 801 | return tup;
|
790 | 802 | }
|
791 | 803 | else
|
| 804 | + { |
| 805 | + PS(node)->all_fetched = true; |
792 | 806 | return NULL;
|
| 807 | + } |
793 | 808 | }
|
794 |
| - else |
| 809 | + /* Backward */ |
| 810 | + if (PS(node)->psort_current <= sizeof (tlendummy)) |
795 | 811 | 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 */ |
796 | 863 | }
|
797 | 864 | else
|
798 | 865 | {
|
799 |
| - if (PS(node)->psort_current < PS(node)->tupcount) |
| 866 | + *should_free = false; |
| 867 | + if (ScanDirectionIsForward (node->plan.state->es_direction)) |
800 | 868 | {
|
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 | + } |
803 | 876 | }
|
804 |
| - else |
| 877 | + /* Backward */ |
| 878 | + if (PS(node)->psort_current <= 0) |
805 | 879 | 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]); |
806 | 893 | }
|
807 | 894 | }
|
808 | 895 |
|
|
0 commit comments