diff --git a/configure.in b/configure.in
index 9ae42b36e418464a7d7144f82bf1143588bf3422..53e48a3fe08407a2ee5db59668904cf8862d74a4 100644
--- a/configure.in
+++ b/configure.in
@@ -1,5 +1,5 @@
 dnl Process this file with autoconf to produce a configure script.
-dnl $Header: /cvsroot/pgsql/configure.in,v 1.264 2003/06/14 19:21:42 momjian Exp $
+dnl $Header: /cvsroot/pgsql/configure.in,v 1.265 2003/06/15 04:07:58 momjian Exp $
 dnl
 dnl Developers, please strive to achieve this order:
 dnl
@@ -323,8 +323,8 @@ IFS=$ac_save_IFS
 # Enable libpq to be thread-safe
 #
 AC_MSG_CHECKING([allow threaded libpq])
-PGAC_ARG_BOOL(with, threads, no, [  --with-threads          allow libpq to be thread-safe],
-              [AC_DEFINE([USE_THREADS], 1, [Define to 1 to build libpq with threads. (--with-threads)])])
+PGAC_ARG_BOOL(with, threads, no, [  --with-threads          allow libpq and ecpg to be thread-safe],
+              [AC_DEFINE([USE_THREADS], 1, [Define to 1 to build libpq and ecpg to be thread-safe. (--with-threads)])])
 
 AC_MSG_RESULT([$with_threads])
 AC_SUBST(with_threads)
diff --git a/doc/src/sgml/ecpg.sgml b/doc/src/sgml/ecpg.sgml
index 8cb4874912ddf99c6f6f7e3b5738adaf19194b7c..d1d36db188d2c93b67086288e60af3c161928346 100644
--- a/doc/src/sgml/ecpg.sgml
+++ b/doc/src/sgml/ecpg.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/ecpg.sgml,v 1.43 2003/03/25 16:15:35 petere Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/ecpg.sgml,v 1.44 2003/06/15 04:07:58 momjian Exp $
 -->
 
 <chapter id="ecpg">
@@ -749,6 +749,13 @@ EXEC SQL INCLUDE <replaceable>filename</replaceable>;
    in the arguments specified for output.
   </para>
 
+  <para>
+   <application>ecpg</application> is thread-safe if it is compiled using
+   the <literal>--with-threads</> <filename>configure</filename>
+   command-line option.  (You might need to use other threading
+   command-line options to compile your client code.)
+  </para>
+
   <para>
    The preprocessor program is called <filename>ecpg</filename> and is
    included in a normal <productname>PostgreSQL</> installation.
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index 4c7a0a35176ca5ea702c2c4cf512988fb57827cc..e5d78e7ad83151ee9cc26a845f6082767cba211f 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -1,4 +1,4 @@
-<!-- $Header: /cvsroot/pgsql/doc/src/sgml/installation.sgml,v 1.134 2003/06/13 23:10:07 momjian Exp $ -->
+<!-- $Header: /cvsroot/pgsql/doc/src/sgml/installation.sgml,v 1.135 2003/06/15 04:07:58 momjian Exp $ -->
 
 <chapter id="installation">
  <title><![%standalone-include[<productname>PostgreSQL</>]]>
@@ -918,7 +918,8 @@ JAVACMD=$JAVA_HOME/bin/java
        <term><option>--with-threads</option></term>
        <listitem>
         <para>
-	 Allow separate libpq threads to safely control their private connection handles.
+	 Allow separate libpq and ecpg threads to safely control their
+         private connection handles.
         </para>
        </listitem>
       </varlistentry>
diff --git a/src/interfaces/ecpg/ecpglib/Makefile b/src/interfaces/ecpg/ecpglib/Makefile
index 269f2d1461329f210ea8d51b7bd4fecf445dc627..68f1a2273d176afadeb6e81a94ef7d3f0cdf7bca 100644
--- a/src/interfaces/ecpg/ecpglib/Makefile
+++ b/src/interfaces/ecpg/ecpglib/Makefile
@@ -4,7 +4,7 @@
 #
 # Copyright (c) 1994, Regents of the University of California
 #
-# $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/Makefile,v 1.3 2003/05/22 17:20:44 petere Exp $
+# $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/Makefile,v 1.4 2003/06/15 04:07:58 momjian Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -13,15 +13,15 @@ top_builddir = ../../../..
 include $(top_builddir)/src/Makefile.global
 
 NAME= ecpg
-SO_MAJOR_VERSION= 3
-SO_MINOR_VERSION= 4.2
+SO_MAJOR_VERSION= 4
+SO_MINOR_VERSION= 1.1
 
-override CPPFLAGS := -I$(top_srcdir)/src/interfaces/ecpg/include -I$(libpq_srcdir) $(CPPFLAGS)
+override CPPFLAGS := -I$(top_srcdir)/src/interfaces/ecpg/include -I$(libpq_srcdir) $(CPPFLAGS) $(THREAD_CFLAGS) 
 
 OBJS= execute.o typename.o descriptor.o data.o error.o prepare.o memory.o \
 	connect.o misc.o
 
