Added in PQconnectdb() function

Submitted by: wieck@sapserv.debis.de (Jan Wieck)
This commit is contained in:
Marc G. Fournier 1996-11-09 10:39:54 +00:00
parent 7ee9464bc1
commit 4aa1734f36
6 changed files with 549 additions and 41 deletions

View File

@ -7,7 +7,7 @@
#
#
# IDENTIFICATION
# $Header: /cvsroot/pgsql/src/Attic/Makefile.global,v 1.56 1996/11/08 07:47:52 scrappy Exp $
# $Header: /cvsroot/pgsql/src/Attic/Makefile.global,v 1.57 1996/11/09 10:39:02 scrappy Exp $
#
# NOTES
# This is seen by any Makefiles that include mk/postgres.mk. To
@ -59,7 +59,7 @@
# to change it in Makefile.custom.
# make sure that you have no whitespaces after the PORTNAME setting
# or the makefiles can get confused
PORTNAME= UNDEFINED
PORTNAME= BSD44_derived
# Ignore LINUX_ELF if you're not using Linux. But if you are, and you're
# compiling to a.out (which means you're using the dld dynamic loading
@ -860,7 +860,7 @@ includedir= $(HEADERDIR)
# Flags for CC and LD. (depend on COPT and PROFILE)
#
# PostgreSQL should *always* compile with -Wall -Werror enabled
CFLAGS+= -Wall -Werror
CFLAGS+= -Wall #-Werror
# Globally pass debugging/optimization/profiling flags based
# on the options selected above.

View File

