*** ./contrib/dict_preload/dict_preload.c.orig	2010-03-18 17:00:33.281409707 +0100
--- ./contrib/dict_preload/dict_preload.c	2010-03-18 17:00:00.417407791 +0100
***************
*** 0 ****
--- 1,102 ----
+ /*-------------------------------------------------------------------------
+  *
+  * dict_preload.c
+  *	  preloaded dictionary - Czech
+  *
+  * Copyright (c) 2007-2010, PostgreSQL Global Development Group
+  *
+  * IDENTIFICATION
+  *	  $PostgreSQL: pgsql/contrib/dict_int/dict_int.c,v 1.6 2010/01/02 16:57:32 momjian Exp $
+  *
+  *-------------------------------------------------------------------------
+  */
+ #include "postgres.h"
+ 
+ #include "commands/defrem.h"
+ #include "fmgr.h"
+ #include "nodes/makefuncs.h"
+ #include "nodes/value.h"
+ #include "tsearch/ts_public.h"
+ #include "tsearch/ts_utils.h"
+ #include "tsearch/dicts/spell.h"
+ #include "utils/memutils.h"
+ 
+ PG_MODULE_MAGIC;
+ 
+ typedef struct
+ {
+ 	StopList	stoplist;
+ 	IspellDict	obj;
+ } DictISpell;
+ 
+ MemoryContext		preload_ctx;
+ 
+ DictISpell		*prepd = NULL;
+ 
+ PG_FUNCTION_INFO_V1(dpreloaddict_init);
+ Datum		dpreloaddict_init(PG_FUNCTION_ARGS);
+ 
+ PG_FUNCTION_INFO_V1(dpreloaddict_lexize);
+ Datum		dpreloaddict_lexize(PG_FUNCTION_ARGS);
+ 
+ void _PG_init(void);
+ 
+ Datum
+ dpreloaddict_init(PG_FUNCTION_ARGS)
+ {
+ 
+ 	if (prepd == NULL)
+ 		return dispell_init(fcinfo);
+ 	else
+ 	{
+ 	
+ 		/* 
+ 		 * Add preload context to current conntext
+ 		 */
+ 		preload_ctx->parent = CurrentMemoryContext;
+ 		preload_ctx->nextchild = CurrentMemoryContext->firstchild;
+ 		CurrentMemoryContext->firstchild = preload_ctx;
+ 		
+ 		return PointerGetDatum(prepd);
+ 	}
+ }
+ 
+ Datum
+ dpreloaddict_lexize(PG_FUNCTION_ARGS)
+ {
+ 	return dispell_lexize(fcinfo);
+ }
+ 
+ 
+ void
+ _PG_init()
+ {
+ 	static bool inited = false;
+ 
+ 	MemoryContext	oldctx;
+ 	List	*dictoptions = NIL;
+ 	FunctionCallInfoData fcinfo;
+ 	
+ 	if (inited)
+ 		return;
+ 	
+ 	preload_ctx = AllocSetContextCreate(NULL, "Ispell dictionary preload context",
+ 											ALLOCSET_DEFAULT_MINSIZE,
+ 											ALLOCSET_DEFAULT_INITSIZE,
+ 											ALLOCSET_DEFAULT_MAXSIZE);
+ 	oldctx = MemoryContextSwitchTo(preload_ctx);
+ 
+ 	dictoptions = list_make1(makeDefElem("DictFile", (Node *) makeString("czech")));
+ 	dictoptions = lappend(dictoptions, makeDefElem("AffFile", (Node *) makeString("czech")));
+ 	dictoptions = lappend(dictoptions, makeDefElem("StopWords", (Node *) makeString("czech")));
+ 	
+ 	InitFunctionCallInfoData(fcinfo, NULL, 1, NULL, NULL);
+ 	fcinfo.arg[0] = PointerGetDatum(dictoptions);
+ 	fcinfo.argnull[0] = false;
+ 	
+ 	prepd = (DictISpell *) DatumGetPointer(dispell_init(&fcinfo));
+ 
+ 	MemoryContextSwitchTo(oldctx);
+ 	
+ 	inited = true;
+ }
*** ./contrib/dict_preload/dict_preload.sql.in.orig	2010-03-18 17:00:52.317502927 +0100
--- ./contrib/dict_preload/dict_preload.sql.in	2010-03-18 13:51:50.816472166 +0100
***************
*** 0 ****
--- 1,19 ----
+ /* $PostgreSQL: pgsql/contrib/dict_int/dict_int.sql.in,v 1.3 2007/11/13 04:24:27 momjian Exp $ */
+ 
+ -- Adjust this setting to control where the objects get created.
+ SET search_path = public;
+ 
+ CREATE OR REPLACE FUNCTION dpreloaddict_init(internal)
+         RETURNS internal
+         AS 'MODULE_PATHNAME'
+         LANGUAGE C STRICT;
+ 
+ CREATE OR REPLACE FUNCTION dpreloaddict_lexize(internal, internal, internal, internal)
+         RETURNS internal
+         AS 'MODULE_PATHNAME'
+         LANGUAGE C STRICT;
+ 
+ CREATE TEXT SEARCH TEMPLATE preloaddict_template (
+         LEXIZE = dpreloaddict_lexize,
+ 	INIT   = dpreloaddict_init
+ );
*** ./contrib/dict_preload/uninstall_dict_preload.sql.orig	2010-03-18 17:00:58.039409567 +0100
--- ./contrib/dict_preload/uninstall_dict_preload.sql	2010-03-18 13:52:49.064472194 +0100
***************
*** 0 ****
--- 1,10 ----
+ /* $PostgreSQL: pgsql/contrib/dict_int/uninstall_dict_int.sql,v 1.3 2007/11/13 04:24:27 momjian Exp $ */
+ 
+ -- Adjust this setting to control where the objects get dropped.
+ SET search_path = public;
+ 
+ DROP TEXT SEARCH TEMPLATE preloaddict_template CASCADE;
+ 
+ DROP FUNCTION dpreloaddict_init(internal);
+ 
+ DROP FUNCTION dpreloaddict_lexize(internal,internal,internal,internal);
*** ./src/backend/tsearch/regis.c.orig	2010-01-02 17:57:53.000000000 +0100
--- ./src/backend/tsearch/regis.c	2010-03-18 16:41:03.027708600 +0100
***************
*** 71,88 ****
  }
  
  static RegisNode *
