summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc G. Fournier1996-10-30 06:18:42 +0000
committerMarc G. Fournier1996-10-30 06:18:42 +0000
commit552620c8b24a53c13da540fc0d5f316597e9d2e8 (patch)
treedf4dd916d5cc643fd79a4ae0be2d1ee3cb3f789b
parent582982e613693c8d4d5a375b9212b33906def0b7 (diff)
Changes to libpgtcl submitted by: [email protected] (Jan Wieck)
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.
-rw-r--r--src/interfaces/libpgtcl/Makefile4
-rw-r--r--src/interfaces/libpgtcl/libpgtcl.h5
-rw-r--r--src/interfaces/libpgtcl/pgtcl.c91
-rw-r--r--src/interfaces/libpgtcl/pgtclCmds.c159
-rw-r--r--src/interfaces/libpgtcl/pgtclCmds.h27
-rw-r--r--src/interfaces/libpgtcl/pgtclId.c189
-rw-r--r--src/interfaces/libpgtcl/pgtclId.h12
7 files changed, 368 insertions, 119 deletions
diff --git a/src/interfaces/libpgtcl/Makefile b/src/interfaces/libpgtcl/Makefile
index 25a2a0ac6ea..ff0e99e0f9f 100644
--- a/src/interfaces/libpgtcl/Makefile
+++ b/src/interfaces/libpgtcl/Makefile
@@ -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
diff --git a/src/interfaces/libpgtcl/libpgtcl.h b/src/interfaces/libpgtcl/libpgtcl.h
index 923bf594d70..7a5fa0364c1 100644
--- a/src/interfaces/libpgtcl/libpgtcl.h
+++ b/src/interfaces/libpgtcl/libpgtcl.h
@@ -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 */
diff --git a/src/interfaces/libpgtcl/pgtcl.c b/src/interfaces/libpgtcl/pgtcl.c
index f3758cd8fb1..d4021894e44 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.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 $
*
*-------------------------------------------------------------------------
*/
@@ -19,92 +19,145 @@
#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);
+}
diff --git a/src/interfaces/libpgtcl/pgtclCmds.c b/src/interfaces/libpgtcl/pgtclCmds.c
index 029a4329f96..91be2bd37f5 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.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 */
diff --git a/src/interfaces/libpgtcl/pgtclCmds.h b/src/interfaces/libpgtcl/pgtclCmds.h
index 23664de18f9..ea3ea84225f 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.2 1996/10/07 21:19:09 scrappy Exp $
+ * $Id: pgtclCmds.h,v 1.3 1996/10/30 06:18:40 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
@@ -14,6 +14,31 @@
#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 */
diff --git a/src/interfaces/libpgtcl/pgtclId.c b/src/interfaces/libpgtcl/pgtclId.c
index 00dffe7a883..53654b6da7f 100644
--- a/src/interfaces/libpgtcl/pgtclId.c
+++ b/src/interfaces/libpgtcl/pgtclId.c
@@ -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 $
*
*-------------------------------------------------------------------------
*/
@@ -21,31 +21,186 @@
#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);
+ }
}
+
+
diff --git a/src/interfaces/libpgtcl/pgtclId.h b/src/interfaces/libpgtcl/pgtclId.h
index af9839ceb1e..9cb431918aa 100644
--- a/src/interfaces/libpgtcl/pgtclId.h
+++ b/src/interfaces/libpgtcl/pgtclId.h
@@ -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);