@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtcl.c,v 1.3 1996/10/30 06:18:38 scrappy Exp $
* $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtcl.c,v 1.4 1996/11/09 10:39:40 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
@ -75,6 +75,11 @@ Pgtcl_Init (Tcl_Interp *interp)
Tcl_CreateExitHandler(Pgtcl_AtExit, (ClientData)cd);
/* register all pgtcl commands */
Tcl_CreateCommand(interp,
"pg_conndefaults",
Pg_conndefaults,
(ClientData)cd, (Tcl_CmdDeleteProc*)NULL);
Tcl_CreateCommand(interp,
"pg_connect",
Pg_connect,

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclCmds.c,v 1.5 1996/10/30 06:18:39 scrappy Exp $
* $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclCmds.c,v 1.6 1996/11/09 10:39:41 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
@ -209,6 +209,44 @@ tcl_value (char *value)
#endif
/**********************************
* pg_conndefaults
syntax:
pg_conndefaults
the return result is a list describing the possible options and their
current default values for a call to pg_connect with the new -conninfo
syntax. Each entry in the list is a sublist of the format:
{optname label dispchar dispsize value}
**********************************/
int
Pg_conndefaults(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
{
PQconninfoOption *option;
char buf[8192];
Tcl_ResetResult(interp);
for(option = PQconndefaults(); option->keyword != NULL; option++) {
if(option->val == NULL) {
option->val = "";
}
sprintf(buf, "{%s} {%s} {%s} %d {%s}",
option->keyword,
option->label,
option->dispchar,
option->dispsize,
option->val);
Tcl_AppendElement(interp, buf);
}
return TCL_OK;
}
/**********************************
* pg_connect
make a connection to a backend.
@ -235,55 +273,73 @@ Pg_connect(ClientData cData, Tcl_Interp *interp, int argc, char* argv[])
if (argc == 1) {
Tcl_AppendResult(interp, "pg_connect: database name missing\n", 0);
Tcl_AppendResult(interp, "pg_connect databaseName [-host hostName] [-port portNumber] [-tty pgtty]]", 0);
Tcl_AppendResult(interp, "pg_connect databaseName [-host hostName] [-port portNumber] [-tty pgtty]]\n", 0);
Tcl_AppendResult(interp, "pg_connect -conninfo <conninfo-string>", 0);
return TCL_ERROR;
}
if (argc > 2) {
/* parse for pg environment settings */
i = 2;
while (i+1 < argc) {
if (strcmp(argv[i], "-host") == 0) {
pghost = argv[i+1];
i += 2;
}
else
if (strcmp(argv[i], "-port") == 0) {
pgport = argv[i+1];
if (!strcmp("-conninfo", argv[1])) {
/*
* Establish a connection using the new PQconnectdb() interface
*/
if (argc != 3) {
Tcl_AppendResult(interp, "pg_connect: syntax error\n", 0);
Tcl_AppendResult(interp, "pg_connect -conninfo <conninfo-string>", 0);
return TCL_ERROR;
}
conn = PQconnectdb(argv[2]);
} else {
/*
* Establish a connection using the old PQsetdb() interface
*/
if (argc > 2) {
/* parse for pg environment settings */
i = 2;
while (i+1 < argc) {
if (strcmp(argv[i], "-host") == 0) {
pghost = argv[i+1];
i += 2;
}
else
if (strcmp(argv[i], "-tty") == 0) {
pgtty = argv[i+1];
if (strcmp(argv[i], "-port") == 0) {
pgport = argv[i+1];
i += 2;
}
else if (strcmp(argv[i], "-options") == 0) {
pgoptions = argv[i+1];
i += 2;
}
else {
Tcl_AppendResult(interp, "Bad option to pg_connect : \n",
argv[i], 0);
Tcl_AppendResult(interp, "pg_connect databaseName [-host hostName] [-port portNumber] [-tty pgtty]]",0);
return TCL_ERROR;
}
} /* while */
if ((i % 2 != 0) || i != argc) {
Tcl_AppendResult(interp, "wrong # of arguments to pg_connect\n", argv[i],0);
Tcl_AppendResult(interp, "pg_connect databaseName [-host hostName] [-port portNumber] [-tty pgtty]]",0);
return TCL_ERROR;
else
if (strcmp(argv[i], "-tty") == 0) {
pgtty = argv[i+1];
i += 2;
}
else if (strcmp(argv[i], "-options") == 0) {
pgoptions = argv[i+1];
i += 2;
}
else {
Tcl_AppendResult(interp, "Bad option to pg_connect : \n",
argv[i], 0);
Tcl_AppendResult(interp, "pg_connect databaseName [-host hostName] [-port portNumber] [-tty pgtty]]",0);
return TCL_ERROR;
}
} /* while */
if ((i % 2 != 0) || i != argc) {
Tcl_AppendResult(interp, "wrong # of arguments to pg_connect\n", argv[i],0);
Tcl_AppendResult(interp, "pg_connect databaseName [-host hostName] [-port portNumber] [-tty pgtty]]",0);
return TCL_ERROR;
}
}
dbName = argv[1];
conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
}
dbName = argv[1];
conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
if (conn->status == CONNECTION_OK) {
PgSetConnectionId(cd, interp->result, conn);
return TCL_OK;
}
else {
Tcl_AppendResult(interp, "Connection to ", dbName, " failed\n", 0);
Tcl_AppendResult(interp, "Connection to database failed\n", 0);
Tcl_AppendResult(interp, conn->errorMessage, 0);
PQfinish(conn);
return TCL_ERROR;
}
}

View File

@ -5,7 +5,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: pgtclCmds.h,v 1.3 1996/10/30 06:18:40 scrappy Exp $
* $Id: pgtclCmds.h,v 1.4 1996/11/09 10:39:42 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
@ -43,6 +43,8 @@ typedef struct Pg_ResultId_s {
/* **************************/
/* registered Tcl functions */
/* **************************/
extern int Pg_conndefaults(
ClientData cData, Tcl_Interp *interp, int argc, char* argv[]);
extern int Pg_connect(
ClientData cData, Tcl_Interp *interp, int argc, char* argv[]);
extern int Pg_disconnect(

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.14 1996/11/04 04:00:54 momjian Exp $
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.15 1996/11/09 10:39:51 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
@ -52,10 +52,197 @@ static int packetSend(Port *port, PacketBuf *buf, PacketLen len,
static void startup2PacketBuf(StartupInfo* s, PacketBuf* res);
static void freePGconn(PGconn *conn);
static void closePGconn(PGconn *conn);
static int conninfo_parse(const char *conninfo, char *errorMessage);
static char *conninfo_getval(char *keyword);
static void conninfo_free();
#define NOTIFYLIST_INITIAL_SIZE 10
#define NOTIFYLIST_GROWBY 10
/* ----------
* Definition of the conninfo parametes and their fallback resources.
* If Environment-Var and Compiled-in are specified as NULL, no
* fallback is available. If after all no value can be determined
* for an option, an error is returned.
*
* The values for dbname and user are treated special in conninfo_parse.
* If the Compiled-in resource is specified as a NULL value, the
* user is determined by fe_getauthname() and for dbname the user
* name is copied.
*
* The Label and Disp-Char entries are provided for applications that
* want to use PQconndefaults() to create a generic database connection
* dialog. Disp-Char is defined as follows:
* "" Normal input field
* ----------
*/
static PQconninfoOption PQconninfoOptions[] = {
/* ----------------------------------------------------------------- */
/* Option-name Environment-Var Compiled-in Current value */
/* Label Disp-Char */
/* ----------------- --------------- --------------- --------------- */
{ "user", "PGUSER", NULL, NULL,
"Database-User", "", 20 },
{ "dbname", "PGDATABASE", NULL, NULL,
"Database-Name", "", 20 },
{ "host", "PGHOST", DefaultHost, NULL,
"Database-Host", "", 40 },
{ "port", "PGPORT", POSTPORT, NULL,
"Database-Port", "", 6 },
{ "tty", "PGTTY", DefaultTty, NULL,
"Backend-Debug-TTY", "D", 40 },
{ "options", "PGOPTIONS", DefaultOption, NULL,
"Backend-Debug-Options", "D", 40 },
/* ----------------- --------------- --------------- --------------- */
{ NULL, NULL, NULL, NULL,
NULL, NULL, 0 }
};
/* ----------------
* PQconnectdb
*
* establishes a connectin to a postgres backend through the postmaster
* using connection information in a string.
*
* The conninfo string is a list of
*
* option = value
*
* definitions. Value might be a single value containing no whitespaces
* or a single quoted string. If a single quote should appear everywhere
* in the value, it must be escaped with a backslash like \'
*
* Returns a PGconn* which is needed for all subsequent libpq calls
* if the status field of the connection returned is CONNECTION_BAD,
* then some fields may be null'ed out instead of having valid values
* ----------------
*/
PGconn*
PQconnectdb(const char *conninfo)
{
PGconn *conn;
PQconninfoOption *option;
char errorMessage[ERROR_MSG_LENGTH];
/* ----------
* Allocate memory for the conn structure
* ----------
*/
conn = (PGconn*)malloc(sizeof(PGconn));
if (conn == NULL) {
fprintf(stderr,
"FATAL: PQsetdb() -- unable to allocate memory for a PGconn");
return (PGconn*)NULL;
}
memset((char *)conn, 0, sizeof(PGconn));
/* ----------
* Parse the conninfo string and get the fallback resources
* ----------
*/
if(conninfo_parse(conninfo, errorMessage) < 0) {
conn->status = CONNECTION_BAD;
strcpy(conn->errorMessage, errorMessage);
conninfo_free();
return conn;
}
/* ----------
* Check that we have all connection parameters
* ----------
*/
for(option = PQconninfoOptions; option->keyword != NULL; option++) {
if(option->val != NULL) continue; /* Value was in conninfo */
/* ----------
* No value was found for this option. Return an error.
* ----------
*/
conn->status = CONNECTION_BAD;
sprintf(conn->errorMessage,
"ERROR: PQconnectdb(): Cannot determine a value for option '%s'.\n",
option->keyword);
strcat(conn->errorMessage,
"Option not specified in conninfo string");
if(option->environ) {
strcat(conn->errorMessage,
", environment variable ");
strcat(conn->errorMessage, option->environ);
strcat(conn->errorMessage, "\nnot set");
}
strcat(conn->errorMessage, " and no compiled in default value.\n");
conninfo_free();
return conn;
}
/* ----------
* Setup the conn structure
* ----------
*/
conn->Pfout = NULL;
conn->Pfin = NULL;
conn->Pfdebug = NULL;
conn->port = NULL;
conn->notifyList = DLNewList();
conn->pghost = strdup(conninfo_getval("host"));
conn->pgport = strdup(conninfo_getval("port"));
conn->pgtty = strdup(conninfo_getval("tty"));
conn->pgoptions = strdup(conninfo_getval("options"));
conn->pguser = strdup(conninfo_getval("user"));
conn->dbName = strdup(conninfo_getval("dbname"));
/* ----------
* Free the connection info - all is in conn now
* ----------
*/
conninfo_free();
/* ----------
* Connect to the database
* ----------
*/
conn->status = connectDB(conn);
if (conn->status == CONNECTION_OK) {
PGresult *res;
/* Send a blank query to make sure everything works; in particular, that
the database exists.
*/
res = PQexec(conn," ");
if (res == NULL || res->resultStatus != PGRES_EMPTY_QUERY) {
/* PQexec has put error message in conn->errorMessage */
closePGconn(conn);
}
PQclear(res);
}
return conn;
}
/* ----------------
* PQconndefaults
*
* Parse an empty string like PQconnectdb() would do and return the
* address of the connection options structure. Using this function
* an application might determine all possible options and their
* current default values.
* ----------------
*/
PQconninfoOption*
PQconndefaults()
{
char errorMessage[ERROR_MSG_LENGTH];
conninfo_parse("", errorMessage);
return PQconninfoOptions;
}
/* ----------------
* PQsetdb
*
@ -162,7 +349,7 @@ PQsetdb(const char *pghost, const char* pgport, const char* pgoptions, const cha
if (((tmp = (char *)dbName) && (dbName[0] != '\0')) ||
((tmp = getenv("PGDATABASE")))) {
conn->dbName = strdup(tmp);
} else conn->dbName = conn->pguser;
} else conn->dbName = strdup(conn->pguser);
} else conn->dbName = NULL;
if (error) conn->status = CONNECTION_BAD;
@ -461,6 +648,230 @@ startup2PacketBuf(StartupInfo* s, PacketBuf* res)
strncpy(tmp, s->tty, sizeof(s->execFile));
}
/* ----------------
* Conninfo parser routine
* ----------------
*/
static int conninfo_parse(const char *conninfo, char *errorMessage)
{
char *pname;
char *pval;
char *buf;
char *tmp;
char *cp;
char *cp2;
PQconninfoOption *option;
char errortmp[ERROR_MSG_LENGTH];
conninfo_free();
if((buf = strdup(conninfo)) == NULL) {
strcpy(errorMessage,
"FATAL: cannot allocate memory for copy of conninfo string\n");
return -1;
}
cp = buf;
while(*cp) {
/* Skip blanks before the parameter name */
if(isspace(*cp)) {
cp++;
continue;
}
/* Get the parameter name */
pname = cp;
while(*cp) {
if(*cp == '=') {
break;
}
if(isspace(*cp)) {
*cp++ = '\0';
while(*cp) {
if(!isspace(*cp)) {
break;
}
cp++;
}
break;
}
cp++;
}
/* Check that there is a following '=' */
if(*cp != '=') {
sprintf(errorMessage,
"ERROR: PQconnectdb() - Missing '=' after '%s' in conninfo\n",
pname);
free(buf);
return -1;
}
*cp++ = '\0';
/* Skip blanks after the '=' */
while(*cp) {
if(!isspace(*cp)) {
break;
}
cp++;
}
pval = cp;
if(*cp != '\'') {
cp2 = pval;
while(*cp) {
if(isspace(*cp)) {
*cp++ = '\0';
break;
}
if(*cp == '\\') {
cp++;
if(*cp != '\0') {
*cp2++ = *cp++;
}
} else {
*cp2++ = *cp++;
}
}
*cp2 = '\0';
} else {
cp2 = pval;
cp++;
for(;;) {
if(*cp == '\0') {
sprintf(errorMessage,
"ERROR: PQconnectdb() - unterminated quoted string in conninfo\n");
free(buf);
return -1;
}
if(*cp == '\\') {
cp++;
if(*cp != '\0') {
*cp2++ = *cp++;
}
continue;
}
if(*cp == '\'') {
*cp2 = '\0';
cp++;
break;
}
*cp2++ = *cp++;
}
}
/* ----------
* Now we have the name and the value. Search
* for the param record.
* ----------
*/
for(option = PQconninfoOptions; option->keyword != NULL; option++) {
if(!strcmp(option->keyword, pname)) {
break;
}
}
if(option->keyword == NULL) {
sprintf(errorMessage,
"ERROR: PQconnectdb() - unknown option '%s'\n",
pname);
free(buf);
return -1;
}
/* ----------
* Store the value
* ----------
*/
option->val = strdup(pval);
}
free(buf);
/* ----------
* Get the fallback resources for parameters not specified
* in the conninfo string.
* ----------
*/
for(option = PQconninfoOptions; option->keyword != NULL; option++) {
if(option->val != NULL) continue; /* Value was in conninfo */
/* ----------
* Try to get the environment variable fallback
* ----------
*/
if(option->environ != NULL) {
if((tmp = getenv(option->environ)) != NULL) {
option->val = strdup(tmp);
continue;
}
}
/* ----------
* No environment variable specified or this one isn't set -
* try compiled in
* ----------
*/
if(option->compiled != NULL) {
option->val = strdup(option->compiled);
continue;
}
/* ----------
* Special handling for user
* ----------
*/
if(!strcmp(option->keyword, "user")) {
tmp = fe_getauthname(errortmp);
if (tmp) {
option->val = strdup(tmp);
}
}
/* ----------
* Special handling for dbname
* ----------
*/
if(!strcmp(option->keyword, "dbname")) {
tmp = conninfo_getval("user");
if (tmp) {
option->val = strdup(tmp);
}
}
}
return 0;
}
static char*
conninfo_getval(char *keyword)
{
PQconninfoOption *option;
for(option = PQconninfoOptions; option->keyword != NULL; option++) {
if (!strcmp(option->keyword, keyword)) {
return option->val;
}
}
return NULL;
}
static void
conninfo_free()
{
PQconninfoOption *option;
for(option = PQconninfoOptions; option->keyword != NULL; option++) {
if(option->val != NULL) {
free(option->val);
option->val = NULL;
}
}
}
/* =========== accessor functions for PGconn ========= */
char*
PQdb(PGconn* conn)
@ -472,6 +883,16 @@ PQdb(PGconn* conn)
return conn->dbName;
}
char*
PQuser(PGconn* conn)
{
if (!conn) {
fprintf(stderr,"PQuser() -- pointer to PGconn is null");
return (char *)NULL;
}
return conn->pguser;
}
char*
PQhost(PGconn* conn)
{

View File

@ -6,7 +6,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: libpq-fe.h,v 1.9 1996/11/04 04:00:56 momjian Exp $
* $Id: libpq-fe.h,v 1.10 1996/11/09 10:39:54 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
@ -146,8 +146,31 @@ struct _PQprintOpt {
typedef struct _PQprintOpt PQprintOpt;
/* ----------------
* Structure for the conninfo parameter definitions of PQconnectdb()
* ----------------
*/
struct _PQconninfoOption {
char *keyword; /* The keyword of the option */
char *environ; /* Fallback environment variable name */
char *compiled; /* Fallback compiled in default value */
char *val; /* Options value */
char *label; /* Label for field in connect dialog */
char *dispchar; /* Character to display for this field */
/* in a connect dialog. Values are: */
/* "" Display entered value as is */
/* "*" Password field - hide value */
/* "D" Debug options - don't */
/* create a field by default */
int dispsize; /* Field size in characters for dialog */
};
typedef struct _PQconninfoOption PQconninfoOption;
/* === in fe-connect.c === */
/* make a new client connection to the backend */
extern PGconn* PQconnectdb(const char* conninfo);
extern PQconninfoOption *PQconndefaults();
extern PGconn* PQsetdb(const char* pghost, const char* pgport, const char* pgoptions,
const char* pgtty, const char* dbName);
/* close the current connection and free the PGconn data structure */
@ -157,6 +180,7 @@ extern void PQfinish(PGconn* conn);
extern void PQreset(PGconn* conn);
extern char* PQdb(PGconn* conn);
extern char* PQuser(PGconn* conn);
extern char* PQhost(PGconn* conn);
extern char* PQoptions(PGconn* conn);
extern char* PQport(PGconn* conn);