-SHLIB_LINK = -L../pgtypeslib -lpgtypes $(libpq)
+SHLIB_LINK = -L../pgtypeslib -lpgtypes $(libpq) $(THREAD_LIBS)
 
 all: all-lib
 
diff --git a/src/interfaces/ecpg/ecpglib/connect.c b/src/interfaces/ecpg/ecpglib/connect.c
index 61e078da901a39f66d3149f71473dae2b6eecef0..58692a1b1be86a0a27060c7032940ce6172a0ec8 100644
--- a/src/interfaces/ecpg/ecpglib/connect.c
+++ b/src/interfaces/ecpg/ecpglib/connect.c
@@ -1,29 +1,53 @@
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/connect.c,v 1.6 2003/06/13 10:50:57 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/connect.c,v 1.7 2003/06/15 04:07:58 momjian Exp $ */
 
+#define POSTGRES_ECPG_INTERNAL
 #include "postgres_fe.h"
 
+#ifdef USE_THREADS
+#include <pthread.h>
+#endif
 #include "ecpgtype.h"
 #include "ecpglib.h"
 #include "ecpgerrno.h"
 #include "extern.h"
 #include "sqlca.h"
 
-static struct connection *all_connections = NULL,
-		   *actual_connection = NULL;
+#ifdef USE_THREADS
+static pthread_mutex_t connections_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+static struct connection *all_connections   = NULL;
+static struct connection *actual_connection = NULL;
 
 struct connection *
 ECPGget_connection(const char *connection_name)
 {
-	struct connection *con = all_connections;
+  struct connection *ret = NULL;
+
+#ifdef USE_THREADS
+  pthread_mutex_lock(&connections_mutex);
+#endif
+
+  if( (connection_name == NULL) || (strcmp(connection_name, "CURRENT") == 0) )
+    {
+      ret = actual_connection;
+    }
+  else
+    {
+      struct connection *con;
+      
+      for( con = all_connections; con != NULL; con = con->next)
+	{
+	  if( strcmp(connection_name, con->name) == 0 )
+	    break;
+	}
+      ret = con;
+    }
 
-	if (connection_name == NULL || strcmp(connection_name, "CURRENT") == 0)
-		return actual_connection;
+#ifdef USE_THREADS
+  pthread_mutex_unlock(&connections_mutex);
+#endif
 
-	for (; con && strcmp(connection_name, con->name) != 0; con = con->next);
-	if (con)
-		return con;
-	else
-		return NULL;
+  return( ret );
 }
 
 static void
@@ -37,6 +61,10 @@ ecpg_finish(struct connection * act)
 		ECPGlog("ecpg_finish: finishing %s.\n", act->name);
 		PQfinish(act->connection);
 
+		/* no need to lock connections_mutex - we're always called
+		   by ECPGdisconnect or ECPGconnect, which are holding
+		   the lock */
+
 		/* remove act from the list */
 		if (act == all_connections)
 			all_connections = act->next;
@@ -118,17 +146,18 @@ ECPGsetconn(int lineno, const char *connection_name)
 static void
 ECPGnoticeProcessor_raise(int code, const char *message)
 {
-	sqlca.sqlcode = code;
-	strncpy(sqlca.sqlerrm.sqlerrmc, message, sizeof(sqlca.sqlerrm.sqlerrmc));
-	sqlca.sqlerrm.sqlerrmc[sizeof(sqlca.sqlerrm.sqlerrmc) - 1] = 0;
-	sqlca.sqlerrm.sqlerrml = strlen(sqlca.sqlerrm.sqlerrmc);
+	struct sqlca_t *sqlca = ECPGget_sqlca();
+	sqlca->sqlcode = code;
+	strncpy(sqlca->sqlerrm.sqlerrmc, message, sizeof(sqlca->sqlerrm.sqlerrmc));
+	sqlca->sqlerrm.sqlerrmc[sizeof(sqlca->sqlerrm.sqlerrmc) - 1] = 0;
+	sqlca->sqlerrm.sqlerrml = strlen(sqlca->sqlerrm.sqlerrmc);
 
 	/* remove trailing newline */
-	if (sqlca.sqlerrm.sqlerrml
-		&& sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml - 1] == '\n')
+	if (sqlca->sqlerrm.sqlerrml
+		&& sqlca->sqlerrm.sqlerrmc[sqlca->sqlerrm.sqlerrml - 1] == '\n')
 	{
-		sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml - 1] = 0;
-		sqlca.sqlerrm.sqlerrml--;
+		sqlca->sqlerrm.sqlerrmc[sqlca->sqlerrm.sqlerrml - 1] = 0;
+		sqlca->sqlerrm.sqlerrml--;
 	}
 
 	ECPGlog("raising sqlcode %d\n", code);
@@ -141,6 +170,8 @@ ECPGnoticeProcessor_raise(int code, const char *message)
 static void
 ECPGnoticeProcessor(void *arg, const char *message)
 {
+	struct sqlca_t *sqlca = ECPGget_sqlca();
+
 	/* these notices raise an error */
 	if (strncmp(message, "WARNING: ", 9))
 	{
@@ -245,7 +276,7 @@ ECPGnoticeProcessor(void *arg, const char *message)
 	if (strstr(message, "cannot be rolled back"))
 		return;
 
-	/* these and other unmentioned should set sqlca.sqlwarn[2] */
+	/* these and other unmentioned should set sqlca->sqlwarn[2] */
 	/* WARNING: The ':' operator is deprecated.  Use exp(x) instead. */
 	/* WARNING: Rel *: Uninitialized page 0 - fixing */
 	/* WARNING: PortalHeapMemoryFree: * not in alloc set! */
@@ -253,14 +284,15 @@ ECPGnoticeProcessor(void *arg, const char *message)
 	/* WARNING: identifier "*" will be truncated to "*" */
 	/* WARNING: InvalidateSharedInvalid: cache state reset */
 	/* WARNING: RegisterSharedInvalid: SI buffer overflow */
-	sqlca.sqlwarn[2] = 'W';
-	sqlca.sqlwarn[0] = 'W';
+	sqlca->sqlwarn[2] = 'W';
+	sqlca->sqlwarn[0] = 'W';
 }
 
 /* this contains some quick hacks, needs to be cleaned up, but it works */
 bool
 ECPGconnect(int lineno, const char *name, const char *user, const char *passwd, const char *connection_name, int autocommit)
 {
+	struct sqlca_t *sqlca = ECPGget_sqlca();
 	struct connection *this;
 	char	   *dbname = strdup(name),
 			   *host = NULL,
@@ -269,7 +301,7 @@ ECPGconnect(int lineno, const char *name, const char *user, const char *passwd,
 			   *realname = NULL,
 			   *options = NULL;
 
-	ECPGinit_sqlca();
+	ECPGinit_sqlca(sqlca);
 
 	if ((this = (struct connection *) ECPGalloc(sizeof(struct connection), lineno)) == NULL)
 		return false;
@@ -394,6 +426,9 @@ ECPGconnect(int lineno, const char *name, const char *user, const char *passwd,
 		realname = strdup(dbname);
 
 	/* add connection to our list */
+#ifdef USE_THREADS
+	pthread_mutex_lock(&connections_mutex);
+#endif
 	if (connection_name != NULL)
 		this->name = ECPGstrdup(connection_name, lineno);
 	else
@@ -424,6 +459,9 @@ ECPGconnect(int lineno, const char *name, const char *user, const char *passwd,
 
         set_backend_err(errmsg, lineno);
 		ecpg_finish(this);
+#ifdef USE_THREADS
+		pthread_mutex_unlock(&connections_mutex);
+#endif
 		ECPGlog("connect: could not open database %s on %s port %s %s%s%s%s in line %d\n\t%s\n",
                 db,
 				host ? host : "<DEFAULT>",
@@ -445,6 +483,9 @@ ECPGconnect(int lineno, const char *name, const char *user, const char *passwd,
 			ECPGfree(dbname);
 		return false;
 	}
+#ifdef USE_THREADS
+	pthread_mutex_unlock(&connections_mutex);
+#endif
 
 	if (host)
 		ECPGfree(host);
@@ -468,11 +509,16 @@ ECPGconnect(int lineno, const char *name, const char *user, const char *passwd,
 bool
 ECPGdisconnect(int lineno, const char *connection_name)
 {
+	struct sqlca_t *sqlca = ECPGget_sqlca();
 	struct connection *con;
 
+#ifdef USE_THREADS
+	pthread_mutex_lock(&connections_mutex);
+#endif
+
 	if (strcmp(connection_name, "ALL") == 0)
 	{
-		ECPGinit_sqlca();
+		ECPGinit_sqlca(sqlca);
 		for (con = all_connections; con;)
 		{
 			struct connection *f = con;
@@ -486,10 +532,19 @@ ECPGdisconnect(int lineno, const char *connection_name)
 		con = ECPGget_connection(connection_name);
 
 		if (!ECPGinit(con, connection_name, lineno))
-			return (false);
+		  {
+#ifdef USE_THREADS
+		    pthread_mutex_unlock(&connections_mutex);
+#endif
+		    return (false);
+		  }
 		else
-			ecpg_finish(con);
+		  ecpg_finish(con);
 	}
 
+#ifdef USE_THREADS
+	pthread_mutex_unlock(&connections_mutex);
+#endif
+
 	return true;
 }
diff --git a/src/interfaces/ecpg/ecpglib/data.c b/src/interfaces/ecpg/ecpglib/data.c
index cae1c500d9b9bc431ba3bc80f1298bc76de9ab46..8105f3a6cf379931468a695fdd68090789f3f0fb 100644
--- a/src/interfaces/ecpg/ecpglib/data.c
+++ b/src/interfaces/ecpg/ecpglib/data.c
@@ -1,5 +1,6 @@
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/data.c,v 1.4 2003/04/01 14:37:25 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/data.c,v 1.5 2003/06/15 04:07:58 momjian Exp $ */
 
+#define POSTGRES_ECPG_INTERNAL
 #include "postgres_fe.h"
 
 #include <stdlib.h>
@@ -21,6 +22,7 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 			 char *var, char *ind, long varcharsize, long offset,
 			 long ind_offset, bool isarray)
 {
+	struct sqlca_t *sqlca = ECPGget_sqlca();
 	char	   *pval = (char *) PQgetvalue(results, act_tuple, act_field);
 
 	ECPGlog("ECPGget_data line %d: RESULT: %s offset: %ld\n", lineno, pval ? pval : "", offset);
@@ -328,7 +330,7 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 							default:
 								break;
 						}
-						sqlca.sqlwarn[0] = sqlca.sqlwarn[1] = 'W';
+						sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
 					}
 				}
 				break;
@@ -373,7 +375,7 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 							default:
 								break;
 						}
-						sqlca.sqlwarn[0] = sqlca.sqlwarn[1] = 'W';
+						sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
 
 						variable->len = varcharsize;
 					}
diff --git a/src/interfaces/ecpg/ecpglib/descriptor.c b/src/interfaces/ecpg/ecpglib/descriptor.c
index 0a5e5a71957d61c02385b32210dd08e39736264c..ade737beeaee1fbe37decfc31c5acfc20103f040 100644
--- a/src/interfaces/ecpg/ecpglib/descriptor.c
+++ b/src/interfaces/ecpg/ecpglib/descriptor.c
@@ -1,8 +1,9 @@
 /* dynamic SQL support routines
  *
- * $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/descriptor.c,v 1.2 2003/05/30 13:22:02 meskes Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/descriptor.c,v 1.3 2003/06/15 04:07:58 momjian Exp $
  */
 
+#define POSTGRES_ECPG_INTERNAL
 #include "postgres_fe.h"
 #include "pg_type.h"
 
@@ -51,14 +52,15 @@ bool
 ECPGget_desc_header(int lineno, char *desc_name, int *count)
 {
 	PGresult   *ECPGresult;
+	struct sqlca_t *sqlca = ECPGget_sqlca();
 
-	ECPGinit_sqlca();
+	ECPGinit_sqlca(sqlca);
 	ECPGresult = ECPGresultByDescriptor(lineno, desc_name);
 	if (!ECPGresult)
 		return false;
 
 	*count = PQnfields(ECPGresult);
-	sqlca.sqlerrd[2] = 1;
+	sqlca->sqlerrd[2] = 1;
 	ECPGlog("ECPGget_desc_header: found %d attributes.\n", *count);
 	return true;
 }
@@ -149,9 +151,10 @@ ECPGget_desc(int lineno, char *desc_name, int index,...)
 	int			ntuples,
 				act_tuple;
 	struct variable data_var;
+	struct sqlca_t *sqlca = ECPGget_sqlca();
 
 	va_start(args, index);
-	ECPGinit_sqlca();
+	ECPGinit_sqlca(sqlca);
 	ECPGresult = ECPGresultByDescriptor(lineno, desc_name);
 	if (!ECPGresult)
 		return (false);
@@ -378,7 +381,7 @@ ECPGget_desc(int lineno, char *desc_name, int index,...)
 			ECPGlog("ECPGget_desc: INDICATOR[%d] = %d\n", act_tuple, -PQgetisnull(ECPGresult, act_tuple, index));
 		}
 	}
-	sqlca.sqlerrd[2] = ntuples;
+	sqlca->sqlerrd[2] = ntuples;
 	return (true);
 }
 
@@ -387,8 +390,9 @@ ECPGdeallocate_desc(int line, const char *name)
 {
 	struct descriptor *i;
 	struct descriptor **lastptr = &all_descriptors;
+	struct sqlca_t *sqlca = ECPGget_sqlca();
 
-	ECPGinit_sqlca();
+	ECPGinit_sqlca(sqlca);
 	for (i = all_descriptors; i; lastptr = &i->next, i = i->next)
 	{
 		if (!strcmp(name, i->name))
@@ -408,8 +412,9 @@ bool
 ECPGallocate_desc(int line, const char *name)
 {
 	struct descriptor *new;
+	struct sqlca_t *sqlca = ECPGget_sqlca();
 
-	ECPGinit_sqlca();
+	ECPGinit_sqlca(sqlca);
 	new = (struct descriptor *) ECPGalloc(sizeof(struct descriptor), line);
 	if (!new)
 		return false;
diff --git a/src/interfaces/ecpg/ecpglib/error.c b/src/interfaces/ecpg/ecpglib/error.c
index 578e7c56033192172cd034a54d71f7ac856e9482..2203b7214a283e1d9878ef6d320732899ae61bbf 100644
--- a/src/interfaces/ecpg/ecpglib/error.c
+++ b/src/interfaces/ecpg/ecpglib/error.c
@@ -1,5 +1,6 @@
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/error.c,v 1.1 2003/03/16 10:42:53 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/error.c,v 1.2 2003/06/15 04:07:58 momjian Exp $ */
 
+#define POSTGRES_ECPG_INTERNAL
 #include "postgres_fe.h"
 
 #include <stdio.h>
@@ -17,117 +18,118 @@ static char *ECPGerr;
 void
 ECPGraise(int line, int code, const char *str)
 {
-	sqlca.sqlcode = code;
+	struct sqlca_t *sqlca = ECPGget_sqlca();
+	sqlca->sqlcode = code;
 
 	switch (code)
 	{
 		case ECPG_NOT_FOUND:
-			snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
 					 "No data found in line %d.", line);
 			break;
 
 		case ECPG_OUT_OF_MEMORY:
-			snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
 					 "Out of memory in line %d.", line);
 			break;
 
 		case ECPG_UNSUPPORTED:
-			snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
 					 "Unsupported type %s in line %d.", str, line);
 			break;
 
 		case ECPG_TOO_MANY_ARGUMENTS:
-			snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
 					 "Too many arguments in line %d.", line);
 			break;
 
 		case ECPG_TOO_FEW_ARGUMENTS:
-			snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
 					 "Too few arguments in line %d.", line);
 			break;
 
 		case ECPG_INT_FORMAT:
-			snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
 			 "Not correctly formatted int type: %s line %d.", str, line);
 			break;
 
 		case ECPG_UINT_FORMAT:
-			snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
 					 "Not correctly formatted unsigned type: %s in line %d.", str, line);
 			break;
 
 		case ECPG_FLOAT_FORMAT:
-			snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
 					 "Not correctly formatted floating-point type: %s in line %d.", str, line);
 			break;
 
 		case ECPG_CONVERT_BOOL:
-			snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
 				  "Unable to convert %s to bool on line %d.", str, line);
 			break;
 
 		case ECPG_EMPTY:
-			snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
 					 "Empty query in line %d.", line);
 			break;
 
 		case ECPG_MISSING_INDICATOR:
-			snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
 					 "NULL value without indicator in line %d.", line);
 			break;
 
 		case ECPG_NO_ARRAY:
-			snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
 					 "Variable is not an array in line %d.", line);
 			break;
 
 		case ECPG_DATA_NOT_ARRAY:
-			snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
 			 "Data read from backend is not an array in line %d.", line);
 			break;
 
 		case ECPG_ARRAY_INSERT:
-			snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
 			 "Trying to insert an array of variables in line %d.", line);
 			break;
 
 		case ECPG_NO_CONN:
-			snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
 					 "No such connection %s in line %d.", str, line);
 			break;
 
 		case ECPG_NOT_CONN:
-			snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
 					 "Not connected to '%s' in line %d.", str, line);
 			break;
 
 		case ECPG_INVALID_STMT:
-			snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
 					 "Invalid statement name %s in line %d.", str, line);
 			break;
 
 		case ECPG_UNKNOWN_DESCRIPTOR:
-			snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
 					 "Descriptor %s not found in line %d.", str, line);
 			break;
 
 		case ECPG_INVALID_DESCRIPTOR_INDEX:
-			snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
 					 "Descriptor index out of range in line %d.", line);
 			break;
 
 		case ECPG_UNKNOWN_DESCRIPTOR_ITEM:
-			snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
 					 "Unknown descriptor item %s in line %d.", str, line);
 			break;
 
 		case ECPG_VAR_NOT_NUMERIC:
-			snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
 					 "Variable is not a numeric type in line %d.", line);
 			break;
 
 		case ECPG_VAR_NOT_CHAR:
-			snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
 				   "Variable is not a character type in line %d.", line);
 			break;
 
@@ -138,29 +140,29 @@ ECPGraise(int line, int code, const char *str)
 				/* strip trailing newline */
 				if (slen > 0 && str[slen - 1] == '\n')
 					slen--;
-				snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+				snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
 						 "'%.*s' in line %d.", slen, str, line);
 				break;
 			}
 
 		case ECPG_TRANS:
-			snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
 					 "Error in transaction processing in line %d.", line);
 			break;
 
 		case ECPG_CONNECT:
-			snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
 			  "Could not connect to database %s in line %d.", str, line);
 			break;
 
 		default:
-			snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
+			snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
 					 "SQL error #%d in line %d.", code, line);
 			break;
 	}
 
-	sqlca.sqlerrm.sqlerrml = strlen(sqlca.sqlerrm.sqlerrmc);
-	ECPGlog("raising sqlcode %d in line %d, '%s'.\n", code, line, sqlca.sqlerrm.sqlerrmc);
+	sqlca->sqlerrm.sqlerrml = strlen(sqlca->sqlerrm.sqlerrmc);
+	ECPGlog("raising sqlcode %d in line %d, '%s'.\n", code, line, sqlca->sqlerrm.sqlerrmc);
 
 	/* free all memory we have allocated for the user */
 	ECPGfree_auto_mem();
@@ -193,6 +195,8 @@ ECPGerrmsg(void)
 void
 sqlprint(void)
 {
-	sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml] = '\0';
-	fprintf(stderr, "sql error %s\n", sqlca.sqlerrm.sqlerrmc);
+	struct sqlca_t *sqlca = ECPGget_sqlca();
+
+	sqlca->sqlerrm.sqlerrmc[sqlca->sqlerrm.sqlerrml] = '\0';
+	fprintf(stderr, "sql error %s\n", sqlca->sqlerrm.sqlerrmc);
 }
diff --git a/src/interfaces/ecpg/ecpglib/execute.c b/src/interfaces/ecpg/ecpglib/execute.c
index 03d1fbd646aa285ff3662c465deb742035fac4f1..108bbe05aba6bcbc12802045b3da5d97df7617c4 100644
--- a/src/interfaces/ecpg/ecpglib/execute.c
+++ b/src/interfaces/ecpg/ecpglib/execute.c
@@ -1,4 +1,4 @@
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.9 2003/06/13 10:50:57 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.10 2003/06/15 04:07:58 momjian Exp $ */
 
 /*
  * The aim is to get a simpler inteface to the database routines.
@@ -13,6 +13,7 @@
 /* Taken over as part of PostgreSQL by Michael Meskes <meskes@postgresql.org>
    on Feb. 5th, 1998 */
 
+#define POSTGRES_ECPG_INTERNAL
 #include "postgres_fe.h"
 
 #include <stdio.h>
@@ -31,34 +32,6 @@
 #include "pgtypes_timestamp.h"
 #include "pgtypes_interval.h"
 
-/* variables visible to the programs */
-struct sqlca sqlca =
-{
-	{
-		'S', 'Q', 'L', 'C', 'A', ' ', ' ', ' '
-	},
-	sizeof(struct sqlca),
-	0,
-	{
-		0,
-		{
-			0
-		}
-	},
-	{
-		'N', 'O', 'T', ' ', 'S', 'E', 'T', ' '
-	},
-	{
-		0, 0, 0, 0, 0, 0
-	},
-	{
-		0, 0, 0, 0, 0, 0, 0, 0
-	},
-	{
-		0, 0, 0, 0, 0, 0, 0, 0
-	}
-};
-
 /* This function returns a newly malloced string that has the  \
    in the argument quoted with \ and the ' quoted with ' as SQL92 says.
  */
@@ -1130,6 +1103,8 @@ ECPGexecute(struct statement * stmt)
 		 */
 	{
 		bool		clear_result = TRUE;
+		struct sqlca_t *sqlca = ECPGget_sqlca();
+
 		errmsg = PQresultErrorMessage(results);
 		set_backend_err(errmsg, stmt->lineno);
 		
@@ -1142,7 +1117,7 @@ ECPGexecute(struct statement * stmt)
 
 			case PGRES_TUPLES_OK:
 				nfields = PQnfields(results);
-				sqlca.sqlerrd[2] = ntuples = PQntuples(results);
+				sqlca->sqlerrd[2] = ntuples = PQntuples(results);
 				status = true;
 
 				if (ntuples < 1)
@@ -1199,10 +1174,10 @@ ECPGexecute(struct statement * stmt)
 			case PGRES_COMMAND_OK:
 				status = true;
 				cmdstat = PQcmdStatus(results);
-				sqlca.sqlerrd[1] = PQoidValue(results);
-				sqlca.sqlerrd[2] = atol(PQcmdTuples(results));
+				sqlca->sqlerrd[1] = PQoidValue(results);
+				sqlca->sqlerrd[2] = atol(PQcmdTuples(results));
 				ECPGlog("ECPGexecute line %d Ok: %s\n", stmt->lineno, cmdstat);
-				if (!sqlca.sqlerrd[2] && (   !strncmp(cmdstat, "UPDATE", 6)
+				if (!sqlca->sqlerrd[2] && (   !strncmp(cmdstat, "UPDATE", 6)
 							  || !strncmp(cmdstat, "INSERT", 6)
 							  || !strncmp(cmdstat, "DELETE", 6)))
 					ECPGraise(stmt->lineno, ECPG_NOT_FOUND, NULL);
diff --git a/src/interfaces/ecpg/ecpglib/extern.h b/src/interfaces/ecpg/ecpglib/extern.h
index a5014512c9e01ff640dbeee9d869d799b9d1f5c5..a43526c7603bd4c8449d790f6a295606f074ccd9 100644
--- a/src/interfaces/ecpg/ecpglib/extern.h
+++ b/src/interfaces/ecpg/ecpglib/extern.h
@@ -3,6 +3,7 @@
 
 #include "postgres_fe.h"
 #include "libpq-fe.h"
+#include "sqlca.h"
 
 /* Here are some methods used by the lib. */
 
@@ -19,7 +20,6 @@ void		ECPGadd_mem(void *ptr, int lineno);
 bool ECPGget_data(const PGresult *, int, int, int, enum ECPGttype type,
 			 enum ECPGttype, char *, char *, long, long, long, bool);
 struct connection *ECPGget_connection(const char *);
-void		ECPGinit_sqlca(void);
 char	   *ECPGalloc(long, int);
 char	   *ECPGrealloc(void *, long, int);
 void		ECPGfree(void *);
diff --git a/src/interfaces/ecpg/ecpglib/memory.c b/src/interfaces/ecpg/ecpglib/memory.c
index a94b293de45bde5f973de00aa1452618f5c54984..1a5de833d1ce4ec1519bb2e60e0f682a070b8542 100644
--- a/src/interfaces/ecpg/ecpglib/memory.c
+++ b/src/interfaces/ecpg/ecpglib/memory.c
@@ -1,5 +1,6 @@
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/memory.c,v 1.1 2003/03/16 10:42:53 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/memory.c,v 1.2 2003/06/15 04:07:58 momjian Exp $ */
 
+#define POSTGRES_ECPG_INTERNAL
 #include "postgres_fe.h"
 
 #include "ecpgtype.h"
diff --git a/src/interfaces/ecpg/ecpglib/misc.c b/src/interfaces/ecpg/ecpglib/misc.c
index 48223d05689552f485c3611d7192e0d81c79467e..5c5128dcef40a02c968983c3104a21d7e424e807 100644
--- a/src/interfaces/ecpg/ecpglib/misc.c
+++ b/src/interfaces/ecpg/ecpglib/misc.c
@@ -1,20 +1,24 @@
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/misc.c,v 1.2 2003/03/21 15:31:04 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/misc.c,v 1.3 2003/06/15 04:07:58 momjian Exp $ */
 
+#define POSTGRES_ECPG_INTERNAL
 #include "postgres_fe.h"
 
 #include <unistd.h>
+#ifdef USE_THREADS
+#include <pthread.h>
+#endif
 #include "ecpgtype.h"
 #include "ecpglib.h"
 #include "ecpgerrno.h"
 #include "extern.h"
 #include "sqlca.h"
 
-static struct sqlca sqlca_init =
+static struct sqlca_t sqlca_init =
 {
 	{
 		'S', 'Q', 'L', 'C', 'A', ' ', ' ', ' '
 	},
-	sizeof(struct sqlca),
+	sizeof(struct sqlca_t),
 	0,
 	{
 		0,
@@ -36,19 +40,54 @@ static struct sqlca sqlca_init =
 	}
 };
 
-static int	simple_debug = 0;
+#ifdef USE_THREADS
+static pthread_key_t   sqlca_key;
+static pthread_once_t  sqlca_key_once = PTHREAD_ONCE_INIT;
+#else
+static struct sqlca_t sqlca =
+{
+	{
+		'S', 'Q', 'L', 'C', 'A', ' ', ' ', ' '
+	},
+	sizeof(struct sqlca_t),
+	0,
+	{
+		0,
+		{
+			0
+		}
+	},
+	{
+		'N', 'O', 'T', ' ', 'S', 'E', 'T', ' '
+	},
+	{
+		0, 0, 0, 0, 0, 0
+	},
+	{
+		0, 0, 0, 0, 0, 0, 0, 0
+	},
+	{
+		0, 0, 0, 0, 0, 0, 0, 0
+	}
+};
+#endif
+
+#ifdef USE_THREADS
+static pthread_mutex_t debug_mutex    = PTHREAD_MUTEX_INITIALIZER;
+#endif
+static int simple_debug = 0;
 static FILE *debugstream = NULL;
 
-void
-ECPGinit_sqlca(void)
+void ECPGinit_sqlca(struct sqlca_t *sqlca)
 {
-	memcpy((char *) &sqlca, (char *) &sqlca_init, sizeof(sqlca));
+	memcpy((char *)sqlca, (char *)&sqlca_init, sizeof(struct sqlca_t));
 }
 
 bool
 ECPGinit(const struct connection * con, const char *connection_name, const int lineno)
 {
-	ECPGinit_sqlca();
+	struct sqlca_t *sqlca = ECPGget_sqlca();
+	ECPGinit_sqlca(sqlca);
 	if (con == NULL)
 	{
 		ECPGraise(lineno, ECPG_NO_CONN, connection_name ? connection_name : "NULL");
@@ -58,6 +97,33 @@ ECPGinit(const struct connection * con, const char *connection_name, const int l
 	return (true);
 }
 
+#ifdef USE_THREADS
+static void ecpg_sqlca_key_init(void)
+{
+  pthread_key_create(&sqlca_key, NULL);
+}
+#endif
+
+struct sqlca_t *ECPGget_sqlca(void)
+{
+#ifdef USE_THREADS
+  struct sqlca_t *sqlca;
+
+  pthread_once(&sqlca_key_once, ecpg_sqlca_key_init);
+
+  sqlca = pthread_getspecific(&sqlca_key);
+  if( sqlca == NULL )
+    {
+      sqlca = malloc(sizeof(struct sqlca_t));
+      ECPGinit_sqlca(sqlca);
+      pthread_setspecific(&sqlca_key, sqlca);
+    }
+  return( sqlca );
+#else
+  return( &sqlca );
+#endif
+}
+
 bool
 ECPGstatus(int lineno, const char *connection_name)
 {
@@ -123,9 +189,17 @@ ECPGtrans(int lineno, const char *connection_name, const char *transaction)
 void
 ECPGdebug(int n, FILE *dbgs)
 {
+#ifdef USE_THREADS
+	pthread_mutex_lock(&debug_mutex);
+#endif
+
 	simple_debug = n;
 	debugstream = dbgs;
 	ECPGlog("ECPGdebug: set to %d\n", simple_debug);
+
+#ifdef USE_THREADS
+	pthread_mutex_unlock(&debug_mutex);
+#endif
 }
 
 void
@@ -133,12 +207,20 @@ ECPGlog(const char *format,...)
 {
 	va_list		ap;
 
-	if (simple_debug)
-	{
-		char	   *f = (char *) malloc(strlen(format) + 100);
+#ifdef USE_THREADS
+	pthread_mutex_lock(&debug_mutex);
+#endif
 
-		if (!f)
+	if( simple_debug )
+	{
+		char *f = (char *)malloc(strlen(format) + 100);
+		if( f == NULL )
+		  {
+#ifdef USE_THREADS
+			pthread_mutex_unlock(&debug_mutex);
+#endif
 			return;
+		  }
 
 		sprintf(f, "[%d]: %s", (int) getpid(), format);
 
@@ -148,4 +230,8 @@ ECPGlog(const char *format,...)
 
 		ECPGfree(f);
 	}
+
+#ifdef USE_THREADS
+	pthread_mutex_unlock(&debug_mutex);
+#endif
 }
diff --git a/src/interfaces/ecpg/ecpglib/prepare.c b/src/interfaces/ecpg/ecpglib/prepare.c
index 13dd2408f26db09274e11570adae5c9e65c002d5..7de8367184c5a3c5f3524bbff5a3a001e0e2cd91 100644
--- a/src/interfaces/ecpg/ecpglib/prepare.c
+++ b/src/interfaces/ecpg/ecpglib/prepare.c
@@ -1,5 +1,6 @@
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/prepare.c,v 1.1 2003/03/16 10:42:53 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/prepare.c,v 1.2 2003/06/15 04:07:58 momjian Exp $ */
 
+#define POSTGRES_ECPG_INTERNAL
 #include "postgres_fe.h"
 
 #include <ctype.h>
diff --git a/src/interfaces/ecpg/ecpglib/typename.c b/src/interfaces/ecpg/ecpglib/typename.c
index 684aa9cfc8a01d505879cb3f4bb8bde533ccd5da..c3293984715ec49208b4283d15f4990ac7b2d219 100644
--- a/src/interfaces/ecpg/ecpglib/typename.c
+++ b/src/interfaces/ecpg/ecpglib/typename.c
@@ -1,5 +1,6 @@
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/typename.c,v 1.3 2003/03/27 14:29:17 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/typename.c,v 1.4 2003/06/15 04:07:58 momjian Exp $ */
 
+#define POSTGRES_ECPG_INTERNAL
 #include "postgres_fe.h"
 
 #include <stdlib.h>
diff --git a/src/interfaces/ecpg/include/sqlca.h b/src/interfaces/ecpg/include/sqlca.h
index 7987eb0d3c879ac5734a78928411375483498b55..8af23921d78a8d66fea8f211e70be5427cfce5b9 100644
--- a/src/interfaces/ecpg/include/sqlca.h
+++ b/src/interfaces/ecpg/include/sqlca.h
@@ -16,7 +16,7 @@ extern		"C"
 {
 #endif
 
-struct sqlca
+struct sqlca_t
 {
 	char		sqlcaid[8];
 	long		sqlabc;
@@ -53,8 +53,11 @@ struct sqlca
 	char		sqlext[8];
 };
 
-extern DLLIMPORT struct sqlca sqlca;
+struct sqlca_t *ECPGget_sqlca(void);
 
+#ifndef POSTGRES_ECPG_INTERNAL
+# define sqlca (*ECPGget_sqlca())
+#endif
 
 #ifdef __cplusplus
 }
diff --git a/src/interfaces/ecpg/preproc/Makefile b/src/interfaces/ecpg/preproc/Makefile
index 5941c154fc655f3947fd39f8880375eb5c178713..7dd4e9375fee38ac8151dbf1a599f2f6d693a10c 100644
--- a/src/interfaces/ecpg/preproc/Makefile
+++ b/src/interfaces/ecpg/preproc/Makefile
@@ -1,11 +1,11 @@
-# $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/Makefile,v 1.91 2003/03/18 10:46:39 meskes Exp $
+# $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/Makefile,v 1.92 2003/06/15 04:07:58 momjian Exp $
 
 subdir = src/interfaces/ecpg/preproc
 top_builddir = ../../../..
 include $(top_builddir)/src/Makefile.global
 
-MAJOR_VERSION=2
-MINOR_VERSION=12
+MAJOR_VERSION=3
+MINOR_VERSION=0
 PATCHLEVEL=0
 
 override CPPFLAGS := -I$(srcdir)/../include -I$(srcdir) $(CPPFLAGS) \