! newRegisNode(RegisNode *prev, int len)
  {
  	RegisNode  *ptr;
  
! 	ptr = (RegisNode *) palloc0(RNHDRSZ + len + 1);
  	if (prev)
  		prev->next = ptr;
  	return ptr;
  }
  
  void
! RS_compile(Regis *r, bool issuffix, const char *str)
  {
  	int			len = strlen(str);
  	int			state = RS_IN_WAIT;
--- 71,89 ----
  }
  
  static RegisNode *
! newRegisNode(RegisNode *prev, int len, MemoryContext simple_ctx)
  {
  	RegisNode  *ptr;
  
! 	ptr = (RegisNode *) MemoryContextAllocZero(simple_ctx,
! 								RNHDRSZ + len + 1);
  	if (prev)
  		prev->next = ptr;
  	return ptr;
  }
  
  void
! RS_compile(Regis *r, bool issuffix, const char *str, MemoryContext simple_ctx)
  {
  	int			len = strlen(str);
  	int			state = RS_IN_WAIT;
***************
*** 99,107 ****
  			if (t_isalpha(c))
  			{
  				if (ptr)
! 					ptr = newRegisNode(ptr, len);
  				else
! 					ptr = r->node = newRegisNode(NULL, len);
  				COPYCHAR(ptr->data, c);
  				ptr->type = RSF_ONEOF;
  				ptr->len = pg_mblen(c);
--- 100,108 ----
  			if (t_isalpha(c))
  			{
  				if (ptr)
! 					ptr = newRegisNode(ptr, len, simple_ctx);
  				else
! 					ptr = r->node = newRegisNode(NULL, len, simple_ctx);
  				COPYCHAR(ptr->data, c);
  				ptr->type = RSF_ONEOF;
  				ptr->len = pg_mblen(c);
***************
*** 109,117 ****
  			else if (t_iseq(c, '['))
  			{
  				if (ptr)
! 					ptr = newRegisNode(ptr, len);
  				else
! 					ptr = r->node = newRegisNode(NULL, len);
  				ptr->type = RSF_ONEOF;
  				state = RS_IN_ONEOF;
  			}
--- 110,118 ----
  			else if (t_iseq(c, '['))
  			{
  				if (ptr)
! 					ptr = newRegisNode(ptr, len, simple_ctx);
  				else
! 					ptr = r->node = newRegisNode(NULL, len, simple_ctx);
  				ptr->type = RSF_ONEOF;
  				state = RS_IN_ONEOF;
  			}
*** ./src/backend/utils/mmgr/Makefile.orig	2010-03-18 15:15:23.063794982 +0100
--- ./src/backend/utils/mmgr/Makefile	2010-03-18 15:15:29.040796648 +0100
***************
*** 12,17 ****
  top_builddir = ../../../..
  include $(top_builddir)/src/Makefile.global
  
! OBJS = aset.o mcxt.o portalmem.o
  
  include $(top_srcdir)/src/backend/common.mk
--- 12,17 ----
  top_builddir = ../../../..
  include $(top_builddir)/src/Makefile.global
  
! OBJS = aset.o mcxt.o portalmem.o simple_alloc.o
  
  include $(top_srcdir)/src/backend/common.mk
*** ./src/backend/utils/mmgr/simple_alloc.c.orig	2010-03-18 15:14:59.593793406 +0100
--- ./src/backend/utils/mmgr/simple_alloc.c	2010-03-18 11:10:26.000000000 +0100
***************
*** 0 ****
--- 1,348 ----
+ #include "postgres.h"
+ 
+ #include "utils/memutils.h"
+ 
+ typedef struct AllocBlockData *AllocBlock;		/* forward reference */
+ 
+ 
+ typedef struct SimpleAllocContextData
+ {
+ 	MemoryContextData header;	/* Standard memory-context fields */
+ 	AllocBlock	blocks;		/* head of list of standard blocks */
+ 	AllocBlock	bigblocks;	/* head of list of blocks larger than initBlockSize */
+ 	bool	isReset;
+ 	/* Allocation parameters for this context */
+ 	Size initBlockSize;
+ 	void *(*external_alloc) (Size size);	/* allocate memory */
+ 	void (*external_free) (void *);		/* deallocate memory */
+ } SimpleAllocContextData;
+ 
+ typedef SimpleAllocContextData *SimpleAlloc;
+ 
+ typedef struct AllocBlockData
+ {
+ 	AllocBlock	next;
+ 	Size 	   freesize;
+ 	char	   *freeptr;
+ 	char	data[1];
+ } AllocBlockData;
+ 
+ #define SimpleAllocCtxIsValid(ctx)	PointerIsValid(ctx)
+ 
+ #define ALLOC_BLOCKHDRSZ	MAXALIGN(sizeof(AllocBlockData))
+ 
+ static void SimpleAllocInit(MemoryContext context);
+ static void SimpleAllocReset(MemoryContext context);
+ static void SimpleAllocDelete(MemoryContext context);
+ static void *SimpleAllocAlloc(MemoryContext context, Size size);
+ static void SimpleAllocStats(MemoryContext context, int level);
+ static void *SimpleAllocRealloc(MemoryContext context, void *pointer, Size size);
+ static void SimpleAllocFree(MemoryContext context, void *pointer);
+ static bool SimpleAllocIsEmpty(MemoryContext context);
+ static Size SimpleAllocGetChunkSpace(MemoryContext context, void *pointer);
+ 
+ #ifdef MEMORY_CONTEXT_CHECKING
+ static void SimpleAllocCheck(MemoryContext context);
+ #endif
+ 
+ /*
+  * This is the virtual function table for SimpleAlloc context
+  */
+ static MemoryContextMethods SimpleAllocMethods = {
+ 	SimpleAllocAlloc,
+ 	SimpleAllocFree,				/* not supported */
+ 	SimpleAllocRealloc,				/* not supported */
+ 	SimpleAllocInit,
+ 	SimpleAllocReset,
+ 	SimpleAllocDelete,
+ 	SimpleAllocGetChunkSpace,			/* not supported */
+ 	SimpleAllocIsEmpty,
+ 	SimpleAllocStats
+ #ifdef MEMORY_CONTEXT_CHECKING
+ 	, SimpleAllocCheck
+ #endif
+ };
+ 
+ #ifdef RANDOMIZE_ALLOCATED_MEMORY
+ 
+ /*
+  * Fill a just-allocated piece of memory with "random" data.  It's not really
+  * very random, just a repeating sequence with a length that's prime.  What
+  * we mainly want out of it is to have a good probability that two palloc's
+  * of the same number of bytes start out containing different data.
+  */
+ static void
+ randomize_mem(char *ptr, size_t size)
+ {
+ 	static int	save_ctr = 1;
+ 	int			ctr;
+ 
+ 	ctr = save_ctr;
+ 	while (size-- > 0)
+ 	{
+ 		*ptr++ = ctr;
+ 		if (++ctr > 251)
+ 			ctr = 1;
+ 	}
+ 	save_ctr = ctr;
+ }
+ #endif   /* RANDOMIZE_ALLOCATED_MEMORY */
+ 
+ /*
+  * SimpleAllocContextCreate 
+  *
+  *
+  */
+ MemoryContext
+ SimpleAllocContextCreate(MemoryContext parent,
+ 					      const char *name,
+ 					      Size initBlockSize,
+ 					      void *(*external_alloc) (Size size),
+ 					      void (*external_free) (void *))
+ {
+ 	SimpleAlloc	context;
+ 	
+ 	context = (SimpleAlloc) MemoryContextCreate(T_SimpleAllocContext,
+ 										sizeof(SimpleAllocContextData),
+ 										&SimpleAllocMethods,
+ 										parent,
+ 										name);
+ 	context->initBlockSize = MAXALIGN(initBlockSize);
+ 	context->external_alloc = external_alloc;
+ 	context->external_free = external_free;
+ 	
+ 	context->blocks = NULL;
+ 	context->bigblocks = NULL;
+ 	context->isReset = true;
+ 	
+ 	return (MemoryContext) context;
+ }
+ 
+ /* 
+  * Context type methods 
+  */
+ static void
+ SimpleAllocInit(MemoryContext context)
+ {
+ 	/*
+ 	 * do nothing
+ 	 */
+ }
+ 
+ static void
+ SimpleAllocReset(MemoryContext context)
+ {
+ 	AllocBlock	block;
+ 	AllocBlock	next;
+ 	SimpleAlloc simple_ctx = (SimpleAlloc) context;
+ 
+ 	Assert(SimpleAllocCtxIsValid(simple_ctx));
+ 	
+ 	/*
+ 	 * because simple alloc context doesn't support operation free
+ 	 * we don't need to implement keeper block.
+ 	 */
+ 	block = simple_ctx->blocks;
+ 	while (block != NULL)
+ 	{
+ 		next = block->next;
+ #ifdef CLOBBER_FREED_MEMORY
+ 		memset(block->data, 0x7F, simple_ctx->initBlockSize);
+ #endif
+ 
+ 		if (simple_ctx->external_free != NULL)
+ 			simple_ctx->external_free(block);
+ 		else
+ 			ereport(ERROR,
+ 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ 					 errmsg("cannot release allocated memory")));
+ 		block = next;
+ 	}
+ 	
+ 	block = simple_ctx->bigblocks;
+ 	while (block != NULL)
+ 	{
+ 		next = block->next;
+ 		
+ #ifdef CLOBBER_FREED_MEMORY
+ 		memset(block->data, 0x7F, simple_ctx->initBlockSize);
+ #endif
+ 
+ 		if (simple_ctx->external_free != NULL)
+ 			simple_ctx->external_free(block);
+ 		else
+ 			ereport(ERROR,
+ 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ 					 errmsg("cannot release allocated memory")));
+ 		block = next;
+ 	}
+ 	
+ 	simple_ctx->isReset = true;
+ 	simple_ctx->blocks = NULL;
+ 	simple_ctx->bigblocks = NULL;
+ }
+ 
+ static void
+ SimpleAllocDelete(MemoryContext context)
+ {
+ 	SimpleAllocReset(context);
+ }
+ 
+ static void *
+ SimpleAllocAlloc(MemoryContext context, Size size)
+ {
+ 	SimpleAlloc simple_ctx = (SimpleAlloc) context;
+ 	AllocBlock   block;
+ 	void	*newPointer;
+ 	Size allocSize;
+ 	bool	isBigBlock;
+ 	
+ 	Assert(SimpleAllocCtxIsValid(simple_ctx));
+ 
+ 	/* 
+ 	 * Allocate separate block for allocation larger than 1/2 of initBlockSize
+ 	 */
+ 	size = MAXALIGN(size);
+ 	if (size > (simple_ctx->initBlockSize/3*2))
+ 	{
+ 		/* 
+ 		 * we will allocate a big block - block only for current
+ 		 * allocation - these blocks are is separete list.
+ 		 */
+ 		allocSize = size;
+ 		isBigBlock = true;
+ 	}
+ 	else
+ 	{
+ 		allocSize = simple_ctx->initBlockSize;
+ 		isBigBlock = false;
+ 	}
+ 	
+ 	/*
+ 	 * Allocate a new block if there are no allocated or is big
+ 	 * or isn't enought space.
+ 	 */
+ 	if (simple_ctx->blocks == NULL || isBigBlock || 
+ 							(!isBigBlock && simple_ctx->blocks && simple_ctx->blocks->freesize < size))
+ 	{
+ 		/* alloc a new block */
+ 
+ 		block = simple_ctx->external_alloc(MAXALIGN(allocSize + sizeof(AllocBlockData) - 1));
+ 		if (block == NULL)
+ 		{
+ 			MemoryContextStats(TopMemoryContext);
+ 			ereport(ERROR,
+ 					(errcode(ERRCODE_OUT_OF_MEMORY),
+ 					 errmsg("out of memory"),
+ 					 errdetail("Failed on request of size %lu.",
+ 							   (unsigned long) allocSize + sizeof(AllocBlockData) - 1)));
+ 		}
+ 
+ 		block->freesize = allocSize;
+ 		block->freeptr = block->data;
+ 		if (!isBigBlock)
+ 		{
+ 			block->next = simple_ctx->blocks;
+ 			simple_ctx->blocks = block;
+ 		}
+ 		else
+ 		{
+ 			block->next = simple_ctx->bigblocks;
+ 			simple_ctx->bigblocks = block;
+ 		}
+ 	}
+ 	else
+ 		block = simple_ctx->blocks;
+ 
+ 	Assert(size <= block->freesize);
+ 	newPointer = block->freeptr;
+ 	
+ 	if (!isBigBlock)
+ 	{
+ 		block->freeptr += size;
+ 		block->freesize -= size;
+ 	}
+ 	
+ #ifdef RANDOMIZE_ALLOCATED_MEMORY
+ 	randomize_mem((char *) newPointer, size);
+ #endif
+ 	simple_ctx->isReset = false;
+ 
+ 	return newPointer;
+ }
+ 
+ /*
+  * SimpleAllocStats
+  */
+ static void
+ SimpleAllocStats(MemoryContext context, int level)
+ {
+ 	SimpleAlloc simple_ctx = (SimpleAlloc) context;
+ 	AllocBlock	block;
+ 	long nblocks = 0;
+ 	long	totalspace = 0;
+ 	long	freespace = 0;
+ 	int		i;
+ 	
+ 	for (block = simple_ctx->blocks; block != NULL; block = block->next)
+ 	{
+ 		nblocks++;
+ 		totalspace += MAXALIGN(simple_ctx->initBlockSize + sizeof(AllocBlockData) - 1);
+ 		freespace += block->freesize;
+ 	}
+ 	
+ 	for (block = simple_ctx->bigblocks; block != NULL; block = block->next)
+ 	{
+ 		nblocks++;
+ 		totalspace += block->freesize + sizeof(AllocBlockData) - 1;
+ 	}
+ 
+ 	for (i = 0; i < level; i++)
+ 		fprintf(stderr, "  ");
+ 
+ 	fprintf(stderr,
+ 			"%s: %lu total in %ld blocks; %lu free; %lu used\n",
+ 			simple_ctx->header.name, totalspace, nblocks, freespace, 
+ 										totalspace - freespace);
+ }
+ 
+ static void *
+ SimpleAllocRealloc(MemoryContext context, void *pointer, Size size)
+ {
+ 	ereport(ERROR,
+ 			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ 			 errmsg("simple allocator can't realloc memory")));
+ 	return NULL;		/* be compiler quite */
+ }
+ 
+ static void
+ SimpleAllocFree(MemoryContext context, void *pointer)
+ {
+ 	ereport(ERROR,
+ 			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ 			 errmsg("simple allocator can't release memory")));
+ }
+ 
+ static bool
+ SimpleAllocIsEmpty(MemoryContext context)
+ {
+ 	return ((SimpleAlloc) context)->isReset;
+ }
+ 
+ static Size
+ SimpleAllocGetChunkSpace(MemoryContext context, void *pointer)
+ {
+ 	ereport(ERROR,
+ 			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ 			 errmsg("simple allocator has not chunks")));
+ 	return 0;		/* be compile quite */
+ }
+ 
+ #ifdef MEMORY_CONTEXT_CHECKING
+ static void
+ SimpleAllocCheck(MemoryContext context)
+ {
+ 	/* do nothing */
+ }
+ 
+ #endif
*** ./src/include/nodes/memnodes.h.orig	2010-01-02 17:58:04.000000000 +0100
--- ./src/include/nodes/memnodes.h	2010-03-18 15:18:55.349792968 +0100
***************
*** 72,77 ****
   */
  #define MemoryContextIsValid(context) \
  	((context) != NULL && \
! 	 (IsA((context), AllocSetContext)))
  
  #endif   /* MEMNODES_H */
