diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c index 466d53d..4d4f9ec 100644 --- a/src/backend/utils/mmgr/mcxt.c +++ b/src/backend/utils/mmgr/mcxt.c @@ -695,6 +695,38 @@ repalloc(void *pointer, Size size) pointer, size); } +/* repallocJJ -- like repalloc only lets you exceed MaxAllocSize + * By using this function, you solemnly plege that you will not + * pass the returned pointer to aset.c code or varlena objects. + * see src/include/utils/memutils.h MaxAllocSize comments. +void * +repallocJJ(void *pointer, Size size) +{ + StandardChunkHeader *header; + + /* + * Try to detect bogus pointers handed to us, poorly though we can. + * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an + * allocated chunk. + */ + Assert(pointer != NULL); + Assert(pointer == (void *) MAXALIGN(pointer)); + + /* + * OK, it's probably safe to look at the chunk header. + */ + header = (StandardChunkHeader *) + ((char *) pointer - STANDARDCHUNKHEADERSIZE); + + AssertArg(MemoryContextIsValid(header->context)); + + /* isReset must be false already */ + Assert(!header->context->isReset); + + return (*header->context->methods->realloc) (header->context, + pointer, size); +} + /* * MemoryContextSwitchTo * Returns the current context; installs the given context. diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c index 1452e8c..8d28548 100644 --- a/src/backend/utils/sort/tuplesort.c +++ b/src/backend/utils/sort/tuplesort.c @@ -960,14 +960,13 @@ grow_memtuples(Tuplesortstate *state) /* * On a 64-bit machine, allowedMem could be high enough to get us into * trouble with MaxAllocSize, too. + * Get around this by using our own repalloc version */ - if ((Size) (state->memtupsize * 2) >= MaxAllocSize / sizeof(SortTuple)) - return false; FREEMEM(state, GetMemoryChunkSpace(state->memtuples)); state->memtupsize *= 2; state->memtuples = (SortTuple *) - repalloc(state->memtuples, + repallocJJ(state->memtuples, state->memtupsize * sizeof(SortTuple)); USEMEM(state, GetMemoryChunkSpace(state->memtuples)); if (LACKMEM(state)) @@ -1653,9 +1652,9 @@ inittapes(Tuplesortstate *state) state->tapeRange = maxTapes - 1; #ifdef TRACE_SORT - if (trace_sort) - elog(LOG, "switching to external sort with %d tapes: %s", - maxTapes, pg_rusage_show(&state->ru_start)); + if (trace_sort) + elog(LOG, "switching to external sort at %d/%d tuples with %d tapes: %s", + state->memtupcount, state->memtupsize, maxTapes, pg_rusage_show(&state->ru_start)); #endif /* diff --git a/src/include/utils/palloc.h b/src/include/utils/palloc.h index 973f306..50cc864 100644 --- a/src/include/utils/palloc.h +++ b/src/include/utils/palloc.h @@ -69,6 +69,7 @@ extern void *MemoryContextAllocZeroAligned(MemoryContext context, Size size); extern void pfree(void *pointer); extern void *repalloc(void *pointer, Size size); +extern void *repallocJJ(void *pointer, Size size); /* * MemoryContextSwitchTo can't be a macro in standard C compilers.