Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 6ac2528

Browse files
committed
From: Randy Kunkee <kunkee@pluto.ops.NeoSoft.com>
It is my hope that the following "patches" to libpgtcl get included in the next release. See the update to the README file to get a full description of the changes. This version of libpgtcl is completely interpreter-safe, implements the database connection handle as a channel (no events yet, but will make it a lot easier to do fileevents on it in the future), and supports the SQL "copy table to stdout" and "copy table from stdin" commands, with the I/O being from and to the connection handle. The connection and result handles are formatted in a way to make access to the tables more efficient.
1 parent 609026b commit 6ac2528

File tree

7 files changed

+1374
-1336
lines changed

7 files changed

+1374
-1336
lines changed

src/interfaces/libpgtcl/Makefile.in

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#
88
#
99
# IDENTIFICATION
10-
# $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/Makefile.in,v 1.3 1998/02/13 05:09:57 scrappy Exp $
10+
# $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/Makefile.in,v 1.4 1998/03/15 08:02:55 scrappy Exp $
1111
#
1212
#-------------------------------------------------------------------------
1313

@@ -37,7 +37,7 @@ ifeq ($(PORTNAME), linux)
3737
install-shlib-dep := install-shlib
3838
shlib := libpgtcl.so.1
3939
CFLAGS += $(CFLAGS_SL)
40-
LDFLAGS_SL = -shared -L $(SRCDIR)/interfaces/libpq -lpq
40+
LDFLAGS_SL = -shared -L$(SRCDIR)/interfaces/libpq -lpq
4141
endif
4242
endif
4343

@@ -53,14 +53,14 @@ endif
5353
ifeq ($(PORTNAME), i386_solaris)
5454
install-shlib-dep := install-shlib
5555
shlib := libpgtcl.so.1
56-
LDFLAGS_SL = -G -z text -L $(SRCDIR)/interfaces/libpq -lpq
56+
LDFLAGS_SL = -G -z text -L$(SRCDIR)/interfaces/libpq -lpq
5757
CFLAGS += $(CFLAGS_SL)
5858
endif
5959

6060
ifeq ($(PORTNAME), univel)
6161
install-shlib-dep := install-shlib
6262
shlib := libpgtcl.so.1
63-
LDFLAGS_SL = -G -z text -L $(SRCDIR)/interfaces/libpq -lpq
63+
LDFLAGS_SL = -G -z text -L$(SRCDIR)/interfaces/libpq -lpq
6464
CFLAGS += $(CFLAGS_SL)
6565
endif
6666

src/interfaces/libpgtcl/README

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,38 @@
1-
libpgtcl is a library that implements Tcl commands for front-end clients
2-
to interact with the PostgreSQL backend. See libpgtcl.doc for details.
3-
1+
libpgtcl is a library that implements Tcl commands for front-end
2+
clients to interact with the Postgresql 6.3 (and perhaps later)
3+
backends. See libpgtcl.doc for details.
4+
45
For an example of how to build a new tclsh to use libpgtcl, see the
56
directory ../bin/pgtclsh
67

