]> granicus.if.org Git - postgresql/commitdiff
Changes to libpgtcl submitted by: wieck@sapserv.debis.de (Jan Wieck)
authorMarc G. Fournier <scrappy@hub.org>
Wed, 30 Oct 1996 06:18:42 +0000 (06:18 +0000)
committerMarc G. Fournier <scrappy@hub.org>
Wed, 30 Oct 1996 06:18:42 +0000 (06:18 +0000)
Adds:

    -lAttributes

        Returns another format of the results attribute list. Per
        attribute a sublist  of  {{attname}  atttype  attlen}  is
        returned  and  an  empty  string  if  no attributes where
        received.

    -numAttrs

        Returns the number of attributes in the result.

src/interfaces/libpgtcl/Makefile
src/interfaces/libpgtcl/libpgtcl.h
src/interfaces/libpgtcl/pgtcl.c
src/interfaces/libpgtcl/pgtclCmds.c
src/interfaces/libpgtcl/pgtclCmds.h
src/interfaces/libpgtcl/pgtclId.c
src/interfaces/libpgtcl/pgtclId.h

index 25a2a0ac6ea1bd9385869d672f78c4c688af9e41..ff0e99e0f9fb26cbcb27b710c8ac4790ae61cbce 100644 (file)
@@ -7,7 +7,7 @@
 #
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/Makefile,v 1.2 1996/07/23 03:38:42 scrappy Exp $
+#    $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/Makefile,v 1.3 1996/10/30 06:18:36 scrappy Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -23,6 +23,8 @@ CFLAGS+= -I$(HEADERDIR) \
         -I$(TCL_INCDIR) \
         -I$(srcdir)/libpq
 
+LIBLDLIBS+= -L$(LIBDIR) -lpq
+
 ifdef KRBVERS
 CFLAGS+= $(KRBFLAGS)
 endif
index 923bf594d70ee10d137b89eb48dd2473a9929f4f..7a5fa0364c13433f7e7f647305f9c5c1c5cf0160 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: libpgtcl.h,v 1.1.1.1 1996/07/09 06:22:16 scrappy Exp $
+ * $Id: libpgtcl.h,v 1.2 1996/10/30 06:18:37 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,6 +16,7 @@
 
 #include "tcl.h"
 
-extern int Pg_Init (Tcl_Interp *interp);
+extern int Pgtcl_Init (Tcl_Interp *interp);
+extern int Pgtcl_SafeInit (Tcl_Interp *interp);
 
 #endif /* LIBPGTCL_H */
index f3758cd8fb1069d49ef879943dab852f08ac45b5..d4021894e44f9ce97f1b4fdfafbff94ca51d9c85 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtcl.c,v 1.2 1996/10/07 21:19:06 scrappy Exp $
+ *    $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtcl.c,v 1.3 1996/10/30 06:18:38 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "pgtclCmds.h"
 
 /*
- * PG_Init 
+ * Pgtcl_Init 
  *    initialization package for the PGLITE Tcl package
  *
  */
 
+/*
+ * Tidy up forgotten postgres connection at Tcl_Exit
+ */
+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_DeleteExitHandler(Pgtcl_AtExit, cData);
+}
+
+/*
+ * Tidy up forgotten postgres connections on Interpreter deletion
+ */
+void
+Pgtcl_Shutdown (ClientData cData, Tcl_Interp *interp)
+{
+  Pgtcl_AtExit(cData);
+}
+
 int
-Pg_Init (Tcl_Interp *interp)
+Pgtcl_Init (Tcl_Interp *interp)
 {
-  /* register all pgtcl commands */
+  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);
+  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_connect",
                    Pg_connect,
