*** ./src/interfaces/libpq/fe-exec.c.orig	2005-10-15 11:49:48.000000000 +0900
--- ./src/interfaces/libpq/fe-exec.c	2005-11-23 11:10:23.000000000 +0900
***************
*** 79,88 ****
   * we need to be able to enlarge it via realloc, and our trivial space
   * allocator doesn't handle that effectively.  (Too bad the FE/BE protocol
   * doesn't tell us up front how many tuples will be returned.)
!  * All other subsidiary storage for a PGresult is kept in PGresult_data blocks
!  * of size PGRESULT_DATA_BLOCKSIZE.  The overhead at the start of each block
!  * is just a link to the next one, if any.	Free-space management info is
!  * kept in the owning PGresult.
   * A query returning a small amount of data will thus require three malloc
   * calls: one for the PGresult, one for the tuples pointer array, and one
   * PGresult_data block.
--- 79,90 ----
   * we need to be able to enlarge it via realloc, and our trivial space
   * allocator doesn't handle that effectively.  (Too bad the FE/BE protocol
   * doesn't tell us up front how many tuples will be returned.)
!  * All other subsidiary storage for a PGresult is kept in PGresult_data
!  * blocks. The size of first block is PGRESULT_DATA_BLOCKSIZE. And
!  * the size of the next block will be doubled until it reaches 
!  * PGRESULT_MAX_DATA_BLOCKSIZE.
!  * The overhead at the start of each block is just a link to the next one,
!  * if any.	Free-space management info is kept in the owning PGresult.
   * A query returning a small amount of data will thus require three malloc
   * calls: one for the PGresult, one for the tuples pointer array, and one
   * PGresult_data block.
***************
*** 94,100 ****
   * around very long anyway, so some wasted space within one is not a problem.
   *
   * Tuning constants for the space allocator are:
!  * PGRESULT_DATA_BLOCKSIZE: size of a standard allocation block, in bytes
   * PGRESULT_ALIGN_BOUNDARY: assumed alignment requirement for binary data
   * PGRESULT_SEP_ALLOC_THRESHOLD: objects bigger than this are given separate
   *	 blocks, instead of being crammed into a regular allocation block.
--- 96,105 ----
   * around very long anyway, so some wasted space within one is not a problem.
   *
   * Tuning constants for the space allocator are:
!  * PGRESULT_DATA_BLOCKSIZE: initial size of a standard allocation block,
!  *	 in bytes
!  * PGRESULT_MAX_DATA_BLOCKSIZE: maximum size of a standard allocation block,
!  *	 in bytes
   * PGRESULT_ALIGN_BOUNDARY: assumed alignment requirement for binary data
   * PGRESULT_SEP_ALLOC_THRESHOLD: objects bigger than this are given separate
   *	 blocks, instead of being crammed into a regular allocation block.
***************
*** 112,117 ****
--- 117,123 ----
   */
  
  #define PGRESULT_DATA_BLOCKSIZE		2048
+ #define PGRESULT_MAX_DATA_BLOCKSIZE	(1024 * 2048)		/* 2Mbyte */
  #define PGRESULT_ALIGN_BOUNDARY		MAXIMUM_ALIGNOF		/* from configure */
  #define PGRESULT_BLOCK_OVERHEAD		Max(sizeof(PGresult_data), PGRESULT_ALIGN_BOUNDARY)
  #define PGRESULT_SEP_ALLOC_THRESHOLD	(PGRESULT_DATA_BLOCKSIZE / 2)
***************
*** 149,154 ****
--- 155,161 ----
  	result->errFields = NULL;
  	result->null_field[0] = '\0';
  	result->curBlock = NULL;
+ 	result->nextAllocSize = PGRESULT_DATA_BLOCKSIZE;
  	result->curOffset = 0;
  	result->spaceLeft = 0;
  
***************
*** 200,205 ****
--- 207,213 ----
  pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary)
  {
  	char	   *space;
+ 	int			alloc_size;
  	PGresult_data *block;
  
  	if (!res)
***************
*** 264,270 ****
  	}
  
  	/* Otherwise, start a new block. */
! 	block = (PGresult_data *) malloc(PGRESULT_DATA_BLOCKSIZE);
  	if (!block)
  		return NULL;
  	block->next = res->curBlock;
--- 272,279 ----
  	}
  
  	/* Otherwise, start a new block. */
! 	alloc_size = res->nextAllocSize;
! 	block = (PGresult_data *) malloc(alloc_size);
  	if (!block)
  		return NULL;
  	block->next = res->curBlock;
***************
*** 273,290 ****
  	{
  		/* object needs full alignment */
  		res->curOffset = PGRESULT_BLOCK_OVERHEAD;
! 		res->spaceLeft = PGRESULT_DATA_BLOCKSIZE - PGRESULT_BLOCK_OVERHEAD;
  	}
  	else
  	{
  		/* we can cram it right after the overhead pointer */
  		res->curOffset = sizeof(PGresult_data);
! 		res->spaceLeft = PGRESULT_DATA_BLOCKSIZE - sizeof(PGresult_data);
  	}
  
  	space = block->space + res->curOffset;
  	res->curOffset += nBytes;
  	res->spaceLeft -= nBytes;
  	return space;
  }
  
--- 282,304 ----
  	{
  		/* object needs full alignment */
  		res->curOffset = PGRESULT_BLOCK_OVERHEAD;
! 		res->spaceLeft = alloc_size - PGRESULT_BLOCK_OVERHEAD;
  	}
  	else
  	{
  		/* we can cram it right after the overhead pointer */
  		res->curOffset = sizeof(PGresult_data);
! 		res->spaceLeft = alloc_size - sizeof(PGresult_data);
  	}
  
  	space = block->space + res->curOffset;
  	res->curOffset += nBytes;
  	res->spaceLeft -= nBytes;
+ 
+ 	/* Set the next allocation size. */ 
+ 	if(res->nextAllocSize < PGRESULT_MAX_DATA_BLOCKSIZE) {
+ 		res->nextAllocSize *= 2;
+ 	}
  	return space;
  }
  
*** ./src/interfaces/libpq/libpq-int.h.orig	2005-10-15 11:49:49.000000000 +0900
--- ./src/interfaces/libpq/libpq-int.h	2005-11-23 10:47:01.000000000 +0900
***************
*** 174,179 ****
--- 174,180 ----
  	 * separately malloc'd block, so that we can realloc it.
  	 */
  	PGresult_data *curBlock;	/* most recently allocated block */
+ 	int			nextAllocSize;	/* block size for next allocation */
  	int			curOffset;		/* start offset of free space in block */
  	int			spaceLeft;		/* number of free bytes remaining in block */
  };