8+
Note this version is modified by NeoSoft to have the following additional
9+
features:
10+
11+
1. Postgres connections are a valid Tcl channel, and can therefore
12+
be manipulated by the interp command (ie. shared or transfered).
13+
A connection handle's results are transfered/shared with it.
14+
(Result handles are NOT channels, though it was tempting). Note
15+
that a "close $connection" is now functionally identical to a
16+
"pg_disconnect $connection", although pg_connect must be used
17+
to create a connection.
18+
19+
2. Result handles are changed in format: ${connection}.<result#>.
20+
This just means for a connection 'pgtcl0', they look like pgtcl0.0,
21+
pgtcl0.1, etc. Enforcing this syntax makes it easy to look up
22+
the real pointer by indexing into an array associated with the
23+
connection.
24+
25+
3. I/O routines are now defined for the connection handle. I/O to/from
26+
the connection is only valid under certain circumstances: following
27+
the execution of the queries "copy <table> from stdin" or
28+
"copy <table> to stdout". In these cases, the result handle obtains
29+
an intermediate status of "PGRES_COPY_IN" or "PGRES_COPY_OUT". The
30+
programmer is then expected to use Tcl gets or read commands on the
31+
database connection (not the result handle) to extract the copy data.
32+
For copy outs, read until the standard EOF indication is encountered.
33+
For copy ins, puts a single terminator (\.). The statement for this
34+
would be
35+
puts $conn "\\." or puts $conn {\.}
36+
In either case (upon detecting the EOF or putting the `\.', the status
37+
of the result handle will change to "PGRES_COMMAND_OK", and any further
38+
I/O attempts will cause a Tcl error.

src/interfaces/libpgtcl/pgtcl.c

Lines changed: 109 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtcl.c,v 1.9 1997/09/08 02:40:08 momjian Exp $
12+
* $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtcl.c,v 1.10 1998/03/15 08:02:57 scrappy Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -23,163 +23,122 @@
2323
#include "pgtclId.h"
2424

2525
/*
26-
* Pgtcl_Init
27-
* initialization package for the PGLITE Tcl package
26+
* Pgtcl_Init
27+
* initialization package for the PGLITE Tcl package
2828
*
2929
*/
3030

31-
/*
32-
* Tidy up forgotten postgres connection at Tcl_Exit
33-
*/
34-
static void
35-
Pgtcl_AtExit(ClientData cData)
36-
{
37-
Pg_clientData *cd = (Pg_clientData *) cData;
38-
Tcl_HashEntry *hent;
39-
Tcl_HashSearch hsearch;
40-
Pg_ConnectionId *connid;
41-
PGconn *conn;
42-
43-
while ((hent = Tcl_FirstHashEntry(&(cd->dbh_hash), &hsearch)) != NULL)
44-
{
45-
connid = (Pg_ConnectionId *) Tcl_GetHashValue(hent);
46-
conn = connid->conn;
47-
PgDelConnectionId(cd, connid->id);
48-
PQfinish(conn);
49-
}
50-
51-
Tcl_DeleteHashTable(&(cd->dbh_hash));
52-
Tcl_DeleteHashTable(&(cd->res_hash));
53-
Tcl_DeleteHashTable(&(cd->notify_hash));
54-
55-
Tcl_DeleteExitHandler(Pgtcl_AtExit, cData);
56-
}
57-
58-
/*
59-
* Tidy up forgotten postgres connections on Interpreter deletion
60-
*/
61-
static void
62-
Pgtcl_Shutdown(ClientData cData, Tcl_Interp * interp)
63-
{
64-
Pgtcl_AtExit(cData);
65-
}
66-
6731
int
68-
Pgtcl_Init(Tcl_Interp * interp)
32+
Pgtcl_Init (Tcl_Interp *interp)
6933
{
70-
Pg_clientData *cd;
71-
72-
/* Create and initialize the client data area */
73-
cd = (Pg_clientData *) ckalloc(sizeof(Pg_clientData));
74-
Tcl_InitHashTable(&(cd->dbh_hash), TCL_STRING_KEYS);
75-
Tcl_InitHashTable(&(cd->res_hash), TCL_STRING_KEYS);
76-
Tcl_InitHashTable(&(cd->notify_hash), TCL_STRING_KEYS);
77-
cd->dbh_count = 0L;
78-
cd->res_count = 0L;
79-
80-
/* Arrange for tidy up when interpreter is deleted or Tcl exits */
81-
Tcl_CallWhenDeleted(interp, Pgtcl_Shutdown, (ClientData) cd);
82-
Tcl_CreateExitHandler(Pgtcl_AtExit, (ClientData) cd);
83-
84-
/* register all pgtcl commands */
85-
Tcl_CreateCommand(interp,
86-
"pg_conndefaults",
87-
Pg_conndefaults,
88-
(ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
89-
90-
Tcl_CreateCommand(interp,
91-
"pg_connect",
92-
Pg_connect,
93-
(ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
94-
95-
Tcl_CreateCommand(interp,
96-
"pg_disconnect",
97-
Pg_disconnect,
98-
(ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
99-
100-
Tcl_CreateCommand(interp,
101-
"pg_exec",
102-
Pg_exec,
103-
(ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
104-
105-
Tcl_CreateCommand(interp,
106-
"pg_select",
107-
Pg_select,
108-
(ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
109-
110-
Tcl_CreateCommand(interp,
111-
"pg_result",
112-
Pg_result,
113-
(ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
114-
115-
Tcl_CreateCommand(interp,
116-
"pg_lo_open",
117-
Pg_lo_open,
118-
(ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
119-
120-
Tcl_CreateCommand(interp,
121-
"pg_lo_close",
122-
Pg_lo_close,
123-
(ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
124-
125-
Tcl_CreateCommand(interp,
126-
"pg_lo_read",
127-
Pg_lo_read,
128-
(ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
129-
130-
Tcl_CreateCommand(interp,
131-
"pg_lo_write",
132-
Pg_lo_write,
133-
(ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
134-
135-
Tcl_CreateCommand(interp,
136-
"pg_lo_lseek",
137-
Pg_lo_lseek,
138-
(ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
139-
140-
Tcl_CreateCommand(interp,
141-
"pg_lo_creat",
142-
Pg_lo_creat,
143-
(ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
144-
145-
Tcl_CreateCommand(interp,
146-
"pg_lo_tell",
147-
Pg_lo_tell,
148-
(ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
149-
150-
Tcl_CreateCommand(interp,
151-
"pg_lo_unlink",
152-
Pg_lo_unlink,
153-
(ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
154-
155-
Tcl_CreateCommand(interp,
156-
"pg_lo_import",
157-
Pg_lo_import,
158-
(ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
159-
160-
Tcl_CreateCommand(interp,
161-
"pg_lo_export",
162-
Pg_lo_export,
163-
(ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
164-
165-
Tcl_CreateCommand(interp,
166-
"pg_listen",
167-
Pg_listen,
168-
(ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
169-
170-
Tcl_CreateCommand(interp,
171-
"pg_notifies",
172-
Pg_notifies,
173-
(ClientData) cd, (Tcl_CmdDeleteProc *) NULL);
174-
175-
Tcl_PkgProvide(interp, "Pgtcl", "1.0");
176-
177-
return TCL_OK;
34+
35+
/* finish off the ChannelType struct. Much easier to do it here then
36+
* to guess where it might be by position in the struct. This is needed
37+
* for Tcl7.6 and beyond, which have the getfileproc.
38+
*/
39+
#if (TCL_MAJOR_VERSION == 7 && TCL_MINOR_VERSION == 6)
40+
Pg_ConnType.getFileProc = PgGetFileProc;
41+
#endif
42+
43+
/* register all pgtcl commands */
44+
Tcl_CreateCommand(interp,
45+
"pg_conndefaults",
46+
Pg_conndefaults,
47+
(ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
48+
49+
Tcl_CreateCommand(interp,
50+
"pg_connect",
51+
Pg_connect,
52+
(ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
53+
54+
Tcl_CreateCommand(interp,
55+
"pg_disconnect",
56+
Pg_disconnect,
57+
(ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
58+
59+
Tcl_CreateCommand(interp,
60+
"pg_exec",
61+
Pg_exec,
62+
(ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
63+
64+
Tcl_CreateCommand(interp,
65+
"pg_select",
66+
Pg_select,
67+
(ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
68+
69+
Tcl_CreateCommand(interp,
70+
"pg_result",
71+
Pg_result,
72+
(ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
73+
74+
Tcl_CreateCommand(interp,
75+
"pg_lo_open",
76+
Pg_lo_open,
77+
(ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
78+
79+
Tcl_CreateCommand(interp,
80+
"pg_lo_close",
81+
Pg_lo_close,
82+
(ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
83+
84+
Tcl_CreateCommand(interp,
85+
"pg_lo_read",
86+
Pg_lo_read,
87+
(ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
88+
89+
Tcl_CreateCommand(interp,
90+
"pg_lo_write",
91+
Pg_lo_write,
92+
(ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
93+
94+
Tcl_CreateCommand(interp,
95+
"pg_lo_lseek",
96+
Pg_lo_lseek,
97+
(ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
98+
99+
Tcl_CreateCommand(interp,
100+
"pg_lo_creat",
101+
Pg_lo_creat,
102+
(ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
103+
104+
Tcl_CreateCommand(interp,
105+
"pg_lo_tell",
106+
Pg_lo_tell,
107+
(ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
108+
109+
Tcl_CreateCommand(interp,
110+
"pg_lo_unlink",
111+
Pg_lo_unlink,
112+
(ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
113+
114+
Tcl_CreateCommand(interp,
115+
"pg_lo_import",
116+
Pg_lo_import,
117+
(ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
118+
119+
Tcl_CreateCommand(interp,
120+
"pg_lo_export",
121+
Pg_lo_export,
122+
(ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
123+
124+
Tcl_CreateCommand(interp,
125+
"pg_listen",
126+
Pg_listen,
127+
(ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
128+
129+
Tcl_CreateCommand(interp,
130+
"pg_notifies",
131+
Pg_notifies,
132+
(ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
133+
134+
Tcl_PkgProvide(interp, "Pgtcl", "1.1");
135+
136+
return TCL_OK;
178137
}
179138

180139

181140
int
182-
Pgtcl_SafeInit(Tcl_Interp * interp)
141+
Pgtcl_SafeInit (Tcl_Interp *interp)
183142
{
184-
return Pgtcl_Init(interp);
143+
return Pgtcl_Init(interp);
185144
}

0 commit comments

Comments
 (0)