-                   (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+                   (ClientData)cd, (Tcl_CmdDeleteProc*)NULL);
 
   Tcl_CreateCommand(interp,
                    "pg_disconnect",
                    Pg_disconnect,
-                   (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+                   (ClientData)cd, (Tcl_CmdDeleteProc*)NULL);
   
   Tcl_CreateCommand(interp,
                    "pg_exec",
                    Pg_exec,
-                   (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+                   (ClientData)cd, (Tcl_CmdDeleteProc*)NULL);
   
   Tcl_CreateCommand(interp,
                    "pg_select",
                    Pg_select,
-                   (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+                   (ClientData)cd, (Tcl_CmdDeleteProc*)NULL);
   
   Tcl_CreateCommand(interp,
                    "pg_result",
                    Pg_result,
-                   (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+                   (ClientData)cd, (Tcl_CmdDeleteProc*)NULL);
   
   Tcl_CreateCommand(interp,
                    "pg_lo_open",
                    Pg_lo_open,
-                   (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+                   (ClientData)cd, (Tcl_CmdDeleteProc*)NULL);
   
   Tcl_CreateCommand(interp,
                    "pg_lo_close",
                    Pg_lo_close,
-                   (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+                   (ClientData)cd, (Tcl_CmdDeleteProc*)NULL);
 
   Tcl_CreateCommand(interp,
                    "pg_lo_read",
                    Pg_lo_read,
-                   (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+                   (ClientData)cd, (Tcl_CmdDeleteProc*)NULL);
 
   Tcl_CreateCommand(interp,
                    "pg_lo_write",
                    Pg_lo_write,
-                   (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+                   (ClientData)cd, (Tcl_CmdDeleteProc*)NULL);
 
   Tcl_CreateCommand(interp,
                    "pg_lo_lseek",
                    Pg_lo_lseek,
-                   (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+                   (ClientData)cd, (Tcl_CmdDeleteProc*)NULL);
 
   Tcl_CreateCommand(interp,
                    "pg_lo_creat",
                    Pg_lo_creat,
-                   (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+                   (ClientData)cd, (Tcl_CmdDeleteProc*)NULL);
 
   Tcl_CreateCommand(interp,
                    "pg_lo_tell",
                    Pg_lo_tell,
-                   (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+                   (ClientData)cd, (Tcl_CmdDeleteProc*)NULL);
 
   Tcl_CreateCommand(interp,
                    "pg_lo_unlink",
                    Pg_lo_unlink,
-                   (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+                   (ClientData)cd, (Tcl_CmdDeleteProc*)NULL);
 
   Tcl_CreateCommand(interp,
                    "pg_lo_import",
                    Pg_lo_import,
-                   (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+                   (ClientData)cd, (Tcl_CmdDeleteProc*)NULL);
   
   Tcl_CreateCommand(interp,
                    "pg_lo_export",
                    Pg_lo_export,
-                   (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+                   (ClientData)cd, (Tcl_CmdDeleteProc*)NULL);
   
+  Tcl_PkgProvide(interp, "Pgtcl", "1.0");
+
   return TCL_OK;
 }
 
 
+int
+Pgtcl_SafeInit (Tcl_Interp *interp)
+{
+    return Pgtcl_Init(interp);
+}
index 029a4329f9637ae690dd3815692e4d3d9040b869..91be2bd37f53ea40ac6db1ff004a3b381a76093c 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclCmds.c,v 1.4 1996/10/07 21:19:07 scrappy Exp $
+ *    $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclCmds.c,v 1.5 1996/10/30 06:18:39 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -224,6 +224,7 @@ tcl_value (char *value)
 int
 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;
@@ -277,7 +278,7 @@ Pg_connect(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 
     conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
     if (conn->status == CONNECTION_OK) {
-       PgSetId(interp->result, (void*)conn);
+       PgSetConnectionId(cd, interp->result, conn);
        return TCL_OK;
     }
     else {
@@ -302,21 +303,21 @@ Pg_connect(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 int
 Pg_disconnect(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 {
+    Pg_clientData *cd = (Pg_clientData *)cData;
     PGconn *conn;
-    char* connPtrName;
 
     if (argc != 2) {
        Tcl_AppendResult(interp, "Wrong # of arguments\n", "pg_disconnect connection", 0);
        return TCL_ERROR;
     }
 
-    connPtrName = argv[1];
-    if (! PgValidId(connPtrName)) {
+    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 = (PGconn*)PgGetId(connPtrName);
+    PgDelConnectionId(cd, argv[1]);
     PQfinish(conn);
     return TCL_OK;
 }
@@ -335,26 +336,25 @@ Pg_disconnect(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 int
 Pg_exec(AlientData cData, Tcl_Interp *interp, int argc, char* argv[])
 {
+    Pg_clientData *cd = (Pg_clientData *)cData;
     PGconn *conn;
     PGresult *result;
-    char* connPtrName;
 
     if (argc != 3) {
        Tcl_AppendResult(interp, "Wrong # of arguments\n",
                         "pg_exec connection queryString", 0);
        return TCL_ERROR;
     }
-    connPtrName = argv[1];
 
-    if (! PgValidId(connPtrName)) {
-       Tcl_AppendResult(interp, "Argument passed in is not a valid connection\n", 0);
+    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 = (PGconn*)PgGetId(connPtrName);
     result = PQexec(conn, argv[2]);
     if (result) {
-       PgSetId(interp->result, (void*)result);
+       PgSetResultId(cd, interp->result, argv[1], result);
        return TCL_OK;
     }
     else {
@@ -386,6 +386,10 @@ Pg_exec(AlientData cData, Tcl_Interp *interp, int argc, char* argv[])
  the number of tuples in the query
  -attributes
  returns a list of the name/type pairs of the tuple attributes
+ -lAttributes
+ returns a list of the {name type len} entries of the tuple attributes
+ -numAttrs
+ returns the number of attributes returned by the query
  -getTuple tupleNumber
  returns the values of the tuple in a list
  -clear 
@@ -394,7 +398,7 @@ Pg_exec(AlientData cData, Tcl_Interp *interp, int argc, char* argv[])
 int
 Pg_result(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 {
-    char* resultPtrName;
+    Pg_clientData *cd = (Pg_clientData *)cData;
     PGresult *result;
     char *opt;
     int i;
@@ -408,13 +412,12 @@ Pg_result(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
        goto Pg_result_errReturn;
     }
 
-    resultPtrName = argv[1];
-    if (! PgValidId(resultPtrName)) {
+    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;
     }
 
-    result = (PGresult*)PgGetId(resultPtrName);
     opt = argv[2];
 
     if (strcmp(opt, "-status") == 0) {
@@ -426,10 +429,11 @@ Pg_result(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
        return TCL_OK;
     }
     else if (strcmp(opt, "-conn") == 0) {
-       PgSetId(interp->result, (void*)result->conn);
+       PgGetConnByResultId(cd, interp->result, argv[1]);
        return TCL_OK;
     }
     else if (strcmp(opt, "-clear") == 0) {
+       PgDelResultId(cd, argv[1]);
        PQclear(result);
        return TCL_OK;
     }
@@ -516,6 +520,21 @@ Pg_result(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
       }
       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),
+                                     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;
@@ -531,6 +550,8 @@ Pg_result(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
                     "\t-assignbyidx arrayVarName\n",
                     "\t-numTuples\n",
                     "\t-attributes\n"
+                    "\t-lAttributes\n"
+                    "\t-numAttrs\n"
                     "\t-getTuple tupleNumber\n",
                     "\t-clear\n",
                     "\t-oid\n",
@@ -553,8 +574,8 @@ Pg_result(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 int
 Pg_lo_open(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 {
+    Pg_clientData *cd = (Pg_clientData *)cData;
     PGconn *conn;
-    char* connPtrName;
     int lobjId;
     int mode;
     int fd;
@@ -564,13 +585,13 @@ Pg_lo_open(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
                         "pg_lo_open connection lobjOid mode", 0);
        return TCL_ERROR;
     }
-    connPtrName = argv[1];
-    if (! PgValidId(connPtrName)) {
-       Tcl_AppendResult(interp, "Argument passed in is not a valid connection\n", 0);
+  
+    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 = (PGconn*)PgGetId(connPtrName);
     lobjId = atoi(argv[2]);
     if (strlen(argv[3]) < 1 ||
        strlen(argv[3]) > 2)
@@ -623,8 +644,8 @@ Pg_lo_open(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 int
 Pg_lo_close(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 {
+    Pg_clientData *cd = (Pg_clientData *)cData;
     PGconn *conn;
-    char* connPtrName;
     int fd;
 
     if (argc != 3) {
@@ -633,13 +654,12 @@ Pg_lo_close(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
        return TCL_ERROR;
     }
 
-    connPtrName = argv[1];
-    if (! PgValidId(connPtrName)) {
-       Tcl_AppendResult(interp, "Argument passed in is not a valid connection\n", 0);
+    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 = (PGconn*)PgGetId(connPtrName);
     fd = atoi(argv[2]);
     sprintf(interp->result,"%d",lo_close(conn,fd));
     return TCL_OK;
@@ -659,8 +679,8 @@ 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_clientData *cd = (Pg_clientData *)cData;
     PGconn *conn;
-    char* connPtrName;
     int fd;
     int nbytes = 0;
     char *buf;
@@ -673,13 +693,12 @@ Pg_lo_read(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
        return TCL_ERROR;
     }
 
-    connPtrName = argv[1];
-    if (! PgValidId(connPtrName)) {
-       Tcl_AppendResult(interp, "Argument passed in is not a valid connection\n", 0);
+    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 = (PGconn*)PgGetId(connPtrName);
     fd = atoi(argv[2]);
 
     bufVar = argv[3];
@@ -712,8 +731,8 @@ Pg_lo_write
 int
 Pg_lo_write(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 {
+    Pg_clientData *cd = (Pg_clientData *)cData;
     PGconn *conn;
-    char *connPtrName;
     char *buf;
     int fd;
     int nbytes = 0;
@@ -725,13 +744,12 @@ Pg_lo_write(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
        return TCL_ERROR;
     }
 
-    connPtrName = argv[1];
-    if (! PgValidId(connPtrName)) {
-       Tcl_AppendResult(interp, "Argument passed in is not a valid connection\n", 0);
+    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 = (PGconn*)PgGetId(connPtrName);
     fd = atoi(argv[2]);
 
     buf = argv[3];
@@ -761,8 +779,8 @@ whence can be either
 int
 Pg_lo_lseek(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 {
+    Pg_clientData *cd = (Pg_clientData *)cData;
     PGconn *conn;
-    char* connPtrName;
     int fd;
     char *whenceStr;
     int offset, whence;
@@ -773,13 +791,12 @@ Pg_lo_lseek(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
        return TCL_ERROR;
     }
 
-    connPtrName = argv[1];
-    if (! PgValidId(connPtrName)) {
-       Tcl_AppendResult(interp, "Argument passed in is not a valid connection\n", 0);
+    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 = (PGconn*)PgGetId(connPtrName);
     fd = atoi(argv[2]);
 
     offset = atoi(argv[3]);
@@ -815,8 +832,8 @@ for now, we don't support any additional storage managers.
 int
 Pg_lo_creat(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 {
+    Pg_clientData *cd = (Pg_clientData *)cData;
     PGconn *conn;
-    char* connPtrName;
     char *modeStr;
     char *modeWord;
     int mode;
@@ -827,14 +844,12 @@ Pg_lo_creat(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
        return TCL_ERROR;
     }
 
-    connPtrName = argv[1];
-    if (! PgValidId(connPtrName)) {
-       Tcl_AppendResult(interp, "Argument passed in is not a valid connection\n", 0);
+    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 = (PGconn*)PgGetId(connPtrName);
-
     modeStr = argv[2];
 
     modeWord = strtok(modeStr,"|");
@@ -880,8 +895,8 @@ Pg_lo_tell
 int
 Pg_lo_tell(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 {
+    Pg_clientData *cd = (Pg_clientData *)cData;
     PGconn *conn;
-    char* connPtrName;
     int fd;
 
     if (argc != 3) {
@@ -890,13 +905,12 @@ Pg_lo_tell(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
        return TCL_ERROR;
     }
 
-    connPtrName = argv[1];
-    if (! PgValidId(connPtrName)) {
-       Tcl_AppendResult(interp, "Argument passed in is not a valid connection\n", 0);
+    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 = (PGconn*)PgGetId(connPtrName);
     fd = atoi(argv[2]);
 
     sprintf(interp->result,"%d",lo_tell(conn,fd));
@@ -916,8 +930,8 @@ Pg_lo_unlink
 int
 Pg_lo_unlink(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 {
+    Pg_clientData *cd = (Pg_clientData *)cData;
     PGconn *conn;
-    char* connPtrName;
     int lobjId;
     int retval;
 
@@ -927,13 +941,12 @@ Pg_lo_unlink(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
        return TCL_ERROR;
     }
 
-    connPtrName = argv[1];
-    if (! PgValidId(connPtrName)) {
-       Tcl_AppendResult(interp, "Argument passed in is not a valid connection\n", 0);
+    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 = (PGconn*)PgGetId(connPtrName);
     lobjId = atoi(argv[2]);
 
     retval = lo_unlink(conn,lobjId);
@@ -960,8 +973,8 @@ Pg_lo_import
 int
 Pg_lo_import(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 {
+    Pg_clientData *cd = (Pg_clientData *)cData;
     PGconn *conn;
-    char* connPtrName;
     char* filename;
     Oid lobjId;
 
@@ -971,13 +984,12 @@ Pg_lo_import(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
        return TCL_ERROR;
     }
 
-    connPtrName = argv[1];
-    if (! PgValidId(connPtrName)) {
-       Tcl_AppendResult(interp, "Argument passed in is not a valid connection\n", 0);
+    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 = (PGconn*)PgGetId(connPtrName);
     filename = argv[2];
 
     lobjId = lo_import(conn,filename);
@@ -1001,8 +1013,8 @@ Pg_lo_export
 int
 Pg_lo_export(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
 {
+    Pg_clientData *cd = (Pg_clientData *)cData;
     PGconn *conn;
-    char* connPtrName;
     char* filename;
     Oid lobjId;
     int retval;
@@ -1013,13 +1025,12 @@ Pg_lo_export(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
        return TCL_ERROR;
     }
 
-    connPtrName = argv[1];
-    if (! PgValidId(connPtrName)) {
-       Tcl_AppendResult(interp, "Argument passed in is not a valid connection\n", 0);
+    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 = (PGconn*)PgGetId(connPtrName);
     lobjId = atoi(argv[2]);
     filename = argv[3];
 
@@ -1055,6 +1066,7 @@ 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_clientData *cd = (Pg_clientData *)cData;
        PGconn *conn;
        PGresult *result;
     int ch_flag, r;
@@ -1073,15 +1085,12 @@ Pg_select(ClientData cData, Tcl_Interp *interp, int argc, char **argv)
                return TCL_ERROR;
        }
 
-    if (! PgValidId(argv[1]))
-       {
-               Tcl_AppendResult(interp,
-                               "Argument passed in 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;
     }
   
-    conn = (PGconn*)PgGetId(argv[1]);
-
        if ((result = PQexec(conn, argv[2])) == 0)
     {
                /* error occurred during the query */
index 23664de18f98493654cb7e83d0515d47e6638ce8..ea3ea84225fb53af33beb010df47457fc3be52dd 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pgtclCmds.h,v 1.2 1996/10/07 21:19:09 scrappy Exp $
+ * $Id: pgtclCmds.h,v 1.3 1996/10/30 06:18:40 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
 #define PGTCLCMDS_H
 
 #include "tcl.h"
+#include "libpq/pqcomm.h"
+#include "libpq-fe.h"
+#include "libpq/libpq-fs.h"
+
+typedef struct Pg_clientData_s {
+    Tcl_HashTable      dbh_hash;
+    Tcl_HashTable      res_hash;
+    long               dbh_count;
+    long               res_count;
+} Pg_clientData;
+
+
+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;
+
 
 /* **************************/
 /* registered Tcl functions */
index 00dffe7a88322e02216e14577f09e47f30d1ecec..53654b6da7f5ac18666ec1b10854def9fb3c8b11 100644 (file)
@@ -12,7 +12,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclId.c,v 1.1.1.1 1996/07/09 06:22:16 scrappy Exp $
+ *    $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclId.c,v 1.2 1996/10/30 06:18:41 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include <string.h>
 #include "tcl.h"
 
+#include "pgtclCmds.h"
 #include "pgtclId.h"
 
-/* convert a pointer into a string */
+/*
+ * Create the Id for a new connection and hash it
+ */
+void
+PgSetConnectionId(Pg_clientData *cd, char *id, 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);
+}
+
+
+/*
+ * Get back the connection from the Id
+ */
+PGconn *
+PgGetConnectionId(Pg_clientData *cd, char *id)
+{
+    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;
+}
+
+
+/*
+ * Remove a connection Id from the hash table and
+ * close all portals the user forgot.
+ */
+void
+PgDelConnectionId(Pg_clientData *cd, char *id)
+{
+    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);
+}
+
+
+/*
+ * Create a new result Id and hash it
+ */
 void
-PgSetId(char *id, void *ptr)
+PgSetResultId(Pg_clientData *cd, char *id, char *connid_c, PGresult *res)
+{
+    Tcl_HashEntry      *hent;
+    Pg_ConnectionId    *connid;
+    Pg_ResultId                *resid;
+    int                        hnew;
+
+    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);
+
+    if(connid != NULL) {
+        hent = Tcl_CreateHashEntry(&(connid->res_hash), resid->id, &hnew);
+       Tcl_SetHashValue(hent, (ClientData)resid);
+    }
+}
+
+
+/*
+ * Get back the result pointer from the Id
+ */
+PGresult *
+PgGetResultId(Pg_clientData *cd, char *id)
 {
-  (void) sprintf(id, "pgp%lx", (long) ptr);
+    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;
 }
 
 
-/* get back a pointer from a string */
-void *
-PgGetId(char *id)
+/*
+ * Remove a result Id from the hash tables
+ */
+void
+PgDelResultId(Pg_clientData *cd, char *id)
 {
-  long ptr; 
-  ptr = strtol(id+3, NULL, 16);
-  return (void *) ptr;
+    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);
+       }
+    }
+
+    Tcl_DeleteHashEntry(hent);
+    ckfree(resid);
 }
 
-/* check to see if the string is a valid pgtcl pointer */
-int 
-PgValidId(char* id)
+
+/*
+ * Get the connection Id from the result Id
+ */
+void
+PgGetConnByResultId(Pg_clientData *cd, char *id, char *resid_c)
 {
-    if ( (strlen(id) > 3) && id[0]=='p' && id[1] == 'g' && id[2] == 'p')
-       return 1;
-    else
-       return 0;
+    Tcl_HashEntry      *hent;
+    Pg_ResultId                *resid;
+
+    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);
+    }
 }
+
+
index af9839ceb1ee8fdb7565fff69de05ac4a8bdaad0..9cb431918aae18ed03e0b1b197c68ee494b06d35 100644 (file)
@@ -8,11 +8,15 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pgtclId.h,v 1.1.1.1 1996/07/09 06:22:16 scrappy Exp $
+ * $Id: pgtclId.h,v 1.2 1996/10/30 06:18:42 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
 
-extern void PgSetId(char *id, void *ptr);
-extern void* PgGetId(char *id);
-extern int PgValidId(char* id);
+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);