libpgtcl - backend version information patch
I've attached a patch for libpgtcl which adds access to backend version
numbers.
This is via a new command:
pg_version <db channel> <major varname> ?<minor varname>? ?<patch varname>?
Using readonly variables rather than a command was my first choice but I
decided that it was inappropiate for the library to start assigning global
variable(s) when that's really the applications job and the command interface
is consistent with the rest of the interface.
Obviously, backend version numbers are specific to a particular connection. So
I've created a new data structure, to keep the information as a distinct unit,
and added an instance of the new structure to the Pg_ConnectionId type. The
version information is retrieved from the given connection on first use of
pg_version and cached in the new data structure for subsequent accesses.
In addition to filling the named variables in the callers scope with version
numbers/strings the command returns the complete string as returned by
version(). It's not possible to turn this return off at the moment but I don't
see it as a problem since normal methods of stopping unwanted values returned
from procedures can be applied in the application if required.
Perhaps the most significant change is that I've increased the package's
version number from 1.3 to 1.4. This will adversly effect anyone using an
application that requires a specific version of the package where their
postgres installation is updated but their application has not been. I can't
imagine there are many applications out there using the package management
features of TCL though.
I envisage this patch applied to 7.3 tip and to 7.2 for the 7.2.2 release
mentioned a couple of days ago. The only problem with doing this for 7.2 that I
can see is where people doing the 'package -exact require Pgtcl 1.x' thing, and
how many of those are there? Even PgAccess doesn't use that.
Note for commiter et al,, this patch also includes one change made in 7.3devel
and not 7.2.1. That is where a test of the return value from a Tcl_SetVar call
has been corrected from a test against TCL_OK to NULL. This is correct and
should be applied to the 7.2 branch in my view, however, I do not know if this
has already been applied there so something to watch out for.
--
Nigel J. Andrews
Director
---
Logictree Systems Limited
Computer Consultants
Attachments:
libpgtcl.patchtext/plain; charset=US-ASCII; name=libpgtcl.patchDownload
Index: src/interfaces/libpgtcl/pgtcl.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/interfaces/libpgtcl/pgtcl.c,v
retrieving revision 1.24
diff -c -r1.24 pgtcl.c
*** src/interfaces/libpgtcl/pgtcl.c 2001/10/25 05:50:12 1.24
--- src/interfaces/libpgtcl/pgtcl.c 2002/05/16 22:07:12
***************
*** 152,158 ****
Pg_listen,
(ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
! Tcl_PkgProvide(interp, "Pgtcl", "1.3");
return TCL_OK;
}
--- 152,163 ----
Pg_listen,
(ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
! Tcl_CreateCommand(interp,
! "pg_version",
! Pg_version,
! (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
!
! Tcl_PkgProvide(interp, "Pgtcl", "1.4");
return TCL_OK;
}
Index: src/interfaces/libpgtcl/pgtclCmds.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/interfaces/libpgtcl/pgtclCmds.c,v
retrieving revision 1.61
diff -c -r1.61 pgtclCmds.c
*** src/interfaces/libpgtcl/pgtclCmds.c 2002/03/04 02:41:49 1.61
--- src/interfaces/libpgtcl/pgtclCmds.c 2002/05/16 22:07:13
***************
*** 423,428 ****
--- 423,431 ----
Tcl_UnregisterChannel(interp, connid->notifier_channel);
#endif
+ if (connid->version.string)
+ ckfree(connid->version.string);
+
return Tcl_UnregisterChannel(interp, conn_chan);
}
***************
*** 1967,1971 ****
--- 1970,2106 ----
}
ckfree(caserelname);
+ return TCL_OK;
+ }
+
+ /**********************************
+ Pg_version
+ get backend version numbers
+
+ syntax:
+ pg_version connection majorvar ?minorvar? ?patchvar?
+
+ the return result is either an error message or the full version string
+ returned from the backend with filled in major, minor and patch version
+ variables
+ **********************************/
+
+ int
+ Pg_version(ClientData cData, Tcl_Interp *interp, int argc, char *argv[])
+ {
+ Pg_ConnectionId *connid;
+ PGconn *conn;
+ struct Pg_VersionNumber_s *version;
+
+ if (argc < 3 || argc > 5)
+ {
+ Tcl_AppendResult(interp, "Wrong # of arguments\n",
+ "pg_version connection majorvar ?minorvar? ?patchvar?", 0);
+ return TCL_ERROR;
+ }
+
+ conn = PgGetConnectionId(interp, argv[1], &connid);
+ if (conn == (PGconn *) NULL)
+ return TCL_ERROR;
+
+ version = &connid->version;
+
+ if (!version->string)
+ {
+ PGresult *result;
+
+ result = PQexec(conn, "SELECT version()");
+
+ /* Transfer any notify events from libpq to Tcl event queue. */
+ PgNotifyTransferEvents(connid);
+
+ if (result && PQntuples(result))
+ {
+ char *vers = PQgetvalue(result, 0, 0);
+ char *tok;
+
+ version->string = ckalloc(strlen(vers)*2+3);
+ strcpy(version->string, vers);
+ strcpy(version->string + strlen(vers) + 1, vers);
+
+ tok = strtok(version->string + strlen(vers) + 1, " ");
+ while (tok)
+ {
+ char *ecnv;
+ int v = strtol(tok, &ecnv, 10);
+
+ if (ecnv != tok)
+ {
+ version->major = v;
+ version->major_str = tok;
+ *ecnv = '\0';
+
+ tok = ecnv + 1;
+ v = strtol(tok, &ecnv, 10);
+ if (ecnv != tok)
+ {
+ version->minor = v;
+ version->minor_str = tok;
+ if (*ecnv)
+ {
+ char *necnv = ecnv;
+
+ if (!isspace(*necnv))
+ necnv++;
+
+ /* these tests are going to skip making a
+ patch value if the has only a single
+ none numeric character after the minor
+ version, but I don't think that's important */
+ if (*necnv && !isspace(*necnv))
+ {
+ tok = necnv;
+ v = strtol(tok, &necnv, 10);
+ version->patch_str = tok;
+ if (necnv != tok)
+ version->patch = v;
+ else
+ if (tok != ecnv)
+ memmove(tok, ecnv, strlen(ecnv)+1);
+ }
+
+ *ecnv = '\0';
+ }
+ }
+
+ break;
+ }
+ else
+ tok = strtok((char *)NULL, " ");
+ }
+ }
+ else
+ {
+ /* error occurred during the query */
+ Tcl_SetResult(interp, PQerrorMessage(conn), TCL_VOLATILE);
+ return TCL_ERROR;
+ }
+ }
+
+ if (!Tcl_SetVar(interp,
+ argv[2],
+ version->major_str ? version->major_str : "",
+ TCL_LEAVE_ERR_MSG)
+ || (argc > 3
+ && !Tcl_SetVar(interp,
+ argv[3],
+ version->minor_str ? version->minor_str : "",
+ TCL_LEAVE_ERR_MSG))
+ || (argc > 4
+ && !Tcl_SetVar(interp,
+ argv[4],
+ version->patch_str ? version->patch_str : "",
+ TCL_LEAVE_ERR_MSG)))
+ {
+ return TCL_ERROR;
+ }
+
+ Tcl_SetResult(interp, version->string, TCL_VOLATILE);
+
return TCL_OK;
}
Index: src/interfaces/libpgtcl/pgtclCmds.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/interfaces/libpgtcl/pgtclCmds.h,v
retrieving revision 1.25
diff -c -r1.25 pgtclCmds.h
*** src/interfaces/libpgtcl/pgtclCmds.h 2001/11/05 17:46:37 1.25
--- src/interfaces/libpgtcl/pgtclCmds.h 2002/05/16 22:07:14
***************
*** 50,55 ****
--- 50,66 ----
Tcl_HashTable notify_hash; /* Active pg_listen requests */
} Pg_TclNotifies;
+ struct Pg_VersionNumber_s
+ {
+ char *string;
+ char *major_str;
+ int major;
+ char *minor_str;
+ int minor;
+ char *patch_str;
+ int patch;
+ };
+
typedef struct Pg_ConnectionId_s
{
char id[32];
***************
*** 70,75 ****
--- 81,87 ----
#else
int notifier_socket; /* PQsocket on which notifier is listening */
#endif
+ struct Pg_VersionNumber_s version; /* backend version numbers */
} Pg_ConnectionId;
/* Values of res_copyStatus */
***************
*** 127,132 ****
--- 139,147 ----
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_version(
ClientData cData, Tcl_Interp *interp, int argc, char *argv[]);
#endif /* PGTCLCMDS_H */
Index: src/interfaces/libpgtcl/pgtclId.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/interfaces/libpgtcl/pgtclId.c,v
retrieving revision 1.29
diff -c -r1.29 pgtclId.c
*** src/interfaces/libpgtcl/pgtclId.c 2001/11/05 17:46:37 1.29
--- src/interfaces/libpgtcl/pgtclId.c 2002/05/16 22:07:14
***************
*** 188,193 ****
--- 188,198 ----
connid->results[i] = NULL;
connid->notify_list = NULL;
connid->notifier_running = 0;
+ connid->version.string = (char *)NULL;
+ connid->version.major_str = (char *)NULL;
+ connid->version.minor_str = (char *)NULL;
+ connid->version.patch_str = (char *)NULL;
+ connid->version.major = connid->version.minor = connid->version.patch = 0;
sprintf(connid->id, "pgsql%d", PQsocket(conn));
Nigel J. Andrews writes:
I've attached a patch for libpgtcl which adds access to backend version
numbers.This is via a new command:
pg_version <db channel> <major varname> ?<minor varname>? ?<patch varname>?
This doesn't truly reflect the way PostgreSQL version numbers are handled.
Say for 7.2.1, the "major" is really "7.2" and the minor is "1". With the
interface you proposed, the information major == 7 doesn't really convey
any useful information.
I envisage this patch applied to 7.3 tip and to 7.2 for the 7.2.2
release mentioned a couple of days ago. The only problem with doing this
for 7.2 that I can see is where people doing the 'package -exact require
Pgtcl 1.x' thing, and how many of those are there? Even PgAccess doesn't
use that.
Normally we only put bug fixes in minor releases. PgAccess may get an
exception, but bumping the version number of a library is stretching it a
little. If you're intending to use the function for PgAccess, why not
make it internal to PgAccess? That way you can tune the major/minor thing
exactly how you need it.
--
Peter Eisentraut peter_e@gmx.net
[My apolgies if this turns up in the lists twice (now three times) but my
mailer claims it's been in the queue for them too long. Not sure why it
thinks that since it's only a few minutes since I sent it.]
On Fri, 17 May 2002, Peter Eisentraut wrote:
Nigel J. Andrews writes:
I've attached a patch for libpgtcl which adds access to backend version
numbers.This is via a new command:
pg_version <db channel> <major varname> ?<minor varname>? ?<patch varname>?
This doesn't truly reflect the way PostgreSQL version numbers are handled.
Say for 7.2.1, the "major" is really "7.2" and the minor is "1". With the
interface you proposed, the information major == 7 doesn't really convey
any useful information.
Ah, oops. I'll change it. I withdraw the patch submission I made yesterday
(now two days back).
I envisage this patch applied to 7.3 tip and to 7.2 for the 7.2.2
release mentioned a couple of days ago. The only problem with doing this
for 7.2 that I can see is where people doing the 'package -exact require
Pgtcl 1.x' thing, and how many of those are there? Even PgAccess doesn't
use that.Normally we only put bug fixes in minor releases. PgAccess may get an
exception, but bumping the version number of a library is stretching it a
little. If you're intending to use the function for PgAccess, why not
make it internal to PgAccess? That way you can tune the major/minor thing
exactly how you need it.
It did occur to me this morning that having it applied for 7.2.2 was perhaps
silly as it was introducing a new feature and not a bug fix.
This feature could be added to PgAccess but I felt it was general enough to be
placed in the interface library. I think someone else suggested such a place a
couple of weeks ago also. If there is a concensus that this should be done in
the application layer I'll happily drop this patch completely.
--
Nigel J. Andrews
Director
---
Logictree Systems Limited
Computer Consultants
Import Notes
Reply to msg id not found: Pine.LNX.4.21.0205171520390.601-100000@ponder.fairway2k.co.uk | Resolved by subject fallback
This is similar to the same patch as I submitted Thursday, and hopefully
withdrew in time after a response was made. I have repeated the description
with appropiate changes for ease of reference.
I've attached a patch for libpgtcl which adds access to backend version
numbers.
This is via a new command:
pg_version <db channel> <major varname> ?<minor varname>?
Using readonly variables rather than a command was my first choice but I
decided that it was inappropiate for the library to start assigning global
variable(s) when that's really the applications job and the command interface
is consistent with the rest of the interface.
Obviously, backend version numbers are specific to a particular connection. So
I've created a new data structure, to keep the information as a distinct unit,
and added an instance of the new structure to the Pg_ConnectionId type. The
version information is retrieved from the given connection on first use of
pg_version and cached in the new data structure for subsequent accesses.
In addition to filling the named variables in the callers scope with version
numbers/strings the command returns the complete string as returned by
version(). It's not possible to turn this return off at the moment but I don't
see it as a problem since normal methods of stopping unwanted values returned
from procedures can be applied in the application if required.
Perhaps the most significant change is that I've increased the package's
version number from 1.3 to 1.4. This will adversly effect anyone using an
application that requires a specific version of the package where their
postgres installation is updated but their application has not been. I can't
imagine there are many applications out there using the package management
features of TCL though.
This isn't a bug fix and is therefore for 7.3 not 7.2.2
--
Nigel J. Andrews
Director
---
Logictree Systems Limited
Computer Consultants
"Nigel J. Andrews" <nandrews@investsystems.co.uk> writes:
This feature could be added to PgAccess but I felt it was general
enough to be placed in the interface library. I think someone else
suggested such a place a couple of weeks ago also. If there is a
concensus that this should be done in the application layer I'll
happily drop this patch completely.
I guess I don't quite see the point of doing this in libpgtcl,
as opposed to doing a "select version()" at the application level.
It would take only a line or two of Tcl code to do that and parse the
result of version(), so why write many lines of C to accomplish the
same thing?
regards, tom lane
On Sat, 18 May 2002, Tom Lane wrote:
"Nigel J. Andrews" <nandrews@investsystems.co.uk> writes:
This feature could be added to PgAccess but I felt it was general
enough to be placed in the interface library. I think someone else
suggested such a place a couple of weeks ago also. If there is a
concensus that this should be done in the application layer I'll
happily drop this patch completely.I guess I don't quite see the point of doing this in libpgtcl,
as opposed to doing a "select version()" at the application level.
It would take only a line or two of Tcl code to do that and parse the
result of version(), so why write many lines of C to accomplish the
same thing?
Yes, you're right. It is only a couple of lines to do the exec, error checking
and parsing.
Someone mentioned how it might be worth considering putting version testing
into the library. I thought it a reasonable idea, something that would be
reasonably be expected to reused across applications and as I'm not putting
forward anything for pgaccess until it's decided what the heck is going on with
it thought I'd do the libpgtcl version of it.
I see the pros as:
version information is accessable to all TCL applications without each having
to worry about getting it,
it comes ready to support multiple DB connections per application.
The cons:
well I don't see anything similar in the perl interface and it's not in libpq
so as the other interfaces are essentially wrappers for libpq it shouldn't be
in libpqtcl either,
there's more C code than TCL code would take (still, I could change it to use a
Tcl_eval if it's lines of code that count)
--
Nigel J. Andrews
Director
---
Logictree Systems Limited
Computer Consultants
Please note this posting was to HACKERS, INTERFACES, and PATCHES, but
I'm only subscribed to INTERFACES so that's where this message is going.
On Sat, 18 May 2002, Nigel J. Andrews wrote:
On Sat, 18 May 2002, Tom Lane wrote:
"Nigel J. Andrews" <nandrews@investsystems.co.uk> writes:
This feature could be added to PgAccess but I felt it was general
enough to be placed in the interface library. I think someone else
suggested such a place a couple of weeks ago also. If there is a
concensus that this should be done in the application layer I'll
happily drop this patch completely.I guess I don't quite see the point of doing this in libpgtcl,
as opposed to doing a "select version()" at the application level.
It would take only a line or two of Tcl code to do that and parse the
result of version(), so why write many lines of C to accomplish the
same thing?Yes, you're right. It is only a couple of lines to do the exec, error checking
and parsing.Someone mentioned how it might be worth considering putting version testing
into the library. I thought it a reasonable idea, something that would be
reasonably be expected to reused across applications and as I'm not putting
forward anything for pgaccess until it's decided what the heck is going on with
it thought I'd do the libpgtcl version of it.
Yes it was I who concurred, for exactly the reasons Nigel offered.
Putting that functionality into the TCL layer would help more than just
pgaccess. I program in PHP a lot and while it provides the basic
functions of the C api there's also several more functions for returning
a variety of information on the connected database, at least with
postgresql and mysql.
As far as pgaccess goes, I don't think we're looking at 7.2.2, as that
seems to be mostly a bug fix release. Maybe we should shoot for 7.3?
I see the pros as:
version information is accessable to all TCL applications without each having
to worry about getting it,
it comes ready to support multiple DB connections per application.The cons:
well I don't see anything similar in the perl interface and it's not in libpq
so as the other interfaces are essentially wrappers for libpq it shouldn't be
in libpqtcl either,
there's more C code than TCL code would take (still, I could change it to use a
Tcl_eval if it's lines of code that count)
I guess not many people are excited about moving this functionality any
lower. I just think with the changes that are coming up with the schema
and all you are leaving too much up to the application programmers or
the end users. I could be wrong, I haven't really been following
postgresql for too long.
--Chris
--
cmaj_at_freedomcorpse_dot_info
fingerprint 5EB8 2035 F07B 3B09 5A31 7C09 196F 4126 C005 1F6A