diff -cpr postgresql-snapshot/src/interfaces/ecpg/ecpglib/connect.c ecpg-descriptor-fix/src/interfaces/ecpg/ecpglib/connect.c
*** postgresql-snapshot/src/interfaces/ecpg/ecpglib/connect.c	2007-09-30 20:38:48.000000000 +0900
--- ecpg-descriptor-fix/src/interfaces/ecpg/ecpglib/connect.c	2007-10-02 13:51:04.000000000 +0900
*************** ECPGconnect(int lineno, int c, const cha
*** 447,452 ****
--- 447,453 ----
  
  	this->cache_head = NULL;
  	this->prep_stmts = NULL;
+ 	this->descriptors = NULL;
  
  	if (all_connections == NULL)
  		this->next = NULL;
diff -cpr postgresql-snapshot/src/interfaces/ecpg/ecpglib/descriptor.c ecpg-descriptor-fix/src/interfaces/ecpg/ecpglib/descriptor.c
*** postgresql-snapshot/src/interfaces/ecpg/ecpglib/descriptor.c	2007-08-14 19:01:52.000000000 +0900
--- ecpg-descriptor-fix/src/interfaces/ecpg/ecpglib/descriptor.c	2007-10-02 13:52:28.000000000 +0900
***************
*** 7,12 ****
--- 7,13 ----
  #include "postgres_fe.h"
  #include "pg_type.h"
  
+ #include "ecpg-pthread-win32.h"
  #include "ecpgtype.h"
  #include "ecpglib.h"
  #include "ecpgerrno.h"
***************
*** 14,31 ****
  #include "sqlca.h"
  #include "sql3types.h"
  
! struct descriptor *all_descriptors = NULL;
  
  /* old internal convenience function that might go away later */
! static PGresult
! 		   *
  ECPGresultByDescriptor(int line, const char *name)
  {
! 	PGresult  **resultpp = ECPGdescriptor_lvalue(line, name);
! 
! 	if (resultpp)
! 		return *resultpp;
! 	return NULL;
  }
  
  static unsigned int
--- 15,69 ----
  #include "sqlca.h"
  #include "sql3types.h"
  
! static void descriptor_free(struct descriptor *desc);
! static void descriptor_deallocate_all(struct descriptor *list);
! 
! /* We manage descriptors separately for each thread. */
! #ifdef ENABLE_THREAD_SAFETY
! static pthread_key_t	descriptor_key;
! #ifndef WIN32
! static pthread_once_t	descriptor_once = PTHREAD_ONCE_INIT;
! #endif
! 
! static void
! descriptor_destructor(void *arg)
! {
! 	descriptor_deallocate_all(arg);
! }
! 
! NON_EXEC_STATIC void
! descriptor_key_init(void)
! {
! 	pthread_key_create(&descriptor_key, descriptor_destructor);
! }
! 
! static struct descriptor *
! get_descriptors(void)
! {
! 	pthread_once(&descriptor_once, descriptor_key_init);
! 	return (struct descriptor *) pthread_getspecific(descriptor_key);
! }
! 
! static void
! set_descriptors(struct descriptor *value)
! {
! 	pthread_setspecific(descriptor_key, value);
! }
! 
! #else
! static struct descriptor		*all_descriptors = NULL;
! #define get_descriptors()		(all_descriptors)
! #define set_descriptors(value)	do { all_descriptors = (value); } while(0)
! #endif
  
  /* old internal convenience function that might go away later */
! static PGresult *
  ECPGresultByDescriptor(int line, const char *name)
  {
! 	struct descriptor *desc = ECPGfind_desc(line, name);
! 	if (desc == NULL)
! 		return NULL;
! 	return desc->result;
  }
  
  static unsigned int
*************** ECPGget_desc(int lineno, const char *des
*** 445,464 ****
  bool
  ECPGset_desc_header(int lineno, const char *desc_name, int count)
  {
! 	struct descriptor *desc;
! 
! 	for (desc = all_descriptors; desc; desc = desc->next)
! 	{
! 		if (strcmp(desc_name, desc->name) == 0)
! 			break;
! 	}
! 
  	if (desc == NULL)
- 	{
- 		ECPGraise(lineno, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, desc_name);
  		return false;
- 	}
- 
  	desc->count = count;
  	return true;
  }
--- 483,491 ----
  bool
  ECPGset_desc_header(int lineno, const char *desc_name, int count)
  {
! 	struct descriptor *desc = ECPGfind_desc(lineno, desc_name);
  	if (desc == NULL)
  		return false;
  	desc->count = count;
  	return true;
  }
*************** ECPGset_desc(int lineno, const char *des
*** 471,487 ****
  	struct descriptor_item *desc_item;
  	struct variable *var;
  
! 	for (desc = all_descriptors; desc; desc = desc->next)
! 	{
! 		if (strcmp(desc_name, desc->name) == 0)
! 			break;
! 	}
! 
  	if (desc == NULL)
- 	{
- 		ECPGraise(lineno, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, desc_name);
  		return false;
- 	}
  
  	for (desc_item = desc->items; desc_item; desc_item = desc_item->next)
  	{
--- 498,506 ----
  	struct descriptor_item *desc_item;
  	struct variable *var;
  
! 	desc = ECPGfind_desc(lineno, desc_name);
  	if (desc == NULL)
  		return false;
  
  	for (desc_item = desc->items; desc_item; desc_item = desc_item->next)
  	{
*************** ECPGset_desc(int lineno, const char *des
*** 506,512 ****
  
  	va_start(args, index);
  
! 	do
  	{
  		enum ECPGdtype itemtype;
  		const char *tobeinserted = NULL;
--- 525,531 ----
  
  	va_start(args, index);
  
! 	for (;;)
  	{
  		enum ECPGdtype itemtype;
  		const char *tobeinserted = NULL;
*************** ECPGset_desc(int lineno, const char *des
*** 585,624 ****
  					return false;
  				}
  		}
! 	} while (true);
  	ECPGfree(var);
  
  	return true;
  }
  
  bool
  ECPGdeallocate_desc(int line, const char *name)
  {
  	struct descriptor *desc;
! 	struct descriptor **lastptr = &all_descriptors;
  	struct sqlca_t *sqlca = ECPGget_sqlca();
  
  	ECPGinit_sqlca(sqlca);
! 	for (desc = all_descriptors; desc; lastptr = &desc->next, desc = desc->next)
  	{
  		if (!strcmp(name, desc->name))
  		{
! 			struct descriptor_item *desc_item;
! 
! 			for (desc_item = desc->items; desc_item;)
! 			{
! 				struct descriptor_item *di;
! 
! 				ECPGfree(desc_item->data);
! 				di = desc_item;
! 				desc_item = desc_item->next;
! 				ECPGfree(di);
! 			}
! 
! 			*lastptr = desc->next;
! 			ECPGfree(desc->name);
! 			PQclear(desc->result);
! 			ECPGfree(desc);
  			return true;
  		}
  	}
--- 604,653 ----
  					return false;
  				}
  		}
! 	}
  	ECPGfree(var);
  
  	return true;
  }
  
+ /* Free the descriptor and items in it. */
+ static void
+ descriptor_free(struct descriptor *desc)
+ {
+ 	struct descriptor_item *desc_item;
+ 
+ 	for (desc_item = desc->items; desc_item;)
+ 	{
+ 		struct descriptor_item *di;
+ 
+ 		ECPGfree(desc_item->data);
+ 		di = desc_item;
+ 		desc_item = desc_item->next;
+ 		ECPGfree(di);
+ 	}
+ 
+ 	ECPGfree(desc->name);
+ 	PQclear(desc->result);
+ 	ECPGfree(desc);
+ }
+ 
  bool
  ECPGdeallocate_desc(int line, const char *name)
  {
  	struct descriptor *desc;
! 	struct descriptor *prev;
  	struct sqlca_t *sqlca = ECPGget_sqlca();
  
  	ECPGinit_sqlca(sqlca);
! 	for (desc = get_descriptors(), prev = NULL; desc; prev = desc, desc = desc->next)
  	{
  		if (!strcmp(name, desc->name))
  		{
! 			if (prev)
! 				prev->next = desc->next;
! 			else
! 				set_descriptors(desc->next);
! 			descriptor_free(desc);
  			return true;
  		}
  	}
*************** ECPGdeallocate_desc(int line, const char
*** 626,631 ****
--- 655,672 ----
  	return false;
  }
  
+ /* Deallocate all descriptors in the list */
+ static void
+ descriptor_deallocate_all(struct descriptor *list)
+ {
+ 	while (list)
+ 	{
+ 		struct descriptor *next = list->next;
+ 		descriptor_free(list);
+ 		list = next;
+ 	}
+ }
+ 
  bool
  ECPGallocate_desc(int line, const char *name)
  {
*************** ECPGallocate_desc(int line, const char *
*** 636,642 ****
  	new = (struct descriptor *) ECPGalloc(sizeof(struct descriptor), line);
  	if (!new)
  		return false;
! 	new->next = all_descriptors;
  	new->name = ECPGalloc(strlen(name) + 1, line);
  	if (!new->name)
  	{
--- 677,683 ----
  	new = (struct descriptor *) ECPGalloc(sizeof(struct descriptor), line);
  	if (!new)
  		return false;
! 	new->next = get_descriptors();
  	new->name = ECPGalloc(strlen(name) + 1, line);
  	if (!new->name)
  	{
*************** ECPGallocate_desc(int line, const char *
*** 654,676 ****
  		return false;
  	}
  	strcpy(new->name, name);
! 	all_descriptors = new;
  	return true;
  }
  
! PGresult  **
! ECPGdescriptor_lvalue(int line, const char *descriptor)
  {
! 	struct descriptor *i;
  
! 	for (i = all_descriptors; i != NULL; i = i->next)
  	{
! 		if (!strcmp(descriptor, i->name))
! 			return &i->result;
  	}
  
! 	ECPGraise(line, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, (char *) descriptor);
! 	return NULL;
  }
  
  bool
--- 695,718 ----
  		return false;
  	}
  	strcpy(new->name, name);
! 	set_descriptors(new);
  	return true;
  }
  
! /* Find descriptor with name in the connection. */
! struct descriptor *
! ECPGfind_desc(int line, const char *name)
  {
! 	struct descriptor *desc;
  
! 	for (desc = get_descriptors(); desc; desc = desc->next)
  	{
! 		if (strcmp(name, desc->name) == 0)
! 			return desc;
  	}
  
! 	ECPGraise(line, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, name);
! 	return NULL;	/* not found */
  }
  
  bool
diff -cpr postgresql-snapshot/src/interfaces/ecpg/ecpglib/execute.c ecpg-descriptor-fix/src/interfaces/ecpg/ecpglib/execute.c
*** postgresql-snapshot/src/interfaces/ecpg/ecpglib/execute.c	2007-09-26 19:57:00.000000000 +0900
--- ecpg-descriptor-fix/src/interfaces/ecpg/ecpglib/execute.c	2007-10-02 13:51:04.000000000 +0900
*************** ECPGexecute(struct statement * stmt)
*** 1088,1104 ****
  			struct descriptor *desc;
  			struct descriptor_item *desc_item;
  
! 			for (desc = all_descriptors; desc; desc = desc->next)
! 			{
! 				if (strcmp(var->pointer, desc->name) == 0)
! 					break;
! 			}
! 
  			if (desc == NULL)
- 			{
- 				ECPGraise(stmt->lineno, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, var->pointer);
  				return false;
- 			}
  
  			desc_counter++;
  			for (desc_item = desc->items; desc_item; desc_item = desc_item->next)
--- 1088,1096 ----
  			struct descriptor *desc;
  			struct descriptor_item *desc_item;
  
! 			desc = ECPGfind_desc(stmt->lineno, var->pointer);
  			if (desc == NULL)
  				return false;
  
  			desc_counter++;
  			for (desc_item = desc->items; desc_item; desc_item = desc_item->next)
*************** ECPGexecute(struct statement * stmt)
*** 1334,1349 ****
  
  			if (var != NULL && var->type == ECPGt_descriptor)
  			{
! 				PGresult  **resultpp = ECPGdescriptor_lvalue(stmt->lineno, (const char *) var->pointer);
! 
! 				if (resultpp == NULL)
  					status = false;
  				else
  				{
! 					if (*resultpp)
! 						PQclear(*resultpp);
! 					*resultpp = results;
! 					clear_result = FALSE;
  					ECPGlog("ECPGexecute putting result (%d tuples) into descriptor '%s'\n", PQntuples(results), (const char *) var->pointer);
  				}
  				var = var->next;
--- 1326,1340 ----
  
  			if (var != NULL && var->type == ECPGt_descriptor)
  			{
! 				struct descriptor *desc = ECPGfind_desc(stmt->lineno, var->pointer);
! 				if (desc == NULL)
  					status = false;
  				else
  				{
! 					if (desc->result)
! 						PQclear(desc->result);
! 					desc->result = results;
! 					clear_result = false;
  					ECPGlog("ECPGexecute putting result (%d tuples) into descriptor '%s'\n", PQntuples(results), (const char *) var->pointer);
  				}
  				var = var->next;
diff -cpr postgresql-snapshot/src/interfaces/ecpg/ecpglib/extern.h ecpg-descriptor-fix/src/interfaces/ecpg/ecpglib/extern.h
*** postgresql-snapshot/src/interfaces/ecpg/ecpglib/extern.h	2007-09-30 20:38:48.000000000 +0900
--- ecpg-descriptor-fix/src/interfaces/ecpg/ecpglib/extern.h	2007-10-02 13:51:04.000000000 +0900
*************** bool ECPGget_data(const PGresult *, int,
*** 36,41 ****
--- 36,43 ----
  
  #ifdef ENABLE_THREAD_SAFETY
  void		ecpg_pthreads_init(void);
+ #else
+ #define		ecpg_pthreads_init()		((void)0)
  #endif
  struct connection *ECPGget_connection(const char *);
  char	   *ECPGalloc(long, int);
*************** struct connection
*** 92,97 ****
--- 94,100 ----
  	int			autocommit;
  	struct ECPGtype_information_cache *cache_head;
  	struct prepared_statement *prep_stmts;
+ 	struct descriptor *descriptors;
  	struct connection *next;
  };
  
*************** struct descriptor
*** 105,112 ****
  	struct descriptor_item *items;
  };
  
- extern struct descriptor *all_descriptors;
- 
  struct descriptor_item
  {
  	int			num;
--- 108,113 ----
*************** struct variable
*** 136,142 ****
  	struct variable *next;
  };
  
! PGresult  **ECPGdescriptor_lvalue(int line, const char *descriptor);
  
  bool ECPGstore_result(const PGresult *results, int act_field,
  				 const struct statement * stmt, struct variable * var);
--- 137,143 ----
  	struct variable *next;
  };
  
! struct descriptor *ECPGfind_desc(int line, const char *name);
  
  bool ECPGstore_result(const PGresult *results, int act_field,
  				 const struct statement * stmt, struct variable * var);
diff -cpr postgresql-snapshot/src/interfaces/ecpg/ecpglib/misc.c ecpg-descriptor-fix/src/interfaces/ecpg/ecpglib/misc.c
*** postgresql-snapshot/src/interfaces/ecpg/ecpglib/misc.c	2007-09-30 20:38:48.000000000 +0900
--- ecpg-descriptor-fix/src/interfaces/ecpg/ecpglib/misc.c	2007-10-02 13:51:04.000000000 +0900
*************** DllMain(HANDLE module, DWORD reason, LPV
*** 431,436 ****
--- 431,437 ----
  		auto_mem_key_init();
  		ecpg_actual_connection_init();
  		ecpg_sqlca_key_init();
+ 		descriptor_key_init();
  	}
  	return TRUE;
  }
diff -cpr postgresql-snapshot/src/interfaces/ecpg/include/ecpg-pthread-win32.h ecpg-descriptor-fix/src/interfaces/ecpg/include/ecpg-pthread-win32.h
*** postgresql-snapshot/src/interfaces/ecpg/include/ecpg-pthread-win32.h	2007-09-30 20:38:48.000000000 +0900
--- ecpg-descriptor-fix/src/interfaces/ecpg/include/ecpg-pthread-win32.h	2007-10-02 13:51:04.000000000 +0900
*************** extern pthread_mutex_t	debug_init_mutex;
*** 47,52 ****
--- 47,53 ----
  extern void auto_mem_key_init(void);
  extern void ecpg_actual_connection_init(void);
  extern void ecpg_sqlca_key_init(void);
+ extern void descriptor_key_init(void);
  extern BOOL WINAPI DllMain(HANDLE module, DWORD reason, LPVOID reserved);
  
  #endif	/* WIN32 */