--- 72,77 ----
   */
  #define MemoryContextIsValid(context) \
  	((context) != NULL && \
! 	 (IsA((context), AllocSetContext) || IsA((context), SimpleAllocContext)))
  
  #endif   /* MEMNODES_H */
*** ./src/include/nodes/nodes.h.orig	2010-03-18 15:21:26.328793052 +0100
--- ./src/include/nodes/nodes.h	2010-03-18 15:21:37.257794503 +0100
***************
*** 234,239 ****
--- 234,240 ----
  	 */
  	T_MemoryContext = 600,
  	T_AllocSetContext,
+ 	T_SimpleAllocContext,
  
  	/*
  	 * TAGS FOR VALUE NODES (value.h)
*** ./src/include/tsearch/dicts/regis.h.orig	2010-03-18 16:40:41.584584472 +0100
--- ./src/include/tsearch/dicts/regis.h	2010-03-18 16:40:13.428708569 +0100
***************
*** 40,46 ****
  
  bool		RS_isRegis(const char *str);
  
! void		RS_compile(Regis *r, bool issuffix, const char *str);
  void		RS_free(Regis *r);
  
  /*returns true if matches */
--- 40,46 ----
  
  bool		RS_isRegis(const char *str);
  
! void		RS_compile(Regis *r, bool issuffix, const char *str, MemoryContext simple_ctx);
  void		RS_free(Regis *r);
  
  /*returns true if matches */
*** ./src/include/utils/memutils.h.orig	2010-01-02 17:58:10.000000000 +0100
--- ./src/include/utils/memutils.h	2010-03-18 15:20:48.889794704 +0100
***************
*** 136,139 ****
--- 136,148 ----
  #define ALLOCSET_SMALL_INITSIZE  (1 * 1024)
  #define ALLOCSET_SMALL_MAXSIZE	 (8 * 1024)
  
+ /* simple_alloc.c */
+ extern MemoryContext SimpleAllocContextCreate(MemoryContext parent,
+ 					      const char *name,
+ 					      Size initBlockSize,
+ 					      void *(*external_alloc) (Size size),
+ 					      void (*external_free) (void *));
+ 
+ #define SIMPLEALLOC_LARGE_INITSIZE	(1024 * 128)
+ 
  #endif   /* MEMUTILS_H */
