Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2006-10-03 22:18:23 +0000
committerTom Lane2006-10-03 22:18:23 +0000
commit6edd2b4a91bda90b7f0290203bf5c88a8a8504db (patch)
treec0890bc97d0e2d1e1c92b9b883150a91995dbc89 /src/backend
parented80f5701be9322d319a4abaef0e4f47f6144f5b (diff)
Switch over to using our own qsort() all the time, as has been proposed
repeatedly. Now that we don't have to worry about memory leaks from glibc's qsort, we can safely put CHECK_FOR_INTERRUPTS into the tuplesort comparators, as was requested a couple months ago. Also, get rid of non-reentrancy and an extra level of function call in tuplesort.c by providing a variant qsort_arg() API that passes an extra void * argument through to the comparison routine. (We might want to use that in other places too, I didn't look yet.)
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/utils/sort/tuplesort.c73
1 files changed, 29 insertions, 44 deletions
diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index 7d503f244fb..08e63e0756d 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -91,7 +91,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/sort/tuplesort.c,v 1.68 2006/07/14 14:52:25 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/sort/tuplesort.c,v 1.69 2006/10/03 22:18:23 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -201,11 +201,11 @@ struct Tuplesortstate
* They are set up by the tuplesort_begin_xxx routines.
*
* Function to compare two tuples; result is per qsort() convention, ie:
- *
- * <0, 0, >0 according as a<b, a=b, a>b.
+ * <0, 0, >0 according as a<b, a=b, a>b. The API must match
+ * qsort_arg_comparator.
*/
- int (*comparetup) (Tuplesortstate *state,
- const SortTuple *a, const SortTuple *b);
+ int (*comparetup) (const SortTuple *a, const SortTuple *b,
+ Tuplesortstate *state);
/*
* Function to copy a supplied input tuple into palloc'd space and set up
@@ -345,7 +345,7 @@ struct Tuplesortstate
#endif
};
-#define COMPARETUP(state,a,b) ((*(state)->comparetup) (state, a, b))
+#define COMPARETUP(state,a,b) ((*(state)->comparetup) (a, b, state))
#define COPYTUP(state,stup,tup) ((*(state)->copytup) (state, stup, tup))
#define WRITETUP(state,tape,stup) ((*(state)->writetup) (state, tape, stup))
#define READTUP(state,stup,tape,len) ((*(state)->readtup) (state, stup, tape, len))
@@ -410,37 +410,28 @@ static void tuplesort_heap_insert(Tuplesortstate *state, SortTuple *tuple,
static void tuplesort_heap_siftup(Tuplesortstate *state, bool checkIndex);
static unsigned int getlen(Tuplesortstate *state, int tapenum, bool eofOK);
static void markrunend(Tuplesortstate *state, int tapenum);
-static int qsort_comparetup(const void *a, const void *b);
-static int comparetup_heap(Tuplesortstate *state,
- const SortTuple *a, const SortTuple *b);
+static int comparetup_heap(const SortTuple *a, const SortTuple *b,
+ Tuplesortstate *state);
static void copytup_heap(Tuplesortstate *state, SortTuple *stup, void *tup);
static void writetup_heap(Tuplesortstate *state, int tapenum,
SortTuple *stup);
static void readtup_heap(Tuplesortstate *state, SortTuple *stup,
int tapenum, unsigned int len);
-static int comparetup_index(Tuplesortstate *state,
- const SortTuple *a, const SortTuple *b);
+static int comparetup_index(const SortTuple *a, const SortTuple *b,
+ Tuplesortstate *state);
static void copytup_index(Tuplesortstate *state, SortTuple *stup, void *tup);
static void writetup_index(Tuplesortstate *state, int tapenum,
SortTuple *stup);
static void readtup_index(Tuplesortstate *state, SortTuple *stup,
int tapenum, unsigned int len);
-static int comparetup_datum(Tuplesortstate *state,
- const SortTuple *a, const SortTuple *b);
+static int comparetup_datum(const SortTuple *a, const SortTuple *b,
+ Tuplesortstate *state);
static void copytup_datum(Tuplesortstate *state, SortTuple *stup, void *tup);
static void writetup_datum(Tuplesortstate *state, int tapenum,
SortTuple *stup);
static void readtup_datum(Tuplesortstate *state, SortTuple *stup,
int tapenum, unsigned int len);
-/*
- * Since qsort(3) will not pass any context info to qsort_comparetup(),
- * we have to use this ugly static variable. It is set to point to the
- * active Tuplesortstate object just before calling qsort. It should
- * not be used directly by anything except qsort_comparetup().
- */
-static Tuplesortstate *qsort_tuplesortstate;
-
/*
* tuplesort_begin_xxx
@@ -930,11 +921,11 @@ tuplesort_performsort(Tuplesortstate *state)
* amount of memory. Just qsort 'em and we're done.
*/
if (state->memtupcount > 1)
- {
- qsort_tuplesortstate = state;
- qsort((void *) state->memtuples, state->memtupcount,
- sizeof(SortTuple), qsort_comparetup);
- }
+ qsort_arg((void *) state->memtuples,
+ state->memtupcount,
+ sizeof(SortTuple),
+ (qsort_arg_comparator) state->comparetup,
+ (void *) state);
state->current = 0;
state->eof_reached = false;
state->markpos_offset = 0;
@@ -1587,7 +1578,6 @@ mergeonerun(Tuplesortstate *state)
*/
while (state->memtupcount > 0)
{
- CHECK_FOR_INTERRUPTS();
/* write the tuple to destTape */
priorAvail = state->availMem;
srcTape = state->memtuples[0].tupindex;
@@ -2092,20 +2082,6 @@ markrunend(Tuplesortstate *state, int tapenum)
/*
- * qsort interface
- */
-
-static int
-qsort_comparetup(const void *a, const void *b)
-{
- /* The passed pointers are pointers to SortTuple ... */
- return COMPARETUP(qsort_tuplesortstate,
- (const SortTuple *) a,
- (const SortTuple *) b);
-}
-
-
-/*
* This routine selects an appropriate sorting function to implement
* a sort operator as efficiently as possible. The straightforward
* method is to use the operator's implementation proc --- ie, "<"
@@ -2319,7 +2295,7 @@ ApplySortFunction(FmgrInfo *sortFunction, SortFunctionKind kind,
*/
static int
-comparetup_heap(Tuplesortstate *state, const SortTuple *a, const SortTuple *b)
+comparetup_heap(const SortTuple *a, const SortTuple *b, Tuplesortstate *state)
{
ScanKey scanKey = state->scanKeys;
HeapTupleData ltup;
@@ -2328,6 +2304,9 @@ comparetup_heap(Tuplesortstate *state, const SortTuple *a, const SortTuple *b)
int nkey;
int32 compare;
+ /* Allow interrupting long sorts */
+ CHECK_FOR_INTERRUPTS();
+
/* Compare the leading sort key */
compare = inlineApplySortFunction(&scanKey->sk_func,
state->sortFnKinds[0],
@@ -2449,7 +2428,7 @@ readtup_heap(Tuplesortstate *state, SortTuple *stup,
*/
static int
-comparetup_index(Tuplesortstate *state, const SortTuple *a, const SortTuple *b)
+comparetup_index(const SortTuple *a, const SortTuple *b, Tuplesortstate *state)
{
/*
* This is similar to _bt_tuplecompare(), but we have already done the
@@ -2466,6 +2445,9 @@ comparetup_index(Tuplesortstate *state, const SortTuple *a, const SortTuple *b)
int nkey;
int32 compare;
+ /* Allow interrupting long sorts */
+ CHECK_FOR_INTERRUPTS();
+
/* Compare the leading sort key */
compare = inlineApplySortFunction(&scanKey->sk_func,
SORTFUNC_CMP,
@@ -2622,8 +2604,11 @@ readtup_index(Tuplesortstate *state, SortTuple *stup,
*/
static int
-comparetup_datum(Tuplesortstate *state, const SortTuple *a, const SortTuple *b)
+comparetup_datum(const SortTuple *a, const SortTuple *b, Tuplesortstate *state)
{
+ /* Allow interrupting long sorts */
+ CHECK_FOR_INTERRUPTS();
+
return inlineApplySortFunction(&state->sortOpFn, state->sortFnKind,
a->datum1, a->isnull1,
b->datum1, b->isnull1);