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));