Le 29/12/2009 14:12, Guillaume Lelarge a écrit :
> Le 29/12/2009 00:03, Guillaume Lelarge a écrit :
>> Le 28/12/2009 22:59, Tom Lane a écrit :
>>> Guillaume Lelarge <[email protected]> writes:
>>>> Le 28/12/2009 17:06, Tom Lane a écrit :
>>>>> I think we were stalled on the question of whether to use one array
>>>>> or two parallel arrays. Do you want to try coding up a sample usage
>>>>> of each possibility so we can see which one seems more useful?
>>>
>>>> I'm interested in working on this. But I don't find the thread that talk
>>>> about this.
>>>
>>> Try here
>>> http://archives.postgresql.org/message-id/[email protected]
>>>
>>
>> Thanks. I've read all the "new version of PQconnectdb" and "Determining
>> client_encoding from client locale" threads. I think I understand the
>> goal. Still need to re-read this one
>> (http://archives.postgresql.org/message-id/[email protected]) and
>> completely understand it (will probably need to look at the code, at
>> least the PQconnectdb one). But I'm definitely working on this.
>>
>
> If I try to sum up my readings so far, this is what we still have to do:
>
> 1. try the one-array approach
> PGconn *PQconnectParams(const char **params)
>
> 2. try the two-arrays approach
> PGconn *PQconnectParams(const char **keywords, const char **values)
>
> Instead of doing a wrapper around PQconnectdb, we need to refactor the
> whole function, so that we can get rid of the parsing of the conninfo
> string (which is quite complicated).
>
> Using psql as an example would be a good idea, AFAICT.
>
> Am I right? did I misunderstand or forget something?
>
I supposed I was right since noone yell at me :)
I worked on this tonight. You'll find two patches attached, one for the
one-array approach, one for the two-arrays approach. I know some more
factoring can be done (at least, the "get the fallback resources..."
part). I'm OK to do them. I just need to know if I'm on the right track.
--
Guillaume.
http://www.postgresqlfr.org
http://dalibo.com
Index: src/bin/psql/startup.c
===================================================================
RCS file: /opt/cvsroot_postgresql/pgsql/src/bin/psql/startup.c,v
retrieving revision 1.158
diff -c -p -c -r1.158 startup.c
*** src/bin/psql/startup.c 2 Jan 2010 16:57:59 -0000 1.158
--- src/bin/psql/startup.c 4 Jan 2010 21:04:13 -0000
*************** main(int argc, char *argv[])
*** 171,181 ****
/* loop until we have a password if requested by backend */
do
{
! new_pass = false;
! pset.db = PQsetdbLogin(options.host, options.port, NULL, NULL,
! options.action == ACT_LIST_DB && options.dbname == NULL ?
! "postgres" : options.dbname,
! options.username, password);
if (PQstatus(pset.db) == CONNECTION_BAD &&
PQconnectionNeedsPassword(pset.db) &&
--- 171,190 ----
/* loop until we have a password if requested by backend */
do
{
! const char *params[] = {
! "host", options.host,
! "port", options.port,
! "dbname", (options.action == ACT_LIST_DB &&
! options.dbname == NULL) ? "postgres" : options.dbname,
! "user", options.username,
! "password", password,
! "application_name", pset.progname,
! NULL, NULL
! };
!
! new_pass = false;
!
! pset.db = PQconnectdbParams(params);
if (PQstatus(pset.db) == CONNECTION_BAD &&
PQconnectionNeedsPassword(pset.db) &&
Index: src/interfaces/libpq/exports.txt
===================================================================
RCS file: /opt/cvsroot_postgresql/pgsql/src/interfaces/libpq/exports.txt,v
retrieving revision 1.23
diff -c -p -c -r1.23 exports.txt
*** src/interfaces/libpq/exports.txt 31 Mar 2009 01:41:27 -0000 1.23
--- src/interfaces/libpq/exports.txt 4 Jan 2010 20:51:13 -0000
*************** PQresultSetInstanceData 150
*** 153,155 ****
--- 153,157 ----
PQfireResultCreateEvents 151
PQconninfoParse 152
PQinitOpenSSL 153
+ PQconnectdbParams 154
+ PQconnectStartParams 155
Index: src/interfaces/libpq/fe-connect.c
===================================================================
RCS file: /opt/cvsroot_postgresql/pgsql/src/interfaces/libpq/fe-connect.c,v
retrieving revision 1.382
diff -c -p -c -r1.382 fe-connect.c
*** src/interfaces/libpq/fe-connect.c 2 Jan 2010 16:58:11 -0000 1.382
--- src/interfaces/libpq/fe-connect.c 4 Jan 2010 20:54:12 -0000
*************** static bool connectOptions2(PGconn *conn
*** 259,264 ****
--- 259,265 ----
static int connectDBStart(PGconn *conn);
static int connectDBComplete(PGconn *conn);
static PGconn *makeEmptyPGconn(void);
+ static void fillPGconn(PGconn *conn, PQconninfoOption *connOptions);
static void freePGconn(PGconn *conn);
static void closePGconn(PGconn *conn);
static PQconninfoOption *conninfo_parse(const char *conninfo,
*************** pgthreadlock_t pg_g_threadlock = default
*** 299,304 ****
--- 300,337 ----
*/
/*
+ * PQconnectdbParams
+ *
+ * establishes a connection to a postgres backend through the postmaster
+ * using connection information in a struct.
+ *
+ * The params struct string is defined as
+ *
+ * const char *params[] = {option1, value1, option2, value2, NULL}
+ *
+ * definitions.
+ *
+ * Returns a PGconn* which is needed for all subsequent libpq calls, or NULL
+ * if a memory allocation failed.
+ * If the status field of the connection returned is CONNECTION_BAD,
+ * then some fields may be null'ed out instead of having valid values.
+ *
+ * You should call PQfinish (if conn is not NULL) regardless of whether this
+ * call succeeded.
+ */
+ PGconn *
+ PQconnectdbParams(const char * const *params)
+ {
+ PGconn *conn = PQconnectStartParams(params);
+
+ if (conn && conn->status != CONNECTION_BAD)
+ (void) connectDBComplete(conn);
+
+ return conn;
+
+ }
+
+ /*
* PQconnectdb
*
* establishes a connection to a postgres backend through the postmaster
*************** PQconnectdb(const char *conninfo)
*** 332,343 ****
}
/*
! * PQconnectStart
*
* Begins the establishment of a connection to a postgres backend through the
! * postmaster using connection information in a string.
*
! * See comment for PQconnectdb for the definition of the string format.
*
* Returns a PGconn*. If NULL is returned, a malloc error has occurred, and
* you should not attempt to proceed with this connection. If the status
--- 365,376 ----
}
/*
! * PQconnectStartParams
*
* Begins the establishment of a connection to a postgres backend through the
! * postmaster using connection information in a struct.
*
! * See comment for PQconnectdbParams for the definition of the string format.
*
* Returns a PGconn*. If NULL is returned, a malloc error has occurred, and
* you should not attempt to proceed with this connection. If the status
*************** PQconnectdb(const char *conninfo)
*** 351,359 ****
* See PQconnectPoll for more info.
*/
PGconn *
! PQconnectStart(const char *conninfo)
{
! PGconn *conn;
/*
* Allocate memory for the conn structure
--- 384,395 ----
* See PQconnectPoll for more info.
*/
PGconn *
! PQconnectStartParams(const char * const *params)
{
! PGconn *conn;
! PQconninfoOption *options;
! PQconninfoOption *option;
! char *tmp;
/*
* Allocate memory for the conn structure
*************** PQconnectStart(const char *conninfo)
*** 363,372 ****
return NULL;
/*
! * Parse the conninfo string
*/
! if (!connectOptions1(conn, conninfo))
! return conn;
/*
* Compute derived options
--- 399,546 ----
return NULL;
/*
! * Make a working copy of PQconninfoOptions
! */
! options = malloc(sizeof(PQconninfoOptions));
! if (options == NULL)
! {
! printfPQExpBuffer(&conn->errorMessage,
! libpq_gettext("out of memory\n"));
! return NULL;
! }
! memcpy(options, PQconninfoOptions, sizeof(PQconninfoOptions));
!
! /*
! * Parse the params struct
*/
! while(*params)
! {
! const char *pname = params[0];
! const char *pvalue = params[1];
!
! if (pvalue != NULL)
! {
! /*
! * Now we have the name and the value. Search for the param record.
! */
! for (option = options; option->keyword != NULL; option++)
! {
! if (strcmp(option->keyword, pname) == 0)
! break;
! }
!
! /*
! * Check for invalid connection option
! */
! if (option->keyword == NULL)
! {
! printfPQExpBuffer(&conn->errorMessage,
! libpq_gettext("invalid connection option \"%s\"\n"),
! pname);
! PQconninfoFree(options);
! return NULL;
! }
!
! /*
! * Store the value
! */
! if (option->val)
! free(option->val);
! option->val = strdup(pvalue);
! if (!option->val)
! {
! printfPQExpBuffer(&conn->errorMessage,
! libpq_gettext("out of memory\n"));
! PQconninfoFree(options);
! return NULL;
! }
! }
!
! params+=2;
! }
!
! /*
! * If there's a service spec, use it to obtain any not-explicitly-given
! * parameters.
! */
! if (parseServiceInfo(options, &conn->errorMessage))
! {
! PQconninfoFree(options);
! return NULL;
! }
!
! /*
! * Get the fallback resources for parameters not specified in the conninfo
! * string nor the service.
! */
! for (option = options; option->keyword != NULL; option++)
! {
! if (option->val != NULL)
! continue; /* Value was in conninfo or service */
!
! /*
! * Try to get the environment variable fallback
! */
! if (option->envvar != NULL)
! {
! if ((tmp = getenv(option->envvar)) != NULL)
! {
! option->val = strdup(tmp);
! if (!option->val)
! {
! printfPQExpBuffer(&conn->errorMessage,
! libpq_gettext("out of memory\n"));
! PQconninfoFree(options);
! return NULL;
! }
! continue;
! }
! }
!
! /*
! * No environment variable specified or this one isn't set - try
! * compiled in
! */
! if (option->compiled != NULL)
! {
! option->val = strdup(option->compiled);
! if (!option->val)
! {
! printfPQExpBuffer(&conn->errorMessage,
! libpq_gettext("out of memory\n"));
! PQconninfoFree(options);
! return NULL;
! }
! continue;
! }
!
! /*
! * Special handling for user
! */
! if (strcmp(option->keyword, "user") == 0)
! {
! option->val = pg_fe_getauthname(&conn->errorMessage);
! continue;
! }
! }
!
! if (options == NULL)
! {
! conn->status = CONNECTION_BAD;
! /* errorMessage is already set */
! return false;
! }
!
! /*
! * Move option values into conn structure
! */
! fillPGconn(conn, options);
!
!
! /*
! * Free the option info - all is in conn now
! */
! PQconninfoFree(options);
/*
* Compute derived options
*************** PQconnectStart(const char *conninfo)
*** 383,419 ****
conn->status = CONNECTION_BAD;
}
! return conn;
}
/*
! * connectOptions1
*
! * Internal subroutine to set up connection parameters given an already-
! * created PGconn and a conninfo string. Derived settings should be
! * processed by calling connectOptions2 next. (We split them because
! * PQsetdbLogin overrides defaults in between.)
*
! * Returns true if OK, false if trouble (in which case errorMessage is set
! * and so is conn->status).
*/
! static bool
! connectOptions1(PGconn *conn, const char *conninfo)
{
! PQconninfoOption *connOptions;
! char *tmp;
/*
* Parse the conninfo string
*/
! connOptions = conninfo_parse(conninfo, &conn->errorMessage, true);
! if (connOptions == NULL)
{
conn->status = CONNECTION_BAD;
- /* errorMessage is already set */
- return false;
}
/*
* Move option values into conn structure
*
--- 557,625 ----
conn->status = CONNECTION_BAD;
}
! return conn;
}
/*
! * PQconnectStart
*
! * Begins the establishment of a connection to a postgres backend through the
! * postmaster using connection information in a string.
*
! * See comment for PQconnectdb for the definition of the string format.
! *
! * Returns a PGconn*. If NULL is returned, a malloc error has occurred, and
! * you should not attempt to proceed with this connection. If the status
! * field of the connection returned is CONNECTION_BAD, an error has
! * occurred. In this case you should call PQfinish on the result, (perhaps
! * inspecting the error message first). Other fields of the structure may not
! * be valid if that occurs. If the status field is not CONNECTION_BAD, then
! * this stage has succeeded - call PQconnectPoll, using select(2) to see when
! * this is necessary.
! *
! * See PQconnectPoll for more info.
*/
! PGconn *
! PQconnectStart(const char *conninfo)
{
! PGconn *conn;
!
! /*
! * Allocate memory for the conn structure
! */
! conn = makeEmptyPGconn();
! if (conn == NULL)
! return NULL;
/*
* Parse the conninfo string
*/
! if (!connectOptions1(conn, conninfo))
! return conn;
!
! /*
! * Compute derived options
! */
! if (!connectOptions2(conn))
! return conn;
!
! /*
! * Connect to the database
! */
! if (!connectDBStart(conn))
{
+ /* Just in case we failed to set it in connectDBStart */
conn->status = CONNECTION_BAD;
}
+ return conn;
+ }
+
+ static void
+ fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
+ {
+ char *tmp;
+
/*
* Move option values into conn structure
*
*************** connectOptions1(PGconn *conn, const char
*** 472,477 ****
--- 678,716 ----
tmp = conninfo_getval(connOptions, "gsslib");
conn->gsslib = tmp ? strdup(tmp) : NULL;
#endif
+ }
+
+ /*
+ * connectOptions1
+ *
+ * Internal subroutine to set up connection parameters given an already-
+ * created PGconn and a conninfo string. Derived settings should be
+ * processed by calling connectOptions2 next. (We split them because
+ * PQsetdbLogin overrides defaults in between.)
+ *
+ * Returns true if OK, false if trouble (in which case errorMessage is set
+ * and so is conn->status).
+ */
+ static bool
+ connectOptions1(PGconn *conn, const char *conninfo)
+ {
+ PQconninfoOption *connOptions;
+
+ /*
+ * Parse the conninfo string
+ */
+ connOptions = conninfo_parse(conninfo, &conn->errorMessage, true);
+ if (connOptions == NULL)
+ {
+ conn->status = CONNECTION_BAD;
+ /* errorMessage is already set */
+ return false;
+ }
+
+ /*
+ * Move option values into conn structure
+ */
+ fillPGconn(conn, connOptions);
/*
* Free the option info - all is in conn now
Index: src/interfaces/libpq/libpq-fe.h
===================================================================
RCS file: /opt/cvsroot_postgresql/pgsql/src/interfaces/libpq/libpq-fe.h,v
retrieving revision 1.148
diff -c -p -c -r1.148 libpq-fe.h
*** src/interfaces/libpq/libpq-fe.h 2 Jan 2010 16:58:12 -0000 1.148
--- src/interfaces/libpq/libpq-fe.h 4 Jan 2010 20:51:53 -0000
*************** typedef struct pgresAttDesc
*** 226,235 ****
--- 226,237 ----
/* make a new client connection to the backend */
/* Asynchronous (non-blocking) */
extern PGconn *PQconnectStart(const char *conninfo);
+ extern PGconn *PQconnectStartParams(const char * const *params);
extern PostgresPollingStatusType PQconnectPoll(PGconn *conn);
/* Synchronous (blocking) */
extern PGconn *PQconnectdb(const char *conninfo);
+ extern PGconn *PQconnectdbParams(const char * const *params);
extern PGconn *PQsetdbLogin(const char *pghost, const char *pgport,
const char *pgoptions, const char *pgtty,
const char *dbName,
Index: src/bin/psql/startup.c
===================================================================
RCS file: /opt/cvsroot_postgresql/pgsql/src/bin/psql/startup.c,v
retrieving revision 1.158
diff -c -p -c -r1.158 startup.c
*** src/bin/psql/startup.c 2 Jan 2010 16:57:59 -0000 1.158
--- src/bin/psql/startup.c 4 Jan 2010 21:27:12 -0000
*************** main(int argc, char *argv[])
*** 168,181 ****
if (pset.getPassword == TRI_YES)
password = simple_prompt(password_prompt, 100, false);
/* loop until we have a password if requested by backend */
do
{
! new_pass = false;
! pset.db = PQsetdbLogin(options.host, options.port, NULL, NULL,
! options.action == ACT_LIST_DB && options.dbname == NULL ?
! "postgres" : options.dbname,
! options.username, password);
if (PQstatus(pset.db) == CONNECTION_BAD &&
PQconnectionNeedsPassword(pset.db) &&
--- 168,200 ----
if (pset.getPassword == TRI_YES)
password = simple_prompt(password_prompt, 100, false);
+ const char *keywords[] = {
+ "host",
+ "port",
+ "dbname",
+ "user",
+ "password",
+ "application_name",
+ NULL
+ };
+
/* loop until we have a password if requested by backend */
do
{
! const char *values[] = {
! options.host,
! options.port,
! (options.action == ACT_LIST_DB &&
! options.dbname == NULL) ? "postgres" : options.dbname,
! options.username,
! password,
! pset.progname,
! NULL
! };
!
! new_pass = false;
!
! pset.db = PQconnectdbParams(keywords, values);
if (PQstatus(pset.db) == CONNECTION_BAD &&
PQconnectionNeedsPassword(pset.db) &&
Index: src/interfaces/libpq/exports.txt
===================================================================
RCS file: /opt/cvsroot_postgresql/pgsql/src/interfaces/libpq/exports.txt,v
retrieving revision 1.23
diff -c -p -c -r1.23 exports.txt
*** src/interfaces/libpq/exports.txt 31 Mar 2009 01:41:27 -0000 1.23
--- src/interfaces/libpq/exports.txt 4 Jan 2010 21:07:49 -0000
*************** PQresultSetInstanceData 150
*** 153,155 ****
--- 153,157 ----
PQfireResultCreateEvents 151
PQconninfoParse 152
PQinitOpenSSL 153
+ PQconnectdbParams 154
+ PQconnectStartParams 155
Index: src/interfaces/libpq/fe-connect.c
===================================================================
RCS file: /opt/cvsroot_postgresql/pgsql/src/interfaces/libpq/fe-connect.c,v
retrieving revision 1.382
diff -c -p -c -r1.382 fe-connect.c
*** src/interfaces/libpq/fe-connect.c 2 Jan 2010 16:58:11 -0000 1.382
--- src/interfaces/libpq/fe-connect.c 4 Jan 2010 21:18:52 -0000
*************** static bool connectOptions2(PGconn *conn
*** 259,264 ****
--- 259,265 ----
static int connectDBStart(PGconn *conn);
static int connectDBComplete(PGconn *conn);
static PGconn *makeEmptyPGconn(void);
+ static void fillPGconn(PGconn *conn, PQconninfoOption *connOptions);
static void freePGconn(PGconn *conn);
static void closePGconn(PGconn *conn);
static PQconninfoOption *conninfo_parse(const char *conninfo,
*************** pgthreadlock_t pg_g_threadlock = default
*** 299,304 ****
--- 300,339 ----
*/
/*
+ * PQconnectdbParams
+ *
+ * establishes a connection to a postgres backend through the postmaster
+ * using connection information in two structs.
+ *
+ * The keywords struct is defined as
+ *
+ * const char *params[] = {option1, option2, NULL}
+ *
+ * The values struct is defined as
+ *
+ * const char *params[] = {option1, option2, NULL}
+ *
+ * Returns a PGconn* which is needed for all subsequent libpq calls, or NULL
+ * if a memory allocation failed.
+ * If the status field of the connection returned is CONNECTION_BAD,
+ * then some fields may be null'ed out instead of having valid values.
+ *
+ * You should call PQfinish (if conn is not NULL) regardless of whether this
+ * call succeeded.
+ */
+ PGconn *
+ PQconnectdbParams(const char **keywords, const char **values)
+ {
+ PGconn *conn = PQconnectStartParams(keywords, values);
+
+ if (conn && conn->status != CONNECTION_BAD)
+ (void) connectDBComplete(conn);
+
+ return conn;
+
+ }
+
+ /*
* PQconnectdb
*
* establishes a connection to a postgres backend through the postmaster
*************** PQconnectdb(const char *conninfo)
*** 332,343 ****
}
/*
! * PQconnectStart
*
* Begins the establishment of a connection to a postgres backend through the
! * postmaster using connection information in a string.
*
! * See comment for PQconnectdb for the definition of the string format.
*
* Returns a PGconn*. If NULL is returned, a malloc error has occurred, and
* you should not attempt to proceed with this connection. If the status
--- 367,378 ----
}
/*
! * PQconnectStartParams
*
* Begins the establishment of a connection to a postgres backend through the
! * postmaster using connection information in a struct.
*
! * See comment for PQconnectdbParams for the definition of the string format.
*
* Returns a PGconn*. If NULL is returned, a malloc error has occurred, and
* you should not attempt to proceed with this connection. If the status
*************** PQconnectdb(const char *conninfo)
*** 351,359 ****
* See PQconnectPoll for more info.
*/
PGconn *
! PQconnectStart(const char *conninfo)
{
! PGconn *conn;
/*
* Allocate memory for the conn structure
--- 386,397 ----
* See PQconnectPoll for more info.
*/
PGconn *
! PQconnectStartParams(const char **keywords, const char **values)
{
! PGconn *conn;
! PQconninfoOption *options;
! PQconninfoOption *option;
! char *tmp;
/*
* Allocate memory for the conn structure
*************** PQconnectStart(const char *conninfo)
*** 363,372 ****
return NULL;
/*
! * Parse the conninfo string
*/
! if (!connectOptions1(conn, conninfo))
! return conn;
/*
* Compute derived options
--- 401,549 ----
return NULL;
/*
! * Make a working copy of PQconninfoOptions
! */
! options = malloc(sizeof(PQconninfoOptions));
! if (options == NULL)
! {
! printfPQExpBuffer(&conn->errorMessage,
! libpq_gettext("out of memory\n"));
! return NULL;
! }
! memcpy(options, PQconninfoOptions, sizeof(PQconninfoOptions));
!
! /*
! * Parse the params struct
*/
! while(*keywords)
! {
! const char *pname = keywords[0];
! const char *pvalue = values[0];
!
! if (pvalue != NULL)
! {
! /*
! * Now we have the name and the value. Search for the param record.
! */
! for (option = options; option->keyword != NULL; option++)
! {
! if (strcmp(option->keyword, pname) == 0)
! break;
! }
!
! /*
! * Check for invalid connection option
! */
! if (option->keyword == NULL)
! {
! printfPQExpBuffer(&conn->errorMessage,
! libpq_gettext("invalid connection option \"%s\"\n"),
! pname);
! PQconninfoFree(options);
! return NULL;
! }
!
! /*
! * Store the value
! */
! if (option->val)
! free(option->val);
! option->val = strdup(pvalue);
! if (!option->val)
! {
! printfPQExpBuffer(&conn->errorMessage,
! libpq_gettext("out of memory\n"));
! PQconninfoFree(options);
! return NULL;
! }
! }
!
! keywords+=1;
! values+=1;
! }
!
! /*
! * If there's a service spec, use it to obtain any not-explicitly-given
! * parameters.
! */
! if (parseServiceInfo(options, &conn->errorMessage))
! {
! PQconninfoFree(options);
! return NULL;
! }
!
! /*
! * Get the fallback resources for parameters not specified in the conninfo
! * string nor the service.
! */
! for (option = options; option->keyword != NULL; option++)
! {
! if (option->val != NULL)
! continue; /* Value was in conninfo or service */
!
! /*
! * Try to get the environment variable fallback
! */
! if (option->envvar != NULL)
! {
! if ((tmp = getenv(option->envvar)) != NULL)
! {
! option->val = strdup(tmp);
! if (!option->val)
! {
! printfPQExpBuffer(&conn->errorMessage,
! libpq_gettext("out of memory\n"));
! PQconninfoFree(options);
! return NULL;
! }
! continue;
! }
! }
!
! /*
! * No environment variable specified or this one isn't set - try
! * compiled in
! */
! if (option->compiled != NULL)
! {
! option->val = strdup(option->compiled);
! if (!option->val)
! {
! printfPQExpBuffer(&conn->errorMessage,
! libpq_gettext("out of memory\n"));
! PQconninfoFree(options);
! return NULL;
! }
! continue;
! }
!
! /*
! * Special handling for user
! */
! if (strcmp(option->keyword, "user") == 0)
! {
! option->val = pg_fe_getauthname(&conn->errorMessage);
! continue;
! }
! }
!
! if (options == NULL)
! {
! conn->status = CONNECTION_BAD;
! /* errorMessage is already set */
! return false;
! }
!
! /*
! * Move option values into conn structure
! */
! fillPGconn(conn, options);
!
!
! /*
! * Free the option info - all is in conn now
! */
! PQconninfoFree(options);
/*
* Compute derived options
*************** PQconnectStart(const char *conninfo)
*** 383,419 ****
conn->status = CONNECTION_BAD;
}
! return conn;
}
/*
! * connectOptions1
*
! * Internal subroutine to set up connection parameters given an already-
! * created PGconn and a conninfo string. Derived settings should be
! * processed by calling connectOptions2 next. (We split them because
! * PQsetdbLogin overrides defaults in between.)
*
! * Returns true if OK, false if trouble (in which case errorMessage is set
! * and so is conn->status).
*/
! static bool
! connectOptions1(PGconn *conn, const char *conninfo)
{
! PQconninfoOption *connOptions;
! char *tmp;
/*
* Parse the conninfo string
*/
! connOptions = conninfo_parse(conninfo, &conn->errorMessage, true);
! if (connOptions == NULL)
{
conn->status = CONNECTION_BAD;
- /* errorMessage is already set */
- return false;
}
/*
* Move option values into conn structure
*
--- 560,628 ----
conn->status = CONNECTION_BAD;
}
! return conn;
}
/*
! * PQconnectStart
*
! * Begins the establishment of a connection to a postgres backend through the
! * postmaster using connection information in a string.
*
! * See comment for PQconnectdb for the definition of the string format.
! *
! * Returns a PGconn*. If NULL is returned, a malloc error has occurred, and
! * you should not attempt to proceed with this connection. If the status
! * field of the connection returned is CONNECTION_BAD, an error has
! * occurred. In this case you should call PQfinish on the result, (perhaps
! * inspecting the error message first). Other fields of the structure may not
! * be valid if that occurs. If the status field is not CONNECTION_BAD, then
! * this stage has succeeded - call PQconnectPoll, using select(2) to see when
! * this is necessary.
! *
! * See PQconnectPoll for more info.
*/
! PGconn *
! PQconnectStart(const char *conninfo)
{
! PGconn *conn;
!
! /*
! * Allocate memory for the conn structure
! */
! conn = makeEmptyPGconn();
! if (conn == NULL)
! return NULL;
/*
* Parse the conninfo string
*/
! if (!connectOptions1(conn, conninfo))
! return conn;
!
! /*
! * Compute derived options
! */
! if (!connectOptions2(conn))
! return conn;
!
! /*
! * Connect to the database
! */
! if (!connectDBStart(conn))
{
+ /* Just in case we failed to set it in connectDBStart */
conn->status = CONNECTION_BAD;
}
+ return conn;
+ }
+
+ static void
+ fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
+ {
+ char *tmp;
+
/*
* Move option values into conn structure
*
*************** connectOptions1(PGconn *conn, const char
*** 472,477 ****
--- 681,719 ----
tmp = conninfo_getval(connOptions, "gsslib");
conn->gsslib = tmp ? strdup(tmp) : NULL;
#endif
+ }
+
+ /*
+ * connectOptions1
+ *
+ * Internal subroutine to set up connection parameters given an already-
+ * created PGconn and a conninfo string. Derived settings should be
+ * processed by calling connectOptions2 next. (We split them because
+ * PQsetdbLogin overrides defaults in between.)
+ *
+ * Returns true if OK, false if trouble (in which case errorMessage is set
+ * and so is conn->status).
+ */
+ static bool
+ connectOptions1(PGconn *conn, const char *conninfo)
+ {
+ PQconninfoOption *connOptions;
+
+ /*
+ * Parse the conninfo string
+ */
+ connOptions = conninfo_parse(conninfo, &conn->errorMessage, true);
+ if (connOptions == NULL)
+ {
+ conn->status = CONNECTION_BAD;
+ /* errorMessage is already set */
+ return false;
+ }
+
+ /*
+ * Move option values into conn structure
+ */
+ fillPGconn(conn, connOptions);
/*
* Free the option info - all is in conn now
Index: src/interfaces/libpq/libpq-fe.h
===================================================================
RCS file: /opt/cvsroot_postgresql/pgsql/src/interfaces/libpq/libpq-fe.h,v
retrieving revision 1.148
diff -c -p -c -r1.148 libpq-fe.h
*** src/interfaces/libpq/libpq-fe.h 2 Jan 2010 16:58:12 -0000 1.148
--- src/interfaces/libpq/libpq-fe.h 4 Jan 2010 21:14:47 -0000
*************** typedef struct pgresAttDesc
*** 226,235 ****
--- 226,237 ----
/* make a new client connection to the backend */
/* Asynchronous (non-blocking) */
extern PGconn *PQconnectStart(const char *conninfo);
+ extern PGconn *PQconnectStartParams(const char **keywords, const char **values);
extern PostgresPollingStatusType PQconnectPoll(PGconn *conn);
/* Synchronous (blocking) */
extern PGconn *PQconnectdb(const char *conninfo);
+ extern PGconn *PQconnectdbParams(const char **keywords, const char **values);
extern PGconn *PQsetdbLogin(const char *pghost, const char *pgport,
const char *pgoptions, const char *pgtty,
const char *dbName,
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers