diff --git a/src/interfaces/libpgtcl/Makefile.in b/src/interfaces/libpgtcl/Makefile.in
index 0905a8a7227b8c5027a4fc5dcb32ac48aad93632..92852a597042d70931983fbe6f1660cf01842607 100644
--- a/src/interfaces/libpgtcl/Makefile.in
+++ b/src/interfaces/libpgtcl/Makefile.in
@@ -7,7 +7,7 @@
 #
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/Makefile.in,v 1.3 1998/02/13 05:09:57 scrappy Exp $
+#    $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/Makefile.in,v 1.4 1998/03/15 08:02:55 scrappy Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -37,7 +37,7 @@ ifeq ($(PORTNAME), linux)
     install-shlib-dep	:= install-shlib
     shlib		:= libpgtcl.so.1
     CFLAGS		+= $(CFLAGS_SL)
-    LDFLAGS_SL		= -shared -L $(SRCDIR)/interfaces/libpq -lpq
+    LDFLAGS_SL		= -shared -L$(SRCDIR)/interfaces/libpq -lpq
   endif
 endif
 
@@ -53,14 +53,14 @@ endif
 ifeq ($(PORTNAME), i386_solaris)
   install-shlib-dep	:= install-shlib
   shlib			:= libpgtcl.so.1
-  LDFLAGS_SL		= -G -z text -L $(SRCDIR)/interfaces/libpq -lpq
+  LDFLAGS_SL		= -G -z text -L$(SRCDIR)/interfaces/libpq -lpq
   CFLAGS		+= $(CFLAGS_SL)
 endif
 
 ifeq ($(PORTNAME), univel)
   install-shlib-dep	:= install-shlib
   shlib			:= libpgtcl.so.1
-  LDFLAGS_SL		= -G -z text -L $(SRCDIR)/interfaces/libpq -lpq
+  LDFLAGS_SL		= -G -z text -L$(SRCDIR)/interfaces/libpq -lpq
   CFLAGS		+= $(CFLAGS_SL)
 endif
 
diff --git a/src/interfaces/libpgtcl/README b/src/interfaces/libpgtcl/README
index b17416bf90f9fe9f66d92b05cfd7116f3599a7c6..c672405955de19005a3b868307a4aef4236d70ed 100644
--- a/src/interfaces/libpgtcl/README
+++ b/src/interfaces/libpgtcl/README
@@ -1,6 +1,38 @@
-libpgtcl is a library that implements Tcl commands for front-end clients
-to interact with the PostgreSQL backend.  See libpgtcl.doc for details.
-
+libpgtcl is a library that implements Tcl commands for front-end
+clients to interact with the Postgresql 6.3 (and perhaps later)
+backends.  See libpgtcl.doc for details.
+  
 For an example of how to build a new tclsh to use libpgtcl, see the
 directory ../bin/pgtclsh
 
+Note this version is modified by NeoSoft to have the following additional
+features:
+
+1. Postgres connections are a valid Tcl channel, and can therefore
+   be manipulated by the interp command (ie. shared or transfered).
+   A connection handle's results are transfered/shared with it.
+   (Result handles are NOT channels, though it was tempting).  Note
+   that a "close $connection" is now functionally identical to a
+   "pg_disconnect $connection", although pg_connect must be used
+   to create a connection.
+   
+2. Result handles are changed in format: ${connection}.<result#>.
+   This just means for a connection 'pgtcl0', they look like pgtcl0.0,
+   pgtcl0.1, etc.  Enforcing this syntax makes it easy to look up
+   the real pointer by indexing into an array associated with the
+   connection.
+
+3. I/O routines are now defined for the connection handle.  I/O to/from
+   the connection is only valid under certain circumstances: following
+   the execution of the queries "copy <table> from stdin" or
+   "copy <table> to stdout".  In these cases, the result handle obtains
+   an intermediate status of "PGRES_COPY_IN" or "PGRES_COPY_OUT".  The
+   programmer is then expected to use Tcl gets or read commands on the
+   database connection (not the result handle) to extract the copy data.
+   For copy outs, read until the standard EOF indication is encountered.
+   For copy ins, puts a single terminator (\.).  The statement for this
+   would be
+	puts $conn "\\."      or       puts $conn {\.}
+   In either case (upon detecting the EOF or putting the `\.', the status
+   of the result handle will change to "PGRES_COMMAND_OK", and any further
+   I/O attempts will cause a Tcl error.
diff --git a/src/interfaces/libpgtcl/pgtcl.c b/src/interfaces/libpgtcl/pgtcl.c
index e8502da5c24e1a5edd541db8917f7ac2eaf4d022..a90c0c7c4908e759aa360f8b057849df94779014 100644
--- a/src/interfaces/libpgtcl/pgtcl.c
+++ b/src/interfaces/libpgtcl/pgtcl.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtcl.c,v 1.9 1997/09/08 02:40:08 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtcl.c,v 1.10 1998/03/15 08:02:57 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -23,163 +23,122 @@
 #include "pgtclId.h"
 
 /*
- * Pgtcl_Init
- *	  initialization package for the PGLITE Tcl package
+ * Pgtcl_Init 
+ *    initialization package for the PGLITE Tcl package
  *
  */
 
-/*
- * Tidy up forgotten postgres connection at Tcl_Exit
- */
-static void
-Pgtcl_AtExit(ClientData cData)
-{
-	Pg_clientData *cd = (Pg_clientData *) cData;
-	Tcl_HashEntry *hent;
-	Tcl_HashSearch hsearch;
-	Pg_ConnectionId *connid;
-	PGconn	   *conn;
-
-	while ((hent = Tcl_FirstHashEntry(&(cd->dbh_hash), &hsearch)) != NULL)
-	{
-		connid = (Pg_ConnectionId *) Tcl_GetHashValue(hent);
-		conn = connid->conn;
-		PgDelConnectionId(cd, connid->id);
-		PQfinish(conn);
-	}
-
-	Tcl_DeleteHashTable(&(cd->dbh_hash));
-	Tcl_DeleteHashTable(&(cd->res_hash));
-	Tcl_DeleteHashTable(&(cd->notify_hash));
-
-	Tcl_DeleteExitHandler(Pgtcl_AtExit, cData);
-}
-
-/*
- * Tidy up forgotten postgres connections on Interpreter deletion
- */
-static void
-Pgtcl_Shutdown(ClientData cData, Tcl_Interp * interp)
-{
-	Pgtcl_AtExit(cData);
-}
-
 int
-Pgtcl_Init(Tcl_Interp * interp)
+Pgtcl_Init (Tcl_Interp *interp)
 {
-	Pg_clientData *cd;
-
-	/* Create and initialize the client data area */
-	cd = (Pg_clientData *) ckalloc(sizeof(Pg_clientData));
-	Tcl_InitHashTable(&(cd->dbh_hash), TCL_STRING_KEYS);
-	Tcl_InitHashTable(&(cd->res_hash), TCL_STRING_KEYS);
-	Tcl_InitHashTable(&(cd->notify_hash), TCL_STRING_KEYS);
-	cd->dbh_count = 0L;
-	cd->res_count = 0L;
-
-	/* Arrange for tidy up when interpreter is deleted or Tcl exits */
-	Tcl_CallWhenDeleted(interp, Pgtcl_Shutdown, (ClientData) cd);
-	Tcl_CreateExitHandler(Pgtcl_AtExit, (ClientData) cd);
-
-	/* register all pgtcl commands */
-	Tcl_CreateCommand(interp,
-					  "pg_conndefaults",
-					  Pg_conndefaults,
-					  (ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
-
-	Tcl_CreateCommand(interp,
-					  "pg_connect",
-					  Pg_connect,
-					  (ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
-
-	Tcl_CreateCommand(interp,
-					  "pg_disconnect",
-					  Pg_disconnect,
-					  (ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
-
-	Tcl_CreateCommand(interp,
-					  "pg_exec",
-					  Pg_exec,
-					  (ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
-
-	Tcl_CreateCommand(interp,
-					  "pg_select",
-					  Pg_select,
-					  (ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
-
-	Tcl_CreateCommand(interp,
-					  "pg_result",
-					  Pg_result,
-					  (ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
-
-	Tcl_CreateCommand(interp,
-					  "pg_lo_open",
-					  Pg_lo_open,
-					  (ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
-
-	Tcl_CreateCommand(interp,
-					  "pg_lo_close",
-					  Pg_lo_close,
-					  (ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
-
-	Tcl_CreateCommand(interp,
-					  "pg_lo_read",
-					  Pg_lo_read,
-					  (ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
-
-	Tcl_CreateCommand(interp,
-					  "pg_lo_write",
-					  Pg_lo_write,
-					  (ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
-
-	Tcl_CreateCommand(interp,
-					  "pg_lo_lseek",
-					  Pg_lo_lseek,
-					  (ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
-
-	Tcl_CreateCommand(interp,
-					  "pg_lo_creat",
-					  Pg_lo_creat,
-					  (ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
-
-	Tcl_CreateCommand(interp,
-					  "pg_lo_tell",
-					  Pg_lo_tell,
-					  (ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
-
-	Tcl_CreateCommand(interp,
-					  "pg_lo_unlink",
-					  Pg_lo_unlink,
-					  (ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
-
-	Tcl_CreateCommand(interp,
-					  "pg_lo_import",
-					  Pg_lo_import,
-					  (ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
-
-	Tcl_CreateCommand(interp,
-					  "pg_lo_export",
-					  Pg_lo_export,
-					  (ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
-
-	Tcl_CreateCommand(interp,
-					  "pg_listen",
-					  Pg_listen,
-					  (ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
-
-	Tcl_CreateCommand(interp,
-					  "pg_notifies",
-					  Pg_notifies,
-					  (ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
-
-	Tcl_PkgProvide(interp, "Pgtcl", "1.0");
-
-	return TCL_OK;
+
+  /* finish off the ChannelType struct.  Much easier to do it here then
+   * to guess where it might be by position in the struct.  This is needed
+   * for Tcl7.6 and beyond, which have the getfileproc.
+   */
+#if (TCL_MAJOR_VERSION == 7 && TCL_MINOR_VERSION == 6)
+  Pg_ConnType.getFileProc = PgGetFileProc;
+#endif
+
+  /* register all pgtcl commands */
+  Tcl_CreateCommand(interp,
+		    "pg_conndefaults",
+		    Pg_conndefaults,
+		    (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+
+  Tcl_CreateCommand(interp,
+		    "pg_connect",
+		    Pg_connect,
+		    (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+
+  Tcl_CreateCommand(interp,
+		    "pg_disconnect",
+		    Pg_disconnect,
+		    (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+  
+  Tcl_CreateCommand(interp,
+		    "pg_exec",
+		    Pg_exec,
+		    (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+  
+  Tcl_CreateCommand(interp,
+		    "pg_select",
+		    Pg_select,
+		    (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+  
+  Tcl_CreateCommand(interp,
+		    "pg_result",
+		    Pg_result,
+		    (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+  
+  Tcl_CreateCommand(interp,
+		    "pg_lo_open",
+		    Pg_lo_open,
+		    (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+  
+  Tcl_CreateCommand(interp,
+		    "pg_lo_close",
+		    Pg_lo_close,
+		    (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+
+  Tcl_CreateCommand(interp,
+		    "pg_lo_read",
+		    Pg_lo_read,
+		    (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+
+  Tcl_CreateCommand(interp,
+		    "pg_lo_write",
+		    Pg_lo_write,
+		    (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+
+  Tcl_CreateCommand(interp,
+		    "pg_lo_lseek",
+		    Pg_lo_lseek,
+		    (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+
+  Tcl_CreateCommand(interp,
+		    "pg_lo_creat",
+		    Pg_lo_creat,
+		    (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+
+  Tcl_CreateCommand(interp,
+		    "pg_lo_tell",
+		    Pg_lo_tell,
+		    (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+
+  Tcl_CreateCommand(interp,
+		    "pg_lo_unlink",
+		    Pg_lo_unlink,
+		    (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+
+  Tcl_CreateCommand(interp,
+		    "pg_lo_import",
+		    Pg_lo_import,
+		    (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+  
+  Tcl_CreateCommand(interp,
+		    "pg_lo_export",
+		    Pg_lo_export,
+		    (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+  
+  Tcl_CreateCommand(interp,
+		    "pg_listen",
+		    Pg_listen,
+		    (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+
+  Tcl_CreateCommand(interp,
+		    "pg_notifies",
+		    Pg_notifies,
+		    (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+
+  Tcl_PkgProvide(interp, "Pgtcl", "1.1");
+
+  return TCL_OK;
 }
 
 
 int
-Pgtcl_SafeInit(Tcl_Interp * interp)
+Pgtcl_SafeInit (Tcl_Interp *interp)
 {
-	return Pgtcl_Init(interp);
+    return Pgtcl_Init(interp);
 }
diff --git a/src/interfaces/libpgtcl/pgtclCmds.c b/src/interfaces/libpgtcl/pgtclCmds.c
index 7f30db081833e7fc281af941e0507a4b0222e288..c68c842fedc84a15c1f5e9888fd31d0c3353eac9 100644
--- a/src/interfaces/libpgtcl/pgtclCmds.c
+++ b/src/interfaces/libpgtcl/pgtclCmds.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclCmds.c,v 1.21 1998/02/26 04:44:48 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclCmds.c,v 1.22 1998/03/15 08:02:58 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -240,258 +240,255 @@ tcl_value(char *value)
 
 /**********************************
  * pg_conndefaults
-
+ 
  syntax:
  pg_conndefaults
-
+ 
  the return result is a list describing the possible options and their
  current default values for a call to pg_connect with the new -conninfo
  syntax. Each entry in the list is a sublist of the format:
 
-	 {optname label dispchar dispsize value}
-
+     {optname label dispchar dispsize value}
+ 
  **********************************/
 
 int
-Pg_conndefaults(ClientData cData, Tcl_Interp * interp, int argc, char **argv)
+Pg_conndefaults(ClientData cData, Tcl_Interp *interp, int argc, char **argv)
 {
-	PQconninfoOption *option;
-	char		buf[8192];
-
-	Tcl_ResetResult(interp);
-	for (option = PQconndefaults(); option->keyword != NULL; option++)
-	{
-		if (option->val == NULL)
-		{
-			option->val = "";
-		}
-		sprintf(buf, "{%s} {%s} {%s} %d {%s}",
-				option->keyword,
-				option->label,
-				option->dispchar,
-				option->dispsize,
-				option->val);
-		Tcl_AppendElement(interp, buf);
-	}
-
-	return TCL_OK;
+    PQconninfoOption *option;
+    char	buf[8192];
+
+    Tcl_ResetResult(interp);
+    for(option = PQconndefaults(); option->keyword != NULL; option++) {
+        if(option->val == NULL) {
+	    option->val = "";
+	}
+	sprintf(buf, "{%s} {%s} {%s} %d {%s}",
+		option->keyword,
+		option->label,
+		option->dispchar,
+		option->dispsize,
+		option->val);
+        Tcl_AppendElement(interp, buf);
+    }
+
+    return TCL_OK;
 }
 
 
 /**********************************
  * pg_connect
- make a connection to a backend.
-
+ make a connection to a backend.  
+ 
  syntax:
  pg_connect dbName [-host hostName] [-port portNumber] [-tty pqtty]]
-
+ 
  the return result is either an error message or a handle for a database
  connection.  Handles start with the prefix "pgp"
-
+ 
  **********************************/
 
 int
-Pg_connect(ClientData cData, Tcl_Interp * interp, int argc, char *argv[])
+Pg_connect(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 {
-	Pg_clientData *cd = (Pg_clientData *) cData;
-	char	   *pghost = NULL;
-	char	   *pgtty = NULL;
-	char	   *pgport = NULL;
-	char	   *pgoptions = NULL;
-	char	   *dbName;
-	int			i;
-	PGconn	   *conn;
-
-	if (argc == 1)
-	{
-		Tcl_AppendResult(interp, "pg_connect: database name missing\n", 0);
-		Tcl_AppendResult(interp, "pg_connect databaseName [-host hostName] [-port portNumber] [-tty pgtty]]\n", 0);
-		Tcl_AppendResult(interp, "pg_connect -conninfo <conninfo-string>", 0);
-		return TCL_ERROR;
+    char *pghost = NULL;
+    char *pgtty = NULL;
+    char *pgport = NULL;
+    char *pgoptions = NULL;
+    char *dbName; 
+    int i;
+    PGconn *conn;
+  
+    if (argc == 1) {
+	Tcl_AppendResult(interp, "pg_connect: database name missing\n", 0);
+	Tcl_AppendResult(interp, "pg_connect databaseName [-host hostName] [-port portNumber] [-tty pgtty]]\n", 0);
+	Tcl_AppendResult(interp, "pg_connect -conninfo <conninfo-string>", 0);
+	return TCL_ERROR;
+    
+    }
 
+    if (!strcmp("-conninfo", argv[1])) {
+	/*
+	 * Establish a connection using the new PQconnectdb() interface
+	 */
+        if (argc != 3) {
+	    Tcl_AppendResult(interp, "pg_connect: syntax error\n", 0);
+	    Tcl_AppendResult(interp, "pg_connect -conninfo <conninfo-string>", 0);
+	    return TCL_ERROR;
 	}
-
-	if (!strcmp("-conninfo", argv[1]))
-	{
-
-		/*
-		 * Establish a connection using the new PQconnectdb() interface
-		 */
-		if (argc != 3)
-		{
-			Tcl_AppendResult(interp, "pg_connect: syntax error\n", 0);
-			Tcl_AppendResult(interp, "pg_connect -conninfo <conninfo-string>", 0);
-			return TCL_ERROR;
+	conn = PQconnectdb(argv[2]);
+    } else {
+	/*
+	 * Establish a connection using the old PQsetdb() interface
+	 */
+	if (argc > 2) { 
+	    /* parse for pg environment settings */
+	    i = 2;
+	    while (i+1 < argc) {
+		if (strcmp(argv[i], "-host") == 0) {
+		    pghost = argv[i+1];
+		    i += 2;
 		}
-		conn = PQconnectdb(argv[2]);
-	}
-	else
-	{
-
-		/*
-		 * Establish a connection using the old PQsetdb() interface
-		 */
-		if (argc > 2)
-		{
-			/* parse for pg environment settings */
-			i = 2;
-			while (i + 1 < argc)
-			{
-				if (strcmp(argv[i], "-host") == 0)
-				{
-					pghost = argv[i + 1];
-					i += 2;
-				}
-				else if (strcmp(argv[i], "-port") == 0)
-				{
-					pgport = argv[i + 1];
-					i += 2;
-				}
-				else if (strcmp(argv[i], "-tty") == 0)
-				{
-					pgtty = argv[i + 1];
-					i += 2;
-				}
-				else if (strcmp(argv[i], "-options") == 0)
-				{
-					pgoptions = argv[i + 1];
-					i += 2;
-				}
-				else
-				{
-					Tcl_AppendResult(interp, "Bad option to pg_connect : \n",
-									 argv[i], 0);
-					Tcl_AppendResult(interp, "pg_connect databaseName [-host hostName] [-port portNumber] [-tty pgtty]]", 0);
-					return TCL_ERROR;
-				}
-			}					/* while */
-			if ((i % 2 != 0) || i != argc)
-			{
-				Tcl_AppendResult(interp, "wrong # of arguments to pg_connect\n", argv[i], 0);
-				Tcl_AppendResult(interp, "pg_connect databaseName [-host hostName] [-port portNumber] [-tty pgtty]]", 0);
-				return TCL_ERROR;
+		else
+		    if (strcmp(argv[i], "-port") == 0) {
+			pgport = argv[i+1];
+			i += 2;
+		    }
+		    else
+			if (strcmp(argv[i], "-tty") == 0) {
+			    pgtty = argv[i+1];
+			    i += 2;
 			}
-		}
-		dbName = argv[1];
-		conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
-	}
-
-	if (conn->status == CONNECTION_OK)
-	{
-		PgSetConnectionId(cd, interp->result, conn);
-		return TCL_OK;
-	}
-	else
-	{
-		Tcl_AppendResult(interp, "Connection to database failed\n", 0);
-		Tcl_AppendResult(interp, conn->errorMessage, 0);
-		PQfinish(conn);
+			else if (strcmp(argv[i], "-options") == 0) {
+			    pgoptions = argv[i+1];
+			    i += 2;
+			}
+			else {
+			    Tcl_AppendResult(interp, "Bad option to pg_connect : \n",
+					     argv[i], 0);
+			    Tcl_AppendResult(interp, "pg_connect databaseName [-host hostName] [-port portNumber] [-tty pgtty]]",0);
+			    return TCL_ERROR;
+			}
+	    } /* while */
+	    if ((i % 2 != 0) || i != argc) {
+		Tcl_AppendResult(interp, "wrong # of arguments to pg_connect\n", argv[i],0);
+		Tcl_AppendResult(interp, "pg_connect databaseName [-host hostName] [-port portNumber] [-tty pgtty]]",0);
 		return TCL_ERROR;
+	    }
 	}
+	dbName = argv[1];
+        conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
+    }
+
+    if (conn->status == CONNECTION_OK) {
+	PgSetConnectionId(interp, conn);
+	return TCL_OK;
+    }
+    else {
+	Tcl_AppendResult(interp, "Connection to database failed\n", 0);
+	Tcl_AppendResult(interp, conn->errorMessage, 0);
+	PQfinish(conn);
+	return TCL_ERROR;
+    }
 }
 
 
 /**********************************
  * pg_disconnect
  close a backend connection
-
+ 
  syntax:
  pg_disconnect connection
-
+ 
  The argument passed in must be a connection pointer.
-
+ 
  **********************************/
 
 int
-Pg_disconnect(ClientData cData, Tcl_Interp * interp, int argc, char *argv[])
+Pg_disconnect(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 {
-	Pg_clientData *cd = (Pg_clientData *) cData;
-	PGconn	   *conn;
+    Tcl_Channel conn_chan;
 
-	if (argc != 2)
-	{
-		Tcl_AppendResult(interp, "Wrong # of arguments\n", "pg_disconnect connection", 0);
-		return TCL_ERROR;
-	}
+    if (argc != 2) {
+	Tcl_AppendResult(interp, "Wrong # of arguments\n", "pg_disconnect connection", 0);
+	return TCL_ERROR;
+    }
 
-	conn = PgGetConnectionId(cd, argv[1]);
-	if (conn == (PGconn *) NULL)
-	{
-		Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0);
-		return TCL_ERROR;
-	}
+    conn_chan = Tcl_GetChannel(interp, argv[1], 0);
+    if (conn_chan == NULL) {
+	Tcl_ResetResult(interp);
+	Tcl_AppendResult(interp, argv[1], " is not a valid connection\n", 0);
+	return TCL_ERROR;
+    }
 
-	PgDelConnectionId(cd, argv[1]);
-	PQfinish(conn);
-	return TCL_OK;
+    return Tcl_UnregisterChannel(interp, conn_chan);
 }
 
 /**********************************
  * pg_exec
  send a query string to the backend connection
-
+ 
  syntax:
  pg_exec connection query
-
+ 
  the return result is either an error message or a handle for a query
  result.  Handles start with the prefix "pgp"
  **********************************/
 
 int
-Pg_exec(ClientData cData, Tcl_Interp * interp, int argc, char *argv[])
+Pg_exec(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 {
-	Pg_clientData *cd = (Pg_clientData *) cData;
-	PGconn	   *conn;
-	PGresult   *result;
+    Pg_ConnectionId *connid;
+    PGconn *conn;
+    PGresult *result;
+    int connStatus;
+
+    if (argc != 3) {
+	Tcl_AppendResult(interp, "Wrong # of arguments\n",
+			 "pg_exec connection queryString", 0);
+	return TCL_ERROR;
+    }
 
-	if (argc != 3)
-	{
-		Tcl_AppendResult(interp, "Wrong # of arguments\n",
-						 "pg_exec connection queryString", 0);
-		return TCL_ERROR;
-	}
+    conn = PgGetConnectionId(interp, argv[1], &connid);
+    if (conn == (PGconn *)NULL) {
+	Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0);
+	return TCL_ERROR;
+    }
 
-	conn = PgGetConnectionId(cd, argv[1]);
-	if (conn == (PGconn *) NULL)
-	{
-		Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0);
-		return TCL_ERROR;
-	}
+    if (connid->res_copyStatus != RES_COPY_NONE) {
+	Tcl_SetResult(interp, "Attempt to query while COPY in progress", TCL_STATIC);
+	return TCL_ERROR;
+    }
 
-	result = PQexec(conn, argv[2]);
-	if (result)
-	{
-		PgSetResultId(cd, interp->result, argv[1], result);
-		return TCL_OK;
+    connStatus = conn->status;
+    result = PQexec(conn, argv[2]);
+    if (result) {
+	int rId = PgSetResultId(interp, argv[1], result);
+	if (result->resultStatus == PGRES_COPY_IN ||
+	    result->resultStatus == PGRES_COPY_OUT) {
+		connid->res_copyStatus = RES_COPY_INPROGRESS;
+		connid->res_copy = rId;
 	}
-	else
-	{
-		/* error occurred during the query */
-		Tcl_SetResult(interp, conn->errorMessage, TCL_STATIC);
-		return TCL_ERROR;
-	}
-	/* check return status of result */
 	return TCL_OK;
+    }
+    else {
+	/* error occurred during the query */
+	Tcl_SetResult(interp, conn->errorMessage, TCL_STATIC);
+	if (connStatus == CONNECTION_OK) {
+	    PQreset(conn);
+	    if (conn->status == CONNECTION_OK) {
+		result = PQexec(conn, argv[2]);
+		if (result) {
+		    int rId = PgSetResultId(interp, argv[1], result);
+		    if (result->resultStatus == PGRES_COPY_IN ||
+			result->resultStatus == PGRES_COPY_OUT) {
+			    connid->res_copyStatus = RES_COPY_INPROGRESS;
+			    connid->res_copy = rId;
+		    }
+		    return TCL_OK;
+		}
+	    }
+	}
+	return TCL_ERROR;
+    }
 }
 
 /**********************************
  * pg_result
  get information about the results of a query
-
+ 
  syntax:
- pg_result result ?option?
-
+ pg_result result ?option? 
+ 
  the options are:
- -status
+ -status  
  the status of the result
  -conn
  the connection that produced the result
  -assign arrayName
  assign the results to an array
- -assignbyidx arrayName ?appendstr?
+ -assignbyidx arrayName
  assign the results to an array using the first field as a key
- optional appendstr append that string to the key name. Usefull for
- creating pseudo-multi dimentional arrays in tcl.
  -numTuples
  the number of tuples in the query
  -attributes
@@ -502,333 +499,303 @@ Pg_exec(ClientData cData, Tcl_Interp * interp, int argc, char *argv[])
  returns the number of attributes returned by the query
  -getTuple tupleNumber
  returns the values of the tuple in a list
- -clear
+ -tupleArray tupleNumber arrayName
+ stores the values of the tuple in array arrayName, indexed
+ by the attributes returned
+ -clear 
  clear the result buffer. Do not reuse after this
  **********************************/
 int
-Pg_result(ClientData cData, Tcl_Interp * interp, int argc, char *argv[])
+Pg_result(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 {
-	Pg_clientData *cd = (Pg_clientData *) cData;
-	PGresult   *result;
-	char	   *opt;
-	int			i;
-	int			tupno;
-	char		prearrayInd[MAX_MESSAGE_LEN];
-	char		arrayInd[MAX_MESSAGE_LEN];
-	char	   *appendstr;
-	char	   *arrVar;
-
-	if (argc != 3 && argc != 4 && argc != 5)
-	{
-		Tcl_AppendResult(interp, "Wrong # of arguments\n", 0);
-		goto Pg_result_errReturn;
-	}
-
-	result = PgGetResultId(cd, argv[1]);
-	if (result == (PGresult *) NULL)
-	{
-		Tcl_AppendResult(interp, "First argument is not a valid query result\n", 0);
-		return TCL_ERROR;
-	}
+    PGresult *result;
+    char *opt;
+    int i;
+    int tupno;
+    char prearrayInd[MAX_MESSAGE_LEN];
+    char arrayInd[MAX_MESSAGE_LEN];
+    char *arrVar;
+
+    if (argc < 3 || argc > 5) {
+	Tcl_AppendResult(interp, "Wrong # of arguments\n",0);
+	goto Pg_result_errReturn;
+    }
+
+    result = PgGetResultId(interp, argv[1]);
+    if (result == (PGresult *)NULL) {
+	Tcl_AppendResult(interp, "First argument is not a valid query result", 0);
+	return TCL_ERROR;
+    }
 
-	opt = argv[2];
+    opt = argv[2];
 
-	if (strcmp(opt, "-status") == 0)
-	{
-		Tcl_AppendResult(interp, pgresStatus[PQresultStatus(result)], 0);
-		return TCL_OK;
-	}
-	else if (strcmp(opt, "-oid") == 0)
-	{
-		Tcl_AppendResult(interp, PQoidStatus(result), 0);
-		return TCL_OK;
-	}
-	else if (strcmp(opt, "-conn") == 0)
-	{
-		PgGetConnByResultId(cd, interp->result, argv[1]);
-		return TCL_OK;
-	}
-	else if (strcmp(opt, "-clear") == 0)
-	{
-		PgDelResultId(cd, argv[1]);
-		PQclear(result);
-		return TCL_OK;
-	}
-	else if (strcmp(opt, "-numTuples") == 0)
-	{
-		sprintf(interp->result, "%d", PQntuples(result));
-		return TCL_OK;
-	}
-	else if (strcmp(opt, "-assign") == 0)
-	{
-		if (argc != 4)
-		{
-			Tcl_AppendResult(interp, "-assign option must be followed by a variable name", 0);
-			return TCL_ERROR;
-		}
-		arrVar = argv[3];
-
-		/*
-		 * this assignment assigns the table of result tuples into a giant
-		 * array with the name given in the argument, the indices of the
-		 * array or (tupno,attrName)
-		 */
-		for (tupno = 0; tupno < PQntuples(result); tupno++)
-		{
-			for (i = 0; i < PQnfields(result); i++)
-			{
-				sprintf(arrayInd, "%d,%s", tupno, PQfname(result, i));
-				Tcl_SetVar2(interp, arrVar, arrayInd,
+    if (strcmp(opt, "-status") == 0) {
+	Tcl_AppendResult(interp, pgresStatus[PQresultStatus(result)], 0);
+	return TCL_OK;
+    }
+    else if (strcmp(opt, "-oid") == 0) {
+	Tcl_AppendResult(interp, PQoidStatus(result), 0);
+	return TCL_OK;
+    }
+    else if (strcmp(opt, "-conn") == 0) {
+	return PgGetConnByResultId(interp, argv[1]);
+    }
+    else if (strcmp(opt, "-clear") == 0) {
+	PgDelResultId(interp, argv[1]);
+	PQclear(result);
+	return TCL_OK;
+    }
+    else if (strcmp(opt, "-numTuples") == 0) {
+	sprintf(interp->result, "%d", PQntuples(result));
+	return TCL_OK;
+    }
+    else if (strcmp(opt, "-assign") == 0) {
+	if (argc != 4) {
+	    Tcl_AppendResult(interp, "-assign option must be followed by a variable name",0);
+	    return TCL_ERROR;
+	}
+	arrVar = argv[3];
+	/* this assignment assigns the table of result tuples into a giant
+	   array with the name given in the argument,
+	   the indices of the array or (tupno,attrName)*/
+	for (tupno = 0; tupno<PQntuples(result); tupno++) {
+	    for (i=0;i<PQnfields(result);i++) {
+		sprintf(arrayInd, "%d,%s", tupno, PQfname(result,i));
+		Tcl_SetVar2(interp, arrVar, arrayInd, 
 #ifdef TCL_ARRAYS
-							tcl_value(PQgetvalue(result, tupno, i)),
+			    tcl_value(PQgetvalue(result,tupno,i)),
 #else
-							PQgetvalue(result, tupno, i),
+			    PQgetvalue(result,tupno,i),
 #endif
-							TCL_LEAVE_ERR_MSG);
-			}
-		}
-		Tcl_AppendResult(interp, arrVar, 0);
-		return TCL_OK;
+			    TCL_LEAVE_ERR_MSG);
+	    }
 	}
-	else if (strcmp(opt, "-assignbyidx") == 0)
-	{
-		if (argc != 4 && argc != 5)
-		{
-			Tcl_AppendResult(interp, "-assignbyidx requires the array name and takes one optional argument as an append string", 0);
-			return TCL_ERROR;
-		}
-		arrVar = argv[3];
-
-		/*
-		 * this assignment assigns the table of result tuples into a giant
-		 * array with the name given in the argument, the indices of the
-		 * array or (tupno,attrName)
-		 */
-		if (argc == 5)
-		{
-			appendstr = argv[4];
-		}
-		else
-		{
-			appendstr = "";
-		}
-		for (tupno = 0; tupno < PQntuples(result); tupno++)
-		{
-			sprintf(prearrayInd, "%s", PQgetvalue(result, tupno, 0));
-			for (i = 1; i < PQnfields(result); i++)
-			{
-				sprintf(arrayInd, "%s,%s%s", prearrayInd, PQfname(result, i),
-						appendstr);
-				Tcl_SetVar2(interp, arrVar, arrayInd,
-							PQgetvalue(result, tupno, i),
-							TCL_LEAVE_ERR_MSG);
-			}
-		}
-		Tcl_AppendResult(interp, arrVar, 0);
-		return TCL_OK;
+	Tcl_AppendResult(interp, arrVar, 0);
+	return TCL_OK;
+    }
+    else if (strcmp(opt, "-assignbyidx") == 0) {
+      if (argc != 4) {
+          Tcl_AppendResult(interp, "-assignbyidx option must be followed by a variable name",0);
+          return TCL_ERROR;
+      }
+      arrVar = argv[3];
+      /* this assignment assigns the table of result tuples into a giant
+         array with the name given in the argument,
+         the indices of the array or (tupno,attrName)*/
+      for (tupno = 0; tupno<PQntuples(result); tupno++) {
+          sprintf(prearrayInd,"%s",PQgetvalue(result,tupno,0));
+          for (i=1;i<PQnfields(result);i++) {
+              sprintf(arrayInd, "%s,%s", prearrayInd, PQfname(result,i));
+              Tcl_SetVar2(interp, arrVar, arrayInd,
+                          PQgetvalue(result,tupno,i),
+                          TCL_LEAVE_ERR_MSG);
+          }
+      }
+      Tcl_AppendResult(interp, arrVar, 0);
+      return TCL_OK;
+    }
+    else if (strcmp(opt, "-getTuple") == 0) {
+	if (argc != 4) {
+	    Tcl_AppendResult(interp, "-getTuple option must be followed by a tuple number",0);
+	    return TCL_ERROR;
+	}
+	tupno = atoi(argv[3]);
+	
+	if (tupno >= PQntuples(result)) {
+	    Tcl_AppendResult(interp, "argument to getTuple cannot exceed number of tuples - 1",0);
+	    return TCL_ERROR;
 	}
-	else if (strcmp(opt, "-getTuple") == 0)
-	{
-		if (argc != 4)
-		{
-			Tcl_AppendResult(interp, "-getTuple option must be followed by a tuple number", 0);
-			return TCL_ERROR;
-		}
-		tupno = atoi(argv[3]);
-
-		if (tupno >= PQntuples(result))
-		{
-			Tcl_AppendResult(interp, "argument to getTuple cannot exceed number of tuples - 1", 0);
-			return TCL_ERROR;
-		}
 
 #ifdef TCL_ARRAYS
-		for (i = 0; i < PQnfields(result); i++)
-		{
-			Tcl_AppendElement(interp, PQgetvalue(result, tupno, i));
-		}
+	for (i=0; i<PQnfields(result); i++) {
+	    Tcl_AppendElement(interp, tcl_value(PQgetvalue(result,tupno,i)));
+	}
 #else
-/*		Tcl_AppendResult(interp, PQgetvalue(result,tupno,0),NULL); */
-		Tcl_AppendElement(interp, PQgetvalue(result, tupno, 0));
-		for (i = 1; i < PQnfields(result); i++)
-		{
-/*		  Tcl_AppendResult(interp, " ", PQgetvalue(result,tupno,i),NULL);*/
-			Tcl_AppendElement(interp, PQgetvalue(result, tupno, i));
-		}
+/*	Tcl_AppendResult(interp, PQgetvalue(result,tupno,0),NULL); */
+        Tcl_AppendElement(interp, PQgetvalue(result,tupno,0));
+	for (i=1;i<PQnfields(result);i++) {
+/*	  Tcl_AppendResult(interp, " ", PQgetvalue(result,tupno,i),NULL);*/
+         Tcl_AppendElement(interp, PQgetvalue(result,tupno,i));
+	}
 #endif
 
-		return TCL_OK;
+	return TCL_OK;
+    }
+    else if (strcmp(opt, "-tupleArray") == 0) {
+	if (argc != 5) {
+	    Tcl_AppendResult(interp, "-tupleArray option must be followed by a tuple number and array name",0);
+	    return TCL_ERROR;
 	}
-	else if (strcmp(opt, "-attributes") == 0)
-	{
-		Tcl_AppendResult(interp, PQfname(result, 0), NULL);
-		for (i = 1; i < PQnfields(result); i++)
-		{
-			Tcl_AppendResult(interp, " ", PQfname(result, i), NULL);
-		}
-		return TCL_OK;
+	tupno = atoi(argv[3]);
+	
+	if (tupno >= PQntuples(result)) {
+	    Tcl_AppendResult(interp, "argument to tupleArray cannot exceed number of tuples - 1",0);
+	    return TCL_ERROR;
 	}
-	else if (strcmp(opt, "-lAttributes") == 0)
-	{
-		char		buf[512];
 
-		Tcl_ResetResult(interp);
-		for (i = 0; i < PQnfields(result); i++)
-		{
-			sprintf(buf, "{%s} %ld %d", PQfname(result, i),
-					(long) PQftype(result, i),
-					PQfsize(result, i));
-			Tcl_AppendElement(interp, buf);
-		}
-		return TCL_OK;
-	}
-	else if (strcmp(opt, "-numAttrs") == 0)
-	{
-		sprintf(interp->result, "%d", PQnfields(result));
-		return TCL_OK;
+	for ( i = 0; i < PQnfields(result); i++) {
+	   if (Tcl_SetVar2(interp, argv[4], PQfname(result, i), PQgetvalue(result, tupno, i), TCL_LEAVE_ERR_MSG) == NULL) {
+	       return TCL_ERROR;
+	   }
 	}
-	else
-	{
-		Tcl_AppendResult(interp, "Invalid option", 0);
-		goto Pg_result_errReturn;
-	}
-
-
-Pg_result_errReturn:
-	Tcl_AppendResult(interp,
-					 "pg_result result ?option? where ?option is\n",
-					 "\t-status\n",
-					 "\t-conn\n",
-					 "\t-assign arrayVarName\n",
-					 "\t-assignbyidx arrayVarName ?appendstr?\n",
-					 "\t-numTuples\n",
-					 "\t-attributes\n"
-					 "\t-lAttributes\n"
-					 "\t-numAttrs\n"
-					 "\t-getTuple tupleNumber\n",
-					 "\t-clear\n",
-					 "\t-oid\n",
-					 0);
-	return TCL_ERROR;
-
+	return TCL_OK;
+    }
+    else if (strcmp(opt, "-attributes") == 0) {
+      Tcl_AppendResult(interp, PQfname(result,0),NULL);
+      for (i=1;i<PQnfields(result);i++) {
+	Tcl_AppendResult(interp, " ", PQfname(result,i), NULL);
+      }
+      return TCL_OK;
+    }
+    else if (strcmp(opt, "-lAttributes") == 0) {
+      char buf[512];
+      Tcl_ResetResult(interp);
+      for (i = 0; i < PQnfields(result); i++) {
+          sprintf(buf, "{%s} %ld %d", PQfname(result, i),
+	  			      (long) PQftype(result, i),
+				      PQfsize(result, i));
+          Tcl_AppendElement(interp, buf);
+      }
+      return TCL_OK;
+    }
+    else if (strcmp(opt, "-numAttrs") == 0) {
+      sprintf(interp->result, "%d", PQnfields(result));
+      return TCL_OK;
+    }
+    else   { 
+	Tcl_AppendResult(interp, "Invalid option",0);
+	goto Pg_result_errReturn;
+    }
+  
+
+ Pg_result_errReturn:
+    Tcl_AppendResult(interp, 
+		     "pg_result result ?option? where ?option is\n", 
+		     "\t-status\n",
+		     "\t-conn\n",
+		     "\t-assign arrayVarName\n",
+		     "\t-assignbyidx arrayVarName\n",
+		     "\t-numTuples\n",
+		     "\t-attributes\n"
+		     "\t-lAttributes\n"
+		     "\t-numAttrs\n"
+		     "\t-getTuple tupleNumber\n",
+		     "\t-tupleArray tupleNumber arrayVarName\n",
+		     "\t-clear\n",
+		     "\t-oid\n",
+		     (char*)0);
+    return TCL_ERROR;
+  
 
 }
 
 /**********************************
  * pg_lo_open
-	 open a large object
-
+     open a large object
+ 
  syntax:
- pg_lo_open conn objOid mode
+ pg_lo_open conn objOid mode 
 
  where mode can be either 'r', 'w', or 'rw'
 **********************/
 
 int
-Pg_lo_open(ClientData cData, Tcl_Interp * interp, int argc, char *argv[])
+Pg_lo_open(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 {
-	Pg_clientData *cd = (Pg_clientData *) cData;
-	PGconn	   *conn;
-	int			lobjId;
-	int			mode;
-	int			fd;
-
-	if (argc != 4)
-	{
-		Tcl_AppendResult(interp, "Wrong # of arguments\n",
-						 "pg_lo_open connection lobjOid mode", 0);
-		return TCL_ERROR;
-	}
-
-	conn = PgGetConnectionId(cd, argv[1]);
-	if (conn == (PGconn *) NULL)
-	{
-		Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0);
-		return TCL_ERROR;
-	}
-
-	lobjId = atoi(argv[2]);
-	if (strlen(argv[3]) < 1 ||
-		strlen(argv[3]) > 2)
-	{
-		Tcl_AppendResult(interp, "mode argument must be 'r', 'w', or 'rw'", 0);
-		return TCL_ERROR;
-	}
-	switch (argv[3][0])
-	{
-		case 'r':
-		case 'R':
-			mode = INV_READ;
-			break;
-		case 'w':
-		case 'W':
-			mode = INV_WRITE;
-			break;
-		default:
-			Tcl_AppendResult(interp, "mode argument must be 'r', 'w', or 'rw'", 0);
-			return TCL_ERROR;
-	}
-	switch (argv[3][1])
-	{
-		case '\0':
-			break;
-		case 'r':
-		case 'R':
-			mode = mode & INV_READ;
-			break;
-		case 'w':
-		case 'W':
-			mode = mode & INV_WRITE;
-			break;
-		default:
-			Tcl_AppendResult(interp, "mode argument must be 'r', 'w', or 'rw'", 0);
-			return TCL_ERROR;
-	}
-
-	fd = lo_open(conn, lobjId, mode);
-	sprintf(interp->result, "%d", fd);
-	return TCL_OK;
+    PGconn *conn;
+    int lobjId;
+    int mode;
+    int fd;
+
+    if (argc != 4) {
+	Tcl_AppendResult(interp, "Wrong # of arguments\n",
+			 "pg_lo_open connection lobjOid mode", 0);
+	return TCL_ERROR;
+    }
+  
+    conn = PgGetConnectionId(interp, argv[1], (Pg_ConnectionId**)NULL);
+    if (conn == (PGconn *)NULL) {
+	Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0);
+	return TCL_ERROR;
+    }
+  
+    lobjId = atoi(argv[2]);
+    if (strlen(argv[3]) < 1 ||
+	strlen(argv[3]) > 2)
+	{
+	Tcl_AppendResult(interp,"mode argument must be 'r', 'w', or 'rw'",0);
+        return TCL_ERROR;
+    }
+    switch (argv[3][0]) {
+    case 'r':
+    case 'R':
+	mode = INV_READ;
+	break;
+    case 'w':
+    case 'W':
+	mode = INV_WRITE;
+	break;
+    default:
+	Tcl_AppendResult(interp,"mode argument must be 'r', 'w', or 'rw'",0);
+        return TCL_ERROR;
+   }
+    switch (argv[3][1]) {
+    case '\0':
+	break;
+    case 'r':
+    case 'R':
+	mode = mode & INV_READ;
+	break;
+    case 'w':
+    case 'W':
+	mode = mode & INV_WRITE;
+	break;
+    default:
+	Tcl_AppendResult(interp,"mode argument must be 'r', 'w', or 'rw'",0);
+        return TCL_ERROR;
+    }
+
+    fd = lo_open(conn,lobjId,mode);
+    sprintf(interp->result,"%d",fd);
+    return TCL_OK;
 }
 
 /**********************************
  * pg_lo_close
-	 close a large object
-
+     close a large object
+ 
  syntax:
- pg_lo_close conn fd
+ pg_lo_close conn fd 
 
 **********************/
 int
-Pg_lo_close(ClientData cData, Tcl_Interp * interp, int argc, char *argv[])
+Pg_lo_close(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 {
-	Pg_clientData *cd = (Pg_clientData *) cData;
-	PGconn	   *conn;
-	int			fd;
+    PGconn *conn;
+    int fd;
 
-	if (argc != 3)
-	{
-		Tcl_AppendResult(interp, "Wrong # of arguments\n",
-						 "pg_lo_close connection fd", 0);
-		return TCL_ERROR;
-	}
-
-	conn = PgGetConnectionId(cd, argv[1]);
-	if (conn == (PGconn *) NULL)
-	{
-		Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0);
-		return TCL_ERROR;
-	}
+    if (argc != 3) {
+	Tcl_AppendResult(interp, "Wrong # of arguments\n",
+			 "pg_lo_close connection fd", 0);
+	return TCL_ERROR;
+    }
 
-	fd = atoi(argv[2]);
-	sprintf(interp->result, "%d", lo_close(conn, fd));
-	return TCL_OK;
+    conn = PgGetConnectionId(interp, argv[1], (Pg_ConnectionId**)NULL);
+    if (conn == (PGconn *)NULL) {
+	Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0);
+	return TCL_ERROR;
+    }
+  
+    fd = atoi(argv[2]);
+    sprintf(interp->result,"%d",lo_close(conn,fd));
+    return TCL_OK;
 }
 
 /**********************************
  * pg_lo_read
-	 reads at most len bytes from a large object into a variable named
+     reads at most len bytes from a large object into a variable named
  bufVar
-
+ 
  syntax:
  pg_lo_read conn fd bufVar len
 
@@ -836,104 +803,96 @@ Pg_lo_close(ClientData cData, Tcl_Interp * interp, int argc, char *argv[])
 
 **********************/
 int
-Pg_lo_read(ClientData cData, Tcl_Interp * interp, int argc, char *argv[])
+Pg_lo_read(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 {
-	Pg_clientData *cd = (Pg_clientData *) cData;
-	PGconn	   *conn;
-	int			fd;
-	int			nbytes = 0;
-	char	   *buf;
-	char	   *bufVar;
-	int			len;
-
-	if (argc != 5)
-	{
-		Tcl_AppendResult(interp, "Wrong # of arguments\n",
-						 " pg_lo_read conn fd bufVar len", 0);
-		return TCL_ERROR;
-	}
-
-	conn = PgGetConnectionId(cd, argv[1]);
-	if (conn == (PGconn *) NULL)
-	{
-		Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0);
-		return TCL_ERROR;
-	}
-
-	fd = atoi(argv[2]);
-
-	bufVar = argv[3];
+    PGconn *conn;
+    int fd;
+    int nbytes = 0;
+    char *buf;
+    char *bufVar;
+    int len;
+
+    if (argc != 5) {
+	Tcl_AppendResult(interp, "Wrong # of arguments\n",
+			 " pg_lo_read conn fd bufVar len", 0);
+	return TCL_ERROR;
+    }
 
-	len = atoi(argv[4]);
+    conn = PgGetConnectionId(interp, argv[1], (Pg_ConnectionId**)NULL);
+    if (conn == (PGconn *)NULL) {
+	Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0);
+	return TCL_ERROR;
+    }
+  
+    fd = atoi(argv[2]);
 
-	if (len <= 0)
-	{
-		sprintf(interp->result, "%d", nbytes);
-		return TCL_OK;
-	}
-	buf = malloc(sizeof(len + 1));
+    bufVar = argv[3];
 
-	nbytes = lo_read(conn, fd, buf, len);
+    len = atoi(argv[4]);
 
-	Tcl_SetVar(interp, bufVar, buf, TCL_LEAVE_ERR_MSG);
-	sprintf(interp->result, "%d", nbytes);
-	free(buf);
+    if (len <= 0) {
+	sprintf(interp->result,"%d",nbytes);
 	return TCL_OK;
+    }
+    buf = ckalloc(sizeof(len+1));
 
+    nbytes = lo_read(conn,fd,buf,len);
+
+    Tcl_SetVar(interp,bufVar,buf,TCL_LEAVE_ERR_MSG);
+    sprintf(interp->result,"%d",nbytes);
+    ckfree(buf);
+    return TCL_OK;
+    
 }
 
 /***********************************
 Pg_lo_write
-   write at most len bytes to a large object
+   write at most len bytes to a large object 
 
  syntax:
  pg_lo_write conn fd buf len
 
 ***********************************/
 int
-Pg_lo_write(ClientData cData, Tcl_Interp * interp, int argc, char *argv[])
+Pg_lo_write(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 {
-	Pg_clientData *cd = (Pg_clientData *) cData;
-	PGconn	   *conn;
-	char	   *buf;
-	int			fd;
-	int			nbytes = 0;
-	int			len;
-
-	if (argc != 5)
-	{
-		Tcl_AppendResult(interp, "Wrong # of arguments\n",
-						 "pg_lo_write conn fd buf len", 0);
-		return TCL_ERROR;
-	}
-
-	conn = PgGetConnectionId(cd, argv[1]);
-	if (conn == (PGconn *) NULL)
-	{
-		Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0);
-		return TCL_ERROR;
-	}
+    PGconn *conn;
+    char *buf;
+    int fd;
+    int nbytes = 0;
+    int len;
+
+    if (argc != 5) {
+	Tcl_AppendResult(interp, "Wrong # of arguments\n",
+			 "pg_lo_write conn fd buf len", 0);
+	return TCL_ERROR;
+    }
 
-	fd = atoi(argv[2]);
+    conn = PgGetConnectionId(interp, argv[1], (Pg_ConnectionId**)NULL);
+    if (conn == (PGconn *)NULL) {
+	Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0);
+	return TCL_ERROR;
+    }
+  
+    fd = atoi(argv[2]);
 
-	buf = argv[3];
+    buf = argv[3];
 
-	len = atoi(argv[4]);
+    len = atoi(argv[4]);
 
-	if (len <= 0)
-	{
-		sprintf(interp->result, "%d", nbytes);
-		return TCL_OK;
-	}
-
-	nbytes = lo_write(conn, fd, buf, len);
-	sprintf(interp->result, "%d", nbytes);
+    if (len <= 0) {
+	sprintf(interp->result,"%d",nbytes);
 	return TCL_OK;
+    }
+
+    nbytes = lo_write(conn,fd,buf,len);
+    sprintf(interp->result,"%d",nbytes);
+    return TCL_OK;
 }
 
 /***********************************
 Pg_lo_lseek
-	seek to a certain position in a large object
+    seek to a certain position in a large object
 
 syntax
   pg_lo_lseek conn fd offset whence
@@ -942,54 +901,43 @@ whence can be either
 "SEEK_CUR", "SEEK_END", or "SEEK_SET"
 ***********************************/
 int
-Pg_lo_lseek(ClientData cData, Tcl_Interp * interp, int argc, char *argv[])
+Pg_lo_lseek(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 {
-	Pg_clientData *cd = (Pg_clientData *) cData;
-	PGconn	   *conn;
-	int			fd;
-	char	   *whenceStr;
-	int			offset,
-				whence;
-
-	if (argc != 5)
-	{
-		Tcl_AppendResult(interp, "Wrong # of arguments\n",
-						 "pg_lo_lseek conn fd offset whence", 0);
-		return TCL_ERROR;
-	}
-
-	conn = PgGetConnectionId(cd, argv[1]);
-	if (conn == (PGconn *) NULL)
-	{
-		Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0);
-		return TCL_ERROR;
-	}
-
-	fd = atoi(argv[2]);
-
-	offset = atoi(argv[3]);
-
-	whenceStr = argv[4];
-	if (strcmp(whenceStr, "SEEK_SET") == 0)
-	{
-		whence = SEEK_SET;
-	}
-	else if (strcmp(whenceStr, "SEEK_CUR") == 0)
-	{
-		whence = SEEK_CUR;
-	}
-	else if (strcmp(whenceStr, "SEEK_END") == 0)
-	{
-		whence = SEEK_END;
-	}
-	else
-	{
-		Tcl_AppendResult(interp, "the whence argument to Pg_lo_lseek must be SEEK_SET, SEEK_CUR or SEEK_END", 0);
-		return TCL_ERROR;
-	}
+    PGconn *conn;
+    int fd;
+    char *whenceStr;
+    int offset, whence;
+
+    if (argc != 5) {
+	Tcl_AppendResult(interp, "Wrong # of arguments\n",
+			 "pg_lo_lseek conn fd offset whence", 0);
+	return TCL_ERROR;
+    }
 
-	sprintf(interp->result, "%d", lo_lseek(conn, fd, offset, whence));
-	return TCL_OK;
+    conn = PgGetConnectionId(interp, argv[1], (Pg_ConnectionId**)NULL);
+    if (conn == (PGconn *)NULL) {
+	Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0);
+	return TCL_ERROR;
+    }
+  
+    fd = atoi(argv[2]);
+
+    offset = atoi(argv[3]);
+
+    whenceStr = argv[4];
+    if (strcmp(whenceStr,"SEEK_SET") == 0) {
+	whence = SEEK_SET;
+    } else if (strcmp(whenceStr,"SEEK_CUR") == 0) {
+	whence = SEEK_CUR;
+    } else if (strcmp(whenceStr,"SEEK_END") == 0) {
+	whence = SEEK_END;
+    } else {
+	Tcl_AppendResult(interp, "the whence argument to Pg_lo_lseek must be SEEK_SET, SEEK_CUR or SEEK_END",0);
+	return TCL_ERROR;
+    }
+	
+    sprintf(interp->result,"%d",lo_lseek(conn,fd,offset,whence));
+    return TCL_OK;
 }
 
 
@@ -1000,113 +948,96 @@ Pg_lo_creat
  syntax:
    pg_lo_creat conn mode
 
-mode can be any OR'ing together of INV_READ, INV_WRITE
+mode can be any OR'ing together of INV_READ, INV_WRITE,
 for now, we don't support any additional storage managers.
 
 ***********************************/
 int
-Pg_lo_creat(ClientData cData, Tcl_Interp * interp, int argc, char *argv[])
+Pg_lo_creat(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 {
-	Pg_clientData *cd = (Pg_clientData *) cData;
-	PGconn	   *conn;
-	char	   *modeStr;
-	char	   *modeWord;
-	int			mode;
-
-	if (argc != 3)
-	{
-		Tcl_AppendResult(interp, "Wrong # of arguments\n",
-						 "pg_lo_creat conn mode", 0);
-		return TCL_ERROR;
-	}
-
-	conn = PgGetConnectionId(cd, argv[1]);
-	if (conn == (PGconn *) NULL)
-	{
-		Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0);
-		return TCL_ERROR;
-	}
-
-	modeStr = argv[2];
-
-	modeWord = strtok(modeStr, "|");
-	if (strcmp(modeWord, "INV_READ") == 0)
-	{
-		mode = INV_READ;
-	}
-	else if (strcmp(modeWord, "INV_WRITE") == 0)
-	{
-		mode = INV_WRITE;
-	}
-	else
-	{
-		Tcl_AppendResult(interp,
-						 "invalid mode argument to Pg_lo_creat\nmode argument must be some OR'd combination of INV_READ, and INV_WRITE",
-						 0);
-		return TCL_ERROR;
-	}
+    PGconn *conn;
+    char *modeStr;
+    char *modeWord;
+    int mode;
+
+    if (argc != 3) {
+	Tcl_AppendResult(interp, "Wrong # of arguments\n",
+			 "pg_lo_creat conn mode", 0);
+	return TCL_ERROR;
+    }
 
-	while ((modeWord = strtok((char *) NULL, "|")) != NULL)
-	{
-		if (strcmp(modeWord, "INV_READ") == 0)
-		{
-			mode |= INV_READ;
-		}
-		else if (strcmp(modeWord, "INV_WRITE") == 0)
-		{
-			mode |= INV_WRITE;
-		}
-		else
-		{
-			Tcl_AppendResult(interp,
-							 "invalid mode argument to Pg_lo_creat\nmode argument must be some OR'd combination of INV_READ, and INV_WRITE",
-							 0);
-			return TCL_ERROR;
-		}
-	}
-	sprintf(interp->result, "%d", lo_creat(conn, mode));
-	return TCL_OK;
+    conn = PgGetConnectionId(interp, argv[1], (Pg_ConnectionId**)NULL);
+    if (conn == (PGconn *)NULL) {
+	Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0);
+	return TCL_ERROR;
+    }
+  
+    modeStr = argv[2];
+
+    modeWord = strtok(modeStr,"|");
+    if (strcmp(modeWord,"INV_READ") == 0) {
+	mode = INV_READ;
+    } else if (strcmp(modeWord,"INV_WRITE") == 0) {
+	mode = INV_WRITE;
+    } else {
+	Tcl_AppendResult(interp,
+			 "invalid mode argument to Pg_lo_creat\nmode argument must be some OR'd combination of INV_READ, and INV_WRITE",
+			 0);
+	return TCL_ERROR;
+    }
+
+    while ( (modeWord = strtok((char*)NULL, "|")) != NULL) {
+	if (strcmp(modeWord,"INV_READ") == 0) {
+	    mode |= INV_READ;
+	} else if (strcmp(modeWord,"INV_WRITE") == 0) {
+	    mode |= INV_WRITE;
+	} else {
+	    Tcl_AppendResult(interp,
+			     "invalid mode argument to Pg_lo_creat\nmode argument must be some OR'd combination of INV_READ, INV_WRITE",
+			     0);
+	    return TCL_ERROR;
+	}
+    }
+    sprintf(interp->result,"%d",lo_creat(conn,mode));
+    return TCL_OK;
 }
 
 /***********************************
 Pg_lo_tell
-	returns the current seek location of the large object
+    returns the current seek location of the large object
 
  syntax:
    pg_lo_tell conn fd
 
 ***********************************/
 int
-Pg_lo_tell(ClientData cData, Tcl_Interp * interp, int argc, char *argv[])
+Pg_lo_tell(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 {
-	Pg_clientData *cd = (Pg_clientData *) cData;
-	PGconn	   *conn;
-	int			fd;
-
-	if (argc != 3)
-	{
-		Tcl_AppendResult(interp, "Wrong # of arguments\n",
-						 "pg_lo_tell conn fd", 0);
-		return TCL_ERROR;
-	}
+    PGconn *conn;
+    int fd;
 
-	conn = PgGetConnectionId(cd, argv[1]);
-	if (conn == (PGconn *) NULL)
-	{
-		Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0);
-		return TCL_ERROR;
-	}
+    if (argc != 3) {
+	Tcl_AppendResult(interp, "Wrong # of arguments\n",
+			 "pg_lo_tell conn fd", 0);
+	return TCL_ERROR;
+    }
 
-	fd = atoi(argv[2]);
+    conn = PgGetConnectionId(interp, argv[1], (Pg_ConnectionId**)NULL);
+    if (conn == (PGconn *)NULL) {
+	Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0);
+	return TCL_ERROR;
+    }
+  
+    fd = atoi(argv[2]);
 
-	sprintf(interp->result, "%d", lo_tell(conn, fd));
-	return TCL_OK;
+    sprintf(interp->result,"%d",lo_tell(conn,fd));
+    return TCL_OK;
 
 }
 
 /***********************************
 Pg_lo_unlink
-	unlink a file based on lobject id
+    unlink a file based on lobject id 
 
  syntax:
    pg_lo_unlink conn lobjId
@@ -1114,43 +1045,39 @@ Pg_lo_unlink
 
 ***********************************/
 int
-Pg_lo_unlink(ClientData cData, Tcl_Interp * interp, int argc, char *argv[])
+Pg_lo_unlink(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 {
-	Pg_clientData *cd = (Pg_clientData *) cData;
-	PGconn	   *conn;
-	int			lobjId;
-	int			retval;
-
-	if (argc != 3)
-	{
-		Tcl_AppendResult(interp, "Wrong # of arguments\n",
-						 "pg_lo_tell conn fd", 0);
-		return TCL_ERROR;
-	}
+    PGconn *conn;
+    int lobjId;
+    int retval;
 
-	conn = PgGetConnectionId(cd, argv[1]);
-	if (conn == (PGconn *) NULL)
-	{
-		Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0);
-		return TCL_ERROR;
-	}
-
-	lobjId = atoi(argv[2]);
+    if (argc != 3) {
+	Tcl_AppendResult(interp, "Wrong # of arguments\n",
+			 "pg_lo_tell conn fd", 0);
+	return TCL_ERROR;
+    }
 
-	retval = lo_unlink(conn, lobjId);
-	if (retval == -1)
-	{
-		sprintf(interp->result, "Pg_lo_unlink of '%d' failed", lobjId);
-		return TCL_ERROR;
-	}
+    conn = PgGetConnectionId(interp, argv[1], (Pg_ConnectionId**)NULL);
+    if (conn == (PGconn *)NULL) {
+	Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0);
+	return TCL_ERROR;
+    }
+  
+    lobjId = atoi(argv[2]);
 
-	sprintf(interp->result, "%d", retval);
-	return TCL_OK;
+    retval = lo_unlink(conn,lobjId);
+    if (retval == -1) {
+	sprintf(interp->result,"Pg_lo_unlink of '%d' failed",lobjId);
+	return TCL_ERROR;
+    }
+	
+    sprintf(interp->result,"%d",retval);
+    return TCL_OK;
 }
 
 /***********************************
 Pg_lo_import
-	import a Unix file into an (inversion) large objct
+    import a Unix file into an (inversion) large objct
  returns the oid of that object upon success
  returns InvalidOid upon failure
 
@@ -1160,87 +1087,79 @@ Pg_lo_import
 ***********************************/
 
 int
-Pg_lo_import(ClientData cData, Tcl_Interp * interp, int argc, char *argv[])
+Pg_lo_import(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 {
-	Pg_clientData *cd = (Pg_clientData *) cData;
-	PGconn	   *conn;
-	char	   *filename;
-	Oid			lobjId;
-
-	if (argc != 3)
-	{
-		Tcl_AppendResult(interp, "Wrong # of arguments\n",
-						 "pg_lo_import conn filename", 0);
-		return TCL_ERROR;
-	}
+    PGconn *conn;
+    char* filename;
+    Oid lobjId;
 
-	conn = PgGetConnectionId(cd, argv[1]);
-	if (conn == (PGconn *) NULL)
-	{
-		Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0);
-		return TCL_ERROR;
-	}
+    if (argc != 3) {
+	Tcl_AppendResult(interp, "Wrong # of arguments\n",
+			 "pg_lo_import conn filename", 0);
+	return TCL_ERROR;
+    }
 
-	filename = argv[2];
+    conn = PgGetConnectionId(interp, argv[1], (Pg_ConnectionId**)NULL);
+    if (conn == (PGconn *)NULL) {
+	Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0);
+	return TCL_ERROR;
+    }
+  
+    filename = argv[2];
 
-	lobjId = lo_import(conn, filename);
-	if (lobjId == InvalidOid)
-	{
-		sprintf(interp->result, "Pg_lo_import of '%s' failed", filename);
-		return TCL_ERROR;
-	}
-	sprintf(interp->result, "%d", lobjId);
-	return TCL_OK;
+    lobjId = lo_import(conn,filename);
+    if (lobjId == InvalidOid) {
+	sprintf(interp->result, "Pg_lo_import of '%s' failed",filename);
+	return TCL_ERROR;
+    }
+    sprintf(interp->result,"%d",lobjId);
+    return TCL_OK;
 }
 
 /***********************************
 Pg_lo_export
-	export an Inversion large object to a Unix file
-
+    export an Inversion large object to a Unix file
+    
  syntax:
    pg_lo_export conn lobjId filename
 
 ***********************************/
 
 int
-Pg_lo_export(ClientData cData, Tcl_Interp * interp, int argc, char *argv[])
+Pg_lo_export(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 {
-	Pg_clientData *cd = (Pg_clientData *) cData;
-	PGconn	   *conn;
-	char	   *filename;
-	Oid			lobjId;
-	int			retval;
-
-	if (argc != 4)
-	{
-		Tcl_AppendResult(interp, "Wrong # of arguments\n",
-						 "pg_lo_export conn lobjId filename", 0);
-		return TCL_ERROR;
-	}
-
-	conn = PgGetConnectionId(cd, argv[1]);
-	if (conn == (PGconn *) NULL)
-	{
-		Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0);
-		return TCL_ERROR;
-	}
-
-	lobjId = atoi(argv[2]);
-	filename = argv[3];
+    PGconn *conn;
+    char* filename;
+    Oid lobjId;
+    int retval;
+
+    if (argc != 4) {
+	Tcl_AppendResult(interp, "Wrong # of arguments\n",
+			 "pg_lo_export conn lobjId filename", 0);
+	return TCL_ERROR;
+    }
 
-	retval = lo_export(conn, lobjId, filename);
-	if (retval == -1)
-	{
-		sprintf(interp->result, "Pg_lo_export %d %s failed", lobjId, filename);
-		return TCL_ERROR;
-	}
-	return TCL_OK;
+    conn = PgGetConnectionId(interp, argv[1], (Pg_ConnectionId**)NULL);
+    if (conn == (PGconn *)NULL) {
+	Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0);
+	return TCL_ERROR;
+    }
+  
+    lobjId = atoi(argv[2]);
+    filename = argv[3];
+
+    retval = lo_export(conn,lobjId,filename);
+    if (retval == -1) {
+	sprintf(interp->result, "Pg_lo_export %d %s failed",lobjId, filename);
+	return TCL_ERROR;
+    }
+    return TCL_OK;
 }
 
 /**********************************
  * pg_select
  send a select query string to the backend connection
-
+ 
  syntax:
  pg_select connection query var proc
 
@@ -1250,7 +1169,7 @@ Pg_lo_export(ClientData cData, Tcl_Interp * interp, int argc, char *argv[])
 
  Originally I was also going to update changes but that has turned out
  to be not so simple.  Instead, the caller should get the OID of any
- table they want to update and update it themself in the loop.	I may
+ table they want to update and update it themself in the loop.  I may
  try to write a simplified table lookup and update function to make
  that task a little easier.
 
@@ -1259,45 +1178,39 @@ Pg_lo_export(ClientData cData, Tcl_Interp * interp, int argc, char *argv[])
  **********************************/
 
 int
-Pg_select(ClientData cData, Tcl_Interp * interp, int argc, char **argv)
+Pg_select(ClientData cData, Tcl_Interp *interp, int argc, char **argv)
 {
-	Pg_clientData *cd = (Pg_clientData *) cData;
-	PGconn	   *conn;
-	PGresult   *result;
-	int			r;
-	size_t		tupno,
-				column,
-				ncols;
+	PGconn *conn;
+   	PGresult *result;
+    int r;
+    size_t tupno, column, ncols;
 	Tcl_DString headers;
-	char		buffer[2048];
-	struct
-	{
-		char	   *cname;
-		int			change;
-	}		   *info;
+	char	buffer[2048];
+	struct info_s {
+		char    *cname;
+		int     change;
+	} *info;
 
 	if (argc != 5)
 	{
 		Tcl_AppendResult(interp, "Wrong # of arguments\n",
-						 "pg_select connection queryString var proc", 0);
-		return TCL_ERROR;
-	}
-
-	conn = PgGetConnectionId(cd, argv[1]);
-	if (conn == (PGconn *) NULL)
-	{
-		Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0);
+			 "pg_select connection queryString var proc", 0);
 		return TCL_ERROR;
 	}
 
+    conn = PgGetConnectionId(interp, argv[1], (Pg_ConnectionId**)NULL);
+    if (conn == (PGconn *)NULL) {
+	return TCL_ERROR;
+    }
+  
 	if ((result = PQexec(conn, argv[2])) == 0)
-	{
+    {
 		/* error occurred during the query */
 		Tcl_SetResult(interp, conn->errorMessage, TCL_STATIC);
 		return TCL_ERROR;
-	}
+    }
 
-	if ((info = malloc(sizeof(*info) * (ncols = PQnfields(result)))) == NULL)
+	if ((info = (struct info_s *)ckalloc(sizeof(*info) * (ncols =  PQnfields(result)))) == NULL)
 	{
 		Tcl_AppendResult(interp, "Not enough memory", 0);
 		return TCL_ERROR;
@@ -1323,8 +1236,8 @@ Pg_select(ClientData cData, Tcl_Interp * interp, int argc, char **argv)
 
 		for (column = 0; column < ncols; column++)
 		{
-			Tcl_SetVar2(interp, argv[3], info[column].cname,
-						PQgetvalue(result, tupno, column), 0);
+			strcpy(buffer, PQgetvalue(result, tupno, column));
+			Tcl_SetVar2(interp, argv[3], info[column].cname, buffer, 0);
 		}
 
 		Tcl_SetVar2(interp, argv[3], ".command", "update", 0);
@@ -1332,196 +1245,166 @@ Pg_select(ClientData cData, Tcl_Interp * interp, int argc, char **argv)
 		if ((r = Tcl_Eval(interp, argv[4])) != TCL_OK && r != TCL_CONTINUE)
 		{
 			if (r == TCL_BREAK)
-			{
-
-				/*
-				 * I suppose that memory used by info and result must be
-				 * released
-				 */
-				free(info);
-				PQclear(result);
-				Tcl_UnsetVar(interp, argv[3], 0);
 				return TCL_OK;
-			}
+
 			if (r == TCL_ERROR)
 			{
-				char		msg[60];
+				char	msg[60];
 
 				sprintf(msg, "\n    (\"pg_select\" body line %d)",
-						interp->errorLine);
+								interp->errorLine);
 				Tcl_AddErrorInfo(interp, msg);
 			}
-			/* also, releasing memory used by info and result */
-			free(info);
-			PQclear(result);
-			Tcl_UnsetVar(interp, argv[3], 0);
+
 			return r;
 		}
 	}
 
-	free(info);
-	/* Release memory used by result */
-	PQclear(result);
+	ckfree((void*)info);
 	Tcl_UnsetVar(interp, argv[3], 0);
 	Tcl_AppendResult(interp, "", 0);
 	return TCL_OK;
 }
 
 int
-Pg_listen(ClientData cData, Tcl_Interp * interp, int argc, char *argv[])
+Pg_listen(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 {
-	Pg_clientData *cd = (Pg_clientData *) cData;
-	int			new;
-	char	   *relname;
-	char	   *callback = NULL;
-	Tcl_HashEntry *entry;
-	PGconn	   *conn;
-	PGresult   *result;
-
-	if ((argc < 3) || (argc > 4))
-	{
-		Tcl_AppendResult(interp, "wrong # args, should be \"",
-						 argv[0], " connection relname ?callback?\"", 0);
-		return TCL_ERROR;
-	}
-
-	/*
-	 * Get the command arguments. Note that relname will copied by
-	 * Tcl_CreateHashEntry while callback must be allocated.
-	 */
-	conn = (PGconn *) PgGetConnectionId(cd, argv[1]);
-	if (conn == (PGconn *) NULL)
-	{
-		Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0);
-		return TCL_ERROR;
-	}
-	relname = argv[2];
-	if ((argc > 3) && *argv[3])
-	{
-		callback = (char *) ckalloc((unsigned) (strlen(argv[3]) + 1));
-		strcpy(callback, argv[3]);
-	}
-
-	/*
-	 * Set or update a callback for a relation;
-	 */
-	if (callback)
-	{
-		entry = Tcl_CreateHashEntry(&(cd->notify_hash), relname, &new);
-		if (new)
-		{
-			/* New callback, execute a listen command on the relation */
-			char	   *cmd = (char *) ckalloc((unsigned) (strlen(argv[2]) + 8));
-
-			sprintf(cmd, "LISTEN %s", relname);
-			result = PQexec(conn, cmd);
-			ckfree(cmd);
-			if (!result || (result->resultStatus != PGRES_COMMAND_OK))
-			{
-				/* Error occurred during the execution of command */
-				if (result)
-					PQclear(result);
-				ckfree(callback);
-				Tcl_DeleteHashEntry(entry);
-				Tcl_SetResult(interp, conn->errorMessage, TCL_STATIC);
-				return TCL_ERROR;
-			}
-			PQclear(result);
-		}
-		else
-		{
-			/* Free the old callback string */
-			ckfree((char *) Tcl_GetHashValue(entry));
-		}
-		/* Store the new callback command */
-		Tcl_SetHashValue(entry, callback);
-	}
-
-	/*
-	 * Remove a callback for a relation.  There is no way to un-listen a
-	 * relation, simply remove the callback from the notify hash table.
-	 */
-	if (callback == NULL)
-	{
-		entry = Tcl_FindHashEntry(&(cd->notify_hash), relname);
-		if (entry == NULL)
-		{
-			Tcl_AppendResult(interp, "not listening on ", relname, 0);
-			return TCL_ERROR;
-		}
-		ckfree((char *) Tcl_GetHashValue(entry));
+    int new;
+    char *relname;
+    char *callback = NULL;
+    Tcl_HashEntry *entry;
+    Pg_ConnectionId *connid;
+    PGconn *conn;
+    PGresult *result;
+
+    if ((argc < 3) || (argc > 4)) {
+	Tcl_AppendResult(interp, "wrong # args, should be \"",
+			 argv[0], " connection relname ?callback?\"", 0);
+	return TCL_ERROR;
+    }
+
+    /*
+     * Get the command arguments. Note that relname will copied by
+     * Tcl_CreateHashEntry while callback must be allocated.
+     */
+    conn = PgGetConnectionId(interp, argv[1], &connid);
+    if (conn == (PGconn *)NULL) {
+	Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0);
+	return TCL_ERROR;
+    }
+    relname = argv[2];
+    if ((argc > 3) && *argv[3]) {
+	callback = (char *) ckalloc((unsigned) (strlen(argv[3])+1));
+	strcpy(callback, argv[3]);
+    }
+
+    /*
+     * Set or update a callback for a relation;
+     */
+    if (callback) {
+	entry = Tcl_CreateHashEntry(&(connid->notify_hash), relname, &new);
+	if (new) {
+	    /* New callback, execute a listen command on the relation */
+	    char *cmd = (char *) ckalloc((unsigned) (strlen(argv[2])+8));
+	    sprintf(cmd, "LISTEN %s", relname);
+	    result = PQexec(conn, cmd);
+	    ckfree(cmd);
+	    if (!result || (result->resultStatus != PGRES_COMMAND_OK)) {
+		/* Error occurred during the execution of command */
+		if (result) PQclear(result);
+		ckfree(callback);
 		Tcl_DeleteHashEntry(entry);
-	}
-
-	return TCL_OK;
+		Tcl_SetResult(interp, conn->errorMessage, TCL_STATIC);
+		return TCL_ERROR;
+	    }
+	    PQclear(result);
+	} else {
+	    /* Free the old callback string */
+	    ckfree((char *) Tcl_GetHashValue(entry));
+	}
+	/* Store the new callback command */
+	Tcl_SetHashValue(entry, callback);
+    }
+
+    /*
+     * Remove a callback for a relation.  There is no way to
+     * un-listen a relation, simply remove the callback from
+     * the notify hash table.
+     */
+    if (callback == NULL) {
+	entry = Tcl_FindHashEntry(&(connid->notify_hash), relname);
+	if (entry == NULL) {
+	    Tcl_AppendResult(interp, "not listening on ", relname, 0);
+	    return TCL_ERROR;
+	}
+	ckfree((char *) Tcl_GetHashValue(entry));
+	Tcl_DeleteHashEntry(entry);
+    }
+
+    return TCL_OK;
 }
 
 int
-Pg_notifies(ClientData cData, Tcl_Interp * interp, int argc, char *argv[])
+Pg_notifies(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 {
-	Pg_clientData *cd = (Pg_clientData *) cData;
-	int			count;
-	char		buff[12];
-	char	   *callback;
-	Tcl_HashEntry *entry;
-	PGconn	   *conn;
-	PGresult   *result;
-	PGnotify   *notify;
-
-	if (argc != 2)
-	{
-		Tcl_AppendResult(interp, "wrong # args, should be \"",
-						 argv[0], " connection\"", 0);
-		return TCL_ERROR;
-	}
-
-	/*
-	 * Get the connection argument.
-	 */
-	conn = (PGconn *) PgGetConnectionId(cd, argv[1]);
-	if (conn == (PGconn *) NULL)
-	{
-		Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0);
-		return TCL_ERROR;
-	}
-
-	/* Execute an empty command to retrieve asynchronous notifications */
-	result = PQexec(conn, " ");
-	if (result == NULL)
-	{
-		/* Error occurred during the execution of command */
-		Tcl_SetResult(interp, conn->errorMessage, TCL_STATIC);
-		return TCL_ERROR;
-	}
-	PQclear(result);
-
-	/*
-	 * Loop while there are pending notifies.
-	 */
-	for (count = 0; count < 999; count++)
-	{
-		/* See if there is a pending notification */
-		notify = PQnotifies(conn);
-		if (notify == NULL)
-		{
-			break;
-		}
-		entry = Tcl_FindHashEntry(&(cd->notify_hash), notify->relname);
-		if (entry != NULL)
-		{
-			callback = Tcl_GetHashValue(entry);
-			if (callback)
-			{
-				Tcl_Eval(interp, callback);
-			}
-		}
-		free(notify);
-	}
-
-	/*
-	 * Return the number of notifications processed.
-	 */
-	sprintf(buff, "%d", count);
-	Tcl_SetResult(interp, buff, TCL_VOLATILE);
-	return TCL_OK;
+    int count;
+    char buff[12];
+    char *callback;
+    Tcl_HashEntry *entry;
+    Pg_ConnectionId *connid;
+    PGconn *conn;
+    PGresult *result;
+    PGnotify *notify;
+
+    if (argc != 2) {
+	Tcl_AppendResult(interp, "wrong # args, should be \"",
+			 argv[0], " connection\"", 0);
+	return TCL_ERROR;
+    }
+
+    /*
+     * Get the connection argument.
+     */
+    conn = (PGconn*)PgGetConnectionId(interp, argv[1], &connid);
+    if (conn == (PGconn *)NULL) {
+	Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0);
+	return TCL_ERROR;
+    }
+
+    /* Execute an empty command to retrieve asynchronous notifications */
+    result = PQexec(conn, " ");
+    if (result == NULL) {
+      /* Error occurred during the execution of command */
+      Tcl_SetResult(interp, conn->errorMessage, TCL_STATIC);
+      return TCL_ERROR;
+    }
+    PQclear(result);
+
+    /*
+     * Loop while there are pending notifies.
+     */
+    for (count=0; count < 999; count++) {
+	/* See if there is a pending notification */
+	notify = PQnotifies(conn);
+	if (notify == NULL) {
+	    break;
+	}
+	entry = Tcl_FindHashEntry(&(connid->notify_hash), notify->relname);
+	if (entry != NULL) {
+	    callback = (char*)Tcl_GetHashValue(entry);
+	    if (callback) {
+		/* This should be a global eval, shouldn't it? */
+		Tcl_Eval(interp, callback);
+		/* And what if there's an error.  Bgerror should be called? */
+	    }
+	}
+	free(notify);
+    }
+
+    /*
+     * Return the number of notifications processed.
+     */
+    sprintf(buff, "%d", count);
+    Tcl_SetResult(interp, buff, TCL_VOLATILE);
+    return TCL_OK;
 }
diff --git a/src/interfaces/libpgtcl/pgtclCmds.h b/src/interfaces/libpgtcl/pgtclCmds.h
index 6def84d97ffc0dde6cf61fa59292feca1b972844..f0f8513da449bdbdb77dc63f9223794ba3e5e4c8 100644
--- a/src/interfaces/libpgtcl/pgtclCmds.h
+++ b/src/interfaces/libpgtcl/pgtclCmds.h
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pgtclCmds.h,v 1.8 1997/09/08 02:40:16 momjian Exp $
+ * $Id: pgtclCmds.h,v 1.9 1998/03/15 08:02:59 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -18,89 +18,69 @@
 #include "libpq-fe.h"
 #include "libpq/libpq-fs.h"
 
-typedef struct Pg_clientData_s
-{
-	Tcl_HashTable dbh_hash;
-	Tcl_HashTable res_hash;
-	Tcl_HashTable notify_hash;
-	long		dbh_count;
-	long		res_count;
-}			Pg_clientData;
+#define RES_HARD_MAX 128
+#define RES_START 16
 
+typedef struct Pg_ConnectionId_s {
+    char		id[32];
+    PGconn		*conn;
+    int			res_max;	/* Max number of results allocated */
+    int			res_hardmax;	/* Absolute max to allow */
+    int			res_count;	/* Current count of active results */
+    int			res_last;	/* Optimize where to start looking */
+    int			res_copy;	/* Query result with active copy */
+    int			res_copyStatus; /* Copying status */
+    PGresult		**results;	/* The results */
+    
+    Tcl_HashTable	notify_hash;
+} Pg_ConnectionId;
 
-typedef struct Pg_ConnectionId_s
-{
-	char		id[32];
-	PGconn	   *conn;
-	Tcl_HashTable res_hash;
-}			Pg_ConnectionId;
 
-
-typedef struct Pg_ResultId_s
-{
-	char		id[32];
-	PGresult   *result;
-	Pg_ConnectionId *connection;
-}			Pg_ResultId;
+#define RES_COPY_NONE	0
+#define RES_COPY_INPROGRESS	1
+#define RES_COPY_FIN	2
 
 
 /* **************************/
 /* registered Tcl functions */
 /* **************************/
-extern int
-Pg_conndefaults(
-		  ClientData cData, Tcl_Interp * interp, int argc, char *argv[]);
-extern int
-Pg_connect(
-		   ClientData cData, Tcl_Interp * interp, int argc, char *argv[]);
-extern int
-Pg_disconnect(
-		  ClientData cData, Tcl_Interp * interp, int argc, char *argv[]);
-extern int
-Pg_exec(
-		ClientData cData, Tcl_Interp * interp, int argc, char *argv[]);
-extern int
-Pg_select(
-		  ClientData cData, Tcl_Interp * interp, int argc, char *argv[]);
-extern int
-Pg_result(
-		  ClientData cData, Tcl_Interp * interp, int argc, char *argv[]);
-extern int
-Pg_lo_open(
-		   ClientData cData, Tcl_Interp * interp, int argc, char *argv[]);
-extern int
-Pg_lo_close(
-		  ClientData cData, Tcl_Interp * interp, int argc, char *argv[]);
-extern int
-Pg_lo_read(
-		   ClientData cData, Tcl_Interp * interp, int argc, char *argv[]);
-extern int
-Pg_lo_write(
-		  ClientData cData, Tcl_Interp * interp, int argc, char *argv[]);
-extern int
-Pg_lo_lseek(
-		  ClientData cData, Tcl_Interp * interp, int argc, char *argv[]);
-extern int
-Pg_lo_creat(
-		  ClientData cData, Tcl_Interp * interp, int argc, char *argv[]);
-extern int
-Pg_lo_tell(
-		   ClientData cData, Tcl_Interp * interp, int argc, char *argv[]);
-extern int
-Pg_lo_unlink(
-		  ClientData cData, Tcl_Interp * interp, int argc, char *argv[]);
-extern int
-Pg_lo_import(
-		  ClientData cData, Tcl_Interp * interp, int argc, char *argv[]);
-extern int
-Pg_lo_export(
-		  ClientData cData, Tcl_Interp * interp, int argc, char *argv[]);
-extern int
-Pg_listen(
-		  ClientData cData, Tcl_Interp * interp, int argc, char *argv[]);
-extern int
-Pg_notifies(
-		  ClientData cData, Tcl_Interp * interp, int argc, char *argv[]);
+extern int Pg_conndefaults(
+    ClientData cData, Tcl_Interp *interp, int argc, char* argv[]);
+extern int Pg_connect(
+    ClientData cData, Tcl_Interp *interp, int argc, char* argv[]);
+extern int Pg_disconnect(
+    ClientData cData, Tcl_Interp *interp, int argc, char* argv[]);
+extern int Pg_exec(
+    ClientData cData, Tcl_Interp *interp, int argc, char* argv[]);
+extern int Pg_select(
+    ClientData cData, Tcl_Interp *interp, int argc, char* argv[]);
+extern int Pg_result(
+    ClientData cData, Tcl_Interp *interp, int argc, char* argv[]);
+extern int Pg_lo_open(
+    ClientData cData, Tcl_Interp *interp, int argc, char* argv[]);
+extern int Pg_lo_close(
+    ClientData cData, Tcl_Interp *interp, int argc, char* argv[]);
+extern int Pg_lo_read(
+    ClientData cData, Tcl_Interp *interp, int argc, char* argv[]);
+extern int Pg_lo_write(
+    ClientData cData, Tcl_Interp *interp, int argc, char* argv[]);
+extern int Pg_lo_lseek(
+    ClientData cData, Tcl_Interp *interp, int argc, char* argv[]);
+extern int Pg_lo_creat(
+    ClientData cData, Tcl_Interp *interp, int argc, char* argv[]);
+extern int Pg_lo_tell(
+    ClientData cData, Tcl_Interp *interp, int argc, char* argv[]);
+extern int Pg_lo_unlink(
+    ClientData cData, Tcl_Interp *interp, int argc, char* argv[]);
+extern int Pg_lo_import(
+    ClientData cData, Tcl_Interp *interp, int argc, char* argv[]);
+extern int Pg_lo_export(
+    ClientData cData, Tcl_Interp *interp, int argc, char* argv[]);
+extern int Pg_listen(
+    ClientData cData, Tcl_Interp *interp, int argc, char* argv[]);
+extern int Pg_notifies(
+    ClientData cData, Tcl_Interp *interp, int argc, char* argv[]);
+
 
+#endif /*PGTCLCMDS_H*/
 
-#endif							/* PGTCLCMDS_H */
diff --git a/src/interfaces/libpgtcl/pgtclId.c b/src/interfaces/libpgtcl/pgtclId.c
index 2473b6c3181013ff3a08a001912843b571c7bbdd..971b04039b45c330c772ead51ffa7353f6cd3afd 100644
--- a/src/interfaces/libpgtcl/pgtclId.c
+++ b/src/interfaces/libpgtcl/pgtclId.c
@@ -1,48 +1,173 @@
 /*-------------------------------------------------------------------------
  *
  * pgtclId.c--
- *	  useful routines to convert between strings and pointers
- *	Needed because everything in tcl is a string, but we want pointers
- *	to data structures
+ *    useful routines to convert between strings and pointers
+ *  Needed because everything in tcl is a string, but we want pointers
+ *  to data structures
  *
- *	ASSUMPTION:  sizeof(long) >= sizeof(void*)
+ *  ASSUMPTION:  sizeof(long) >= sizeof(void*)
  *
  *
  * Copyright (c) 1994, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclId.c,v 1.7 1998/02/26 04:44:53 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclId.c,v 1.8 1998/03/15 08:03:00 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include <stdlib.h>
 #include <string.h>
+#include <errno.h>
 #include <tcl.h>
 
 #include "postgres.h"
 #include "pgtclCmds.h"
 #include "pgtclId.h"
 
+int PgEndCopy(Pg_ConnectionId *connid, int *errorCodePtr)
+{
+    connid->res_copyStatus = RES_COPY_NONE;
+    if (PQendcopy(connid->conn)) {
+	connid->results[connid->res_copy]->resultStatus = PGRES_BAD_RESPONSE;
+	connid->res_copy = -1;
+	*errorCodePtr = EIO;
+	return -1;
+    } else {
+	connid->results[connid->res_copy]->resultStatus = PGRES_COMMAND_OK;
+	connid->res_copy = -1;
+	return 0;
+    }
+}
+
+/*
+ *  Called when reading data (via gets) for a copy <rel> to stdout
+ */
+int PgInputProc(DRIVER_INPUT_PROTO)
+{
+    Pg_ConnectionId	*connid;
+    PGconn		*conn;
+    int			c;
+    int			avail;
+
+    connid = (Pg_ConnectionId *)cData;
+    conn = connid->conn;
+
+    if (connid->res_copy < 0 ||
+      connid->results[connid->res_copy]->resultStatus != PGRES_COPY_OUT) {
+	*errorCodePtr = EBUSY;
+	return -1;
+    }
+
+    if (connid->res_copyStatus == RES_COPY_FIN) {
+	return PgEndCopy(connid, errorCodePtr);
+    }
+
+    avail = bufSize;
+    while (avail > 0 &&
+	    (c = pqGetc(conn->Pfin, conn->Pfdebug)) != EOF) {
+	/* fprintf(stderr, "%d: got char %c\n", bufSize-avail, c); */
+	*buf++ = c;
+	--avail;
+	if (c == '\n' && bufSize-avail > 3) {
+	    if ((bufSize-avail == 3 || buf[-4] == '\n') &&
+		    buf[-3] == '\\' && buf[-2] == '.') {
+		avail += 3;
+		connid->res_copyStatus = RES_COPY_FIN;
+		break;
+	    }
+	}
+    }
+    /* fprintf(stderr, "returning %d chars\n", bufSize - avail); */
+    return bufSize - avail;
+}
+
+/*
+ *  Called when writing data (via puts) for a copy <rel> from stdin
+ */
+int PgOutputProc(DRIVER_OUTPUT_PROTO)
+{
+    Pg_ConnectionId	*connid;
+    PGconn		*conn;
+
+    connid = (Pg_ConnectionId *)cData;
+    conn = connid->conn;
+
+    if (connid->res_copy < 0 ||
+      connid->results[connid->res_copy]->resultStatus != PGRES_COPY_IN) {
+	*errorCodePtr = EBUSY;
+	return -1;
+    }
+
+    /*
+    fprintf(stderr, "PgOutputProc called: bufSize=%d: atend:%d <", bufSize,
+	strncmp(buf, "\\.\n", 3));
+    fwrite(buf, 1, bufSize, stderr);
+    fputs(">\n", stderr);
+    */
+    fwrite(buf, 1, bufSize, conn->Pfout);
+    if (bufSize > 2 && strncmp(&buf[bufSize-3], "\\.\n", 3) == 0) {
+	/* fprintf(stderr,"checking closure\n"); */
+	fflush(conn->Pfout);
+	if (PgEndCopy(connid, errorCodePtr) == -1)
+	    return -1;
+    }
+    return bufSize;
+}
+
+#if (TCL_MAJOR_VERSION == 7 && TCL_MINOR_VERSION == 6)
+Tcl_File
+PgGetFileProc(ClientData cData, int direction)
+{
+    return (Tcl_File)NULL;
+}
+#endif
+
+Tcl_ChannelType Pg_ConnType = {
+    "pgsql",			/* channel type */
+    NULL,			/* blockmodeproc */
+    PgDelConnectionId,		/* closeproc */
+    PgInputProc,		/* inputproc */
+    PgOutputProc,		/* outputproc */
+    /*  Note the additional stuff can be left NULL,
+	or is initialized during a PgSetConnectionId */
+};
+
 /*
- * Create the Id for a new connection and hash it
+ * Create and register a new channel for the connection
  */
 void
-PgSetConnectionId(Pg_clientData * cd, char *id, PGconn *conn)
+PgSetConnectionId(Tcl_Interp *interp, PGconn *conn)
 {
-	Tcl_HashEntry *hent;
-	Pg_ConnectionId *connid;
-	int			hnew;
-
-	connid = (Pg_ConnectionId *) ckalloc(sizeof(Pg_ConnectionId));
-	connid->conn = conn;
-	Tcl_InitHashTable(&(connid->res_hash), TCL_STRING_KEYS);
-	sprintf(connid->id, "pgc%ld", cd->dbh_count++);
-	strcpy(id, connid->id);
-
-	hent = Tcl_CreateHashEntry(&(cd->dbh_hash), connid->id, &hnew);
-	Tcl_SetHashValue(hent, (ClientData) connid);
+    Tcl_Channel		conn_chan;
+    Pg_ConnectionId	*connid;
+    int			i;
+
+    connid = (Pg_ConnectionId *)ckalloc(sizeof(Pg_ConnectionId));
+    connid->conn = conn;
+    connid->res_count = 0;
+    connid->res_last = -1;
+    connid->res_max = RES_START;
+    connid->res_hardmax = RES_HARD_MAX;
+    connid->res_copy = -1;
+    connid->res_copyStatus = RES_COPY_NONE;
+    connid->results = (PGresult**)ckalloc(sizeof(PGresult*) * RES_START);
+    for (i = 0; i < RES_START; i++) connid->results[i] = NULL;
+    Tcl_InitHashTable(&connid->notify_hash, TCL_STRING_KEYS);
+
+    sprintf(connid->id, "pgsql%d", fileno(conn->Pfout));
+
+#if TCL_MAJOR_VERSION == 7 && TCL_MINOR_VERSION == 5
+    conn_chan = Tcl_CreateChannel(&Pg_ConnType, connid->id, conn->Pfin, conn->Pfout, (ClientData)connid);
+#else
+    conn_chan = Tcl_CreateChannel(&Pg_ConnType, connid->id, (ClientData)connid,
+	TCL_READABLE | TCL_WRITABLE);
+#endif
+
+    Tcl_SetChannelOption(interp, conn_chan, "-buffering", "line");
+    Tcl_SetResult(interp, connid->id, TCL_VOLATILE);
+    Tcl_RegisterChannel(interp, conn_chan);
 }
 
 
@@ -50,19 +175,22 @@ PgSetConnectionId(Pg_clientData * cd, char *id, PGconn *conn)
  * Get back the connection from the Id
  */
 PGconn *
-PgGetConnectionId(Pg_clientData * cd, char *id)
+PgGetConnectionId(Tcl_Interp *interp, char *id, Pg_ConnectionId **connid_p)
 {
-	Tcl_HashEntry *hent;
-	Pg_ConnectionId *connid;
-
-	hent = Tcl_FindHashEntry(&(cd->dbh_hash), id);
-	if (hent == NULL)
-	{
-		return (PGconn *) NULL;
-	}
-
-	connid = (Pg_ConnectionId *) Tcl_GetHashValue(hent);
-	return connid->conn;
+    Tcl_Channel conn_chan;
+    Pg_ConnectionId	*connid;
+
+    conn_chan = Tcl_GetChannel(interp, id, 0);
+    if(conn_chan == NULL || Tcl_GetChannelType(conn_chan) != &Pg_ConnType) {
+	Tcl_ResetResult(interp);
+	Tcl_AppendResult(interp, id, " is not a valid postgresql connection\n", 0);
+        return (PGconn *)NULL;
+    }
+
+    connid = (Pg_ConnectionId *)Tcl_GetChannelInstanceData(conn_chan);
+    if (connid_p)
+	*connid_p = connid;
+    return connid->conn;
 }
 
 
@@ -70,98 +198,139 @@ PgGetConnectionId(Pg_clientData * cd, char *id)
  * Remove a connection Id from the hash table and
  * close all portals the user forgot.
  */
-void
-PgDelConnectionId(Pg_clientData * cd, char *id)
+int PgDelConnectionId(DRIVER_DEL_PROTO)
 {
-	Tcl_HashEntry *hent;
-	Tcl_HashEntry *hent2;
-	Tcl_HashEntry *hent3;
-	Tcl_HashSearch hsearch;
-	Pg_ConnectionId *connid;
-	Pg_ResultId *resid;
-
-	hent = Tcl_FindHashEntry(&(cd->dbh_hash), id);
-	if (hent == NULL)
-	{
-		return;
-	}
-
-	connid = (Pg_ConnectionId *) Tcl_GetHashValue(hent);
-
-	hent2 = Tcl_FirstHashEntry(&(connid->res_hash), &hsearch);
-	while (hent2 != NULL)
-	{
-		resid = (Pg_ResultId *) Tcl_GetHashValue(hent2);
-		PQclear(resid->result);
-		hent3 = Tcl_FindHashEntry(&(cd->res_hash), resid->id);
-		if (hent3 != NULL)
-		{
-			Tcl_DeleteHashEntry(hent3);
-		}
-		ckfree(resid);
-		hent2 = Tcl_NextHashEntry(&hsearch);
-	}
-	Tcl_DeleteHashTable(&(connid->res_hash));
-	Tcl_DeleteHashEntry(hent);
-	ckfree(connid);
+    Tcl_HashEntry	*entry;
+    char		*hval;
+    Tcl_HashSearch	hsearch;
+    Pg_ConnectionId	*connid;
+    int			i;
+
+    connid = (Pg_ConnectionId *)cData;
+
+    for (i = 0; i < connid->res_max; i++) {
+	if (connid->results[i])
+	    PQclear(connid->results[i]);
+    }
+    ckfree((void*)connid->results);
+
+    for (entry = Tcl_FirstHashEntry(&(connid->notify_hash), &hsearch);
+	entry != NULL;
+	entry = Tcl_NextHashEntry(&hsearch))
+    {
+	hval = (char*)Tcl_GetHashValue(entry);
+	ckfree(hval);
+    }
+    
+    Tcl_DeleteHashTable(&connid->notify_hash);
+    PQfinish(connid->conn);
+    ckfree((void*)connid);
+    return 0;
 }
 
 
 /*
- * Create a new result Id and hash it
+ * Find a slot for a new result id.  If the table is full, expand it by
+ * a factor of 2.  However, do not expand past the hard max, as the client
+ * is probably just not clearing result handles like they should.
  */
-void
-PgSetResultId(Pg_clientData * cd, char *id, char *connid_c, PGresult *res)
+int
+PgSetResultId(Tcl_Interp *interp, char *connid_c, PGresult *res)
 {
-	Tcl_HashEntry *hent;
-	Pg_ConnectionId *connid;
-	Pg_ResultId *resid;
-	int			hnew;
+    Tcl_Channel		conn_chan;
+    Pg_ConnectionId	*connid;
+    int			resid, i;
+    char		buf[32];
 
-	hent = Tcl_FindHashEntry(&(cd->dbh_hash), connid_c);
-	if (hent == NULL)
-	{
-		connid = NULL;
-	}
-	else
-	{
-		connid = (Pg_ConnectionId *) Tcl_GetHashValue(hent);
-	}
-
-	resid = (Pg_ResultId *) ckalloc(sizeof(Pg_ResultId));
-	resid->result = res;
-	resid->connection = connid;
-	sprintf(resid->id, "pgr%ld", cd->res_count++);
-	strcpy(id, resid->id);
 
-	hent = Tcl_CreateHashEntry(&(cd->res_hash), resid->id, &hnew);
-	Tcl_SetHashValue(hent, (ClientData) resid);
+    conn_chan = Tcl_GetChannel(interp, connid_c, 0);
+    if(conn_chan == NULL)
+        return TCL_ERROR;
+    connid = (Pg_ConnectionId *)Tcl_GetChannelInstanceData(conn_chan);
 
-	if (connid != NULL)
+    for (resid = connid->res_last+1; resid != connid->res_last; resid++) {
+	if (resid == connid->res_max)
+	    resid = 0;
+	if (!connid->results[resid])
 	{
-		hent = Tcl_CreateHashEntry(&(connid->res_hash), resid->id, &hnew);
-		Tcl_SetHashValue(hent, (ClientData) resid);
+	    connid->res_last = resid;
+	    break;
+	}
+    }
+
+    if (connid->results[resid]) {
+	if (connid->res_max == connid->res_hardmax) {
+	    Tcl_SetResult(interp, "hard limit on result handles reached",
+		TCL_STATIC);
+	    return TCL_ERROR;
 	}
+	connid->res_last = connid->res_max;
+	resid = connid->res_max;
+	connid->res_max *= 2;
+	if (connid->res_max > connid->res_hardmax)
+	    connid->res_max = connid->res_hardmax;
+	connid->results = (PGresult**)ckrealloc((void*)connid->results,
+	    sizeof(PGresult*) * connid->res_max);
+	for (i = connid->res_last; i < connid->res_max; i++)
+	    connid->results[i] = NULL;
+    }
+
+    connid->results[resid] = res;
+    sprintf(buf, "%s.%d", connid_c, resid);
+    Tcl_SetResult(interp, buf, TCL_VOLATILE);
+    return resid;
+}
+
+static int getresid(Tcl_Interp *interp, char *id, Pg_ConnectionId **connid_p)
+{
+    Tcl_Channel		conn_chan;
+    char		*mark;
+    int			resid;
+    Pg_ConnectionId	*connid;
+
+    if (!(mark = strchr(id, '.')))
+	return -1;
+    *mark = '\0';
+    conn_chan = Tcl_GetChannel(interp, id, 0);
+    *mark = '.';
+    if(conn_chan == NULL || Tcl_GetChannelType(conn_chan) != &Pg_ConnType) {
+	Tcl_SetResult(interp, "Invalid connection handle", TCL_STATIC);
+        return -1;
+    }
+
+    if (Tcl_GetInt(interp, mark + 1, &resid) == TCL_ERROR) {
+	Tcl_SetResult(interp, "Poorly formated result handle", TCL_STATIC);
+	return -1;
+    }
+
+    connid = (Pg_ConnectionId *)Tcl_GetChannelInstanceData(conn_chan);
+
+    if (resid < 0 || resid > connid->res_max || connid->results[resid] == NULL) {
+	Tcl_SetResult(interp, "Invalid result handle", TCL_STATIC);
+	return -1;
+    }
+
+    *connid_p = connid;
+
+    return resid;
 }
 
 
 /*
  * Get back the result pointer from the Id
  */
-PGresult   *
-PgGetResultId(Pg_clientData * cd, char *id)
+PGresult *
+PgGetResultId(Tcl_Interp *interp, char *id)
 {
-	Tcl_HashEntry *hent;
-	Pg_ResultId *resid;
-
-	hent = Tcl_FindHashEntry(&(cd->res_hash), id);
-	if (hent == NULL)
-	{
-		return (PGresult *) NULL;
-	}
-
-	resid = (Pg_ResultId *) Tcl_GetHashValue(hent);
-	return resid->result;
+    Pg_ConnectionId	*connid;
+    int			resid;
+
+    if (!id)
+	return NULL;
+    resid = getresid(interp, id, &connid);
+    if (resid == -1)
+	return NULL;
+    return connid->results[resid];
 }
 
 
@@ -169,51 +338,41 @@ PgGetResultId(Pg_clientData * cd, char *id)
  * Remove a result Id from the hash tables
  */
 void
-PgDelResultId(Pg_clientData * cd, char *id)
+PgDelResultId(Tcl_Interp *interp, char *id)
 {
-	Tcl_HashEntry *hent;
-	Tcl_HashEntry *hent2;
-	Pg_ResultId *resid;
-
-	hent = Tcl_FindHashEntry(&(cd->res_hash), id);
-	if (hent == NULL)
-	{
-		return;
-	}
-
-	resid = (Pg_ResultId *) Tcl_GetHashValue(hent);
-	if (resid->connection != NULL)
-	{
-		hent2 = Tcl_FindHashEntry(&(resid->connection->res_hash), id);
-		if (hent2 != NULL)
-		{
-			Tcl_DeleteHashEntry(hent2);
-		}
-	}
+    Pg_ConnectionId	*connid;
+    int			resid;
 
-	Tcl_DeleteHashEntry(hent);
-	ckfree(resid);
+    resid = getresid(interp, id, &connid);
+    if (resid == -1)
+	return;
+    connid->results[resid] = 0;
 }
 
 
 /*
  * Get the connection Id from the result Id
  */
-void
-PgGetConnByResultId(Pg_clientData * cd, char *id, char *resid_c)
+int
+PgGetConnByResultId(Tcl_Interp *interp, char *resid_c)
 {
-	Tcl_HashEntry *hent;
-	Pg_ResultId *resid;
+    char		*mark;
+    Tcl_Channel		conn_chan;
+
+    if (!(mark = strchr(resid_c, '.')))
+	goto error_out;
+    *mark = '\0';
+    conn_chan = Tcl_GetChannel(interp, resid_c, 0);
+    *mark = '.';
+    if(conn_chan && Tcl_GetChannelType(conn_chan) != &Pg_ConnType) {
+	Tcl_SetResult(interp, Tcl_GetChannelName(conn_chan), TCL_VOLATILE);
+	return TCL_OK;
+    }
+
+  error_out:
+    Tcl_ResetResult(interp);
+    Tcl_AppendResult(interp, resid_c, " is not a valid connection\n", 0);
+    return TCL_ERROR;
+}
 
-	hent = Tcl_FindHashEntry(&(cd->res_hash), id);
-	if (hent == NULL)
-	{
-		return;
-	}
 
-	resid = (Pg_ResultId *) Tcl_GetHashValue(hent);
-	if (resid->connection != NULL)
-	{
-		strcpy(id, resid->connection->id);
-	}
-}
diff --git a/src/interfaces/libpgtcl/pgtclId.h b/src/interfaces/libpgtcl/pgtclId.h
index 130f017ec6ec39a740c67af283d6f458de6fa3c7..648531fdc7fe9dd8fba4248d3056635f04dd89f7 100644
--- a/src/interfaces/libpgtcl/pgtclId.h
+++ b/src/interfaces/libpgtcl/pgtclId.h
@@ -1,22 +1,47 @@
 /*-------------------------------------------------------------------------
- *
- * pgtclId.h--
- *	  useful routines to convert between strings and pointers
- *	Needed because everything in tcl is a string, but often, pointers
- *	to data structures are needed.
- *
- *
- * Copyright (c) 1994, Regents of the University of California
- *
- * $Id: pgtclId.h,v 1.5 1997/09/08 21:55:26 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
+*
+* pgtclId.h--
+*    useful routines to convert between strings and pointers
+*  Needed because everything in tcl is a string, but often, pointers
+*  to data structures are needed.
+*    
+*
+* Copyright (c) 1994, Regents of the University of California
+*
+* $Id: pgtclId.h,v 1.6 1998/03/15 08:03:00 scrappy Exp $
+*
+*-------------------------------------------------------------------------
+*/
+  
+extern void PgSetConnectionId(Tcl_Interp *interp, PGconn *conn);
 
-extern void PgSetConnectionId(Pg_clientData * cd, char *id, PGconn *conn);
-extern PGconn *PgGetConnectionId(Pg_clientData * cd, char *id);
-extern void PgDelConnectionId(Pg_clientData * cd, char *id);
-extern void PgSetResultId(Pg_clientData * cd, char *id, char *connid, PGresult *res);
-extern PGresult *PgGetResultId(Pg_clientData * cd, char *id);
-extern void PgDelResultId(Pg_clientData * cd, char *id);
-extern void PgGetConnByResultId(Pg_clientData * cd, char *id, char *resid);
+#if (TCL_MAJOR_VERSION == 7 && TCL_MINOR_VERSION == 5)
+# define DRIVER_DEL_PROTO ClientData cData, Tcl_Interp *interp, \
+ 	Tcl_File inFile, Tcl_File outFile
+# define DRIVER_OUTPUT_PROTO ClientData cData, Tcl_File outFile, char *buf, \
+	int bufSize, int *errorCodePtr
+# define DRIVER_INPUT_PROTO ClientData cData, Tcl_File inFile, char *buf, \
+	int bufSize, int *errorCodePtr
+#else
+# define DRIVER_OUTPUT_PROTO ClientData cData, char *buf, int bufSize, \
+	int *errorCodePtr
+# define DRIVER_INPUT_PROTO ClientData cData, char *buf, int bufSize, \
+	int *errorCodePtr
+# define DRIVER_DEL_PROTO ClientData cData, Tcl_Interp *interp
+#endif
+
+extern PGconn *PgGetConnectionId(Tcl_Interp *interp, char *id, \
+	Pg_ConnectionId **);
+extern PgDelConnectionId(DRIVER_DEL_PROTO);
+extern int PgOutputProc(DRIVER_OUTPUT_PROTO);
+extern PgInputProc(DRIVER_INPUT_PROTO);
+extern int PgSetResultId(Tcl_Interp *interp, char *connid, PGresult *res);
+extern PGresult *PgGetResultId(Tcl_Interp *interp, char *id);
+extern void PgDelResultId(Tcl_Interp *interp, char *id);
+extern int PgGetConnByResultId(Tcl_Interp *interp, char *resid);
+
+#if (TCL_MAJOR_VERSION < 8)
+extern Tcl_File PgGetFileProc(ClientData cData, int direction);
+#endif
+
+extern Tcl_ChannelType Pg_ConnType;