From e9ce658b6203e9052bff5c89ed6265fba69cdb36 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 22 Mar 2012 12:08:34 -0400 Subject: [PATCH] Refactor to eliminate duplicate copies of conninfo default-finding code. Alex Shulgin, lightly edited by me --- src/interfaces/libpq/fe-connect.c | 185 ++++++++++++++---------------- 1 file changed, 84 insertions(+), 101 deletions(-) diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 817d83b9cb..6a20a1485d 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -121,9 +121,9 @@ static int ldapServiceLookup(const char *purl, PQconninfoOption *options, * fallback is available. If after all no value can be determined * for an option, an error is returned. * - * The value for the username is treated specially in conninfo_parse. - * If the Compiled-in resource is specified as a NULL value, the - * user is determined by pg_fe_getauthname(). + * The value for the username is treated specially in conninfo_add_defaults. + * If the value is not obtained any other way, the username is determined + * by pg_fe_getauthname(). * * The Label and Disp-Char entries are provided for applications that * want to use PQconndefaults() to create a generic database connection @@ -292,11 +292,14 @@ static PGconn *makeEmptyPGconn(void); static void fillPGconn(PGconn *conn, PQconninfoOption *connOptions); static void freePGconn(PGconn *conn); static void closePGconn(PGconn *conn); +static PQconninfoOption *conninfo_init(PQExpBuffer errorMessage); static PQconninfoOption *conninfo_parse(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults); static PQconninfoOption *conninfo_array_parse(const char *const * keywords, const char *const * values, PQExpBuffer errorMessage, bool use_defaults, int expand_dbname); +static bool conninfo_add_defaults(PQconninfoOption *options, + PQExpBuffer errorMessage); static char *conninfo_getval(PQconninfoOption *connOptions, const char *keyword); static void defaultNoticeReceiver(void *arg, const PGresult *res); @@ -813,10 +816,9 @@ connectOptions2(PGconn *conn) /* * PQconndefaults * - * Parse an empty string like PQconnectdb() would do and return the - * resulting connection options array, ie, all the default values that are - * available from the environment etc. On error (eg out of memory), - * NULL is returned. + * Construct a default connection options array, which identifies all the + * available options and shows any default values that are available from the + * environment etc. On error (eg out of memory), NULL is returned. * * Using this function, an application may determine all possible options * and their current default values. @@ -833,10 +835,21 @@ PQconndefaults(void) PQExpBufferData errorBuf; PQconninfoOption *connOptions; + /* We don't actually report any errors here, but callees want a buffer */ initPQExpBuffer(&errorBuf); if (PQExpBufferDataBroken(errorBuf)) return NULL; /* out of memory already :-( */ - connOptions = conninfo_parse("", &errorBuf, true); + + connOptions = conninfo_init(&errorBuf); + if (connOptions != NULL) + { + if (!conninfo_add_defaults(connOptions, &errorBuf)) + { + PQconninfoFree(connOptions); + connOptions = NULL; + } + } + termPQExpBuffer(&errorBuf); return connOptions; } @@ -3986,6 +3999,25 @@ PQconninfoParse(const char *conninfo, char **errmsg) return connOptions; } +/* + * Build a working copy of the constant PQconninfoOptions array. + */ +static PQconninfoOption * +conninfo_init(PQExpBuffer errorMessage) +{ + PQconninfoOption *options; + + options = (PQconninfoOption *) malloc(sizeof(PQconninfoOptions)); + if (options == NULL) + { + printfPQExpBuffer(errorMessage, + libpq_gettext("out of memory\n")); + return NULL; + } + memcpy(options, PQconninfoOptions, sizeof(PQconninfoOptions)); + return options; +} + /* * Conninfo parser routine * @@ -4002,21 +4034,15 @@ conninfo_parse(const char *conninfo, PQExpBuffer errorMessage, char *pname; char *pval; char *buf; - char *tmp; char *cp; char *cp2; PQconninfoOption *options; PQconninfoOption *option; /* Make a working copy of PQconninfoOptions */ - options = malloc(sizeof(PQconninfoOptions)); + options = conninfo_init(errorMessage); if (options == NULL) - { - printfPQExpBuffer(errorMessage, - libpq_gettext("out of memory\n")); return NULL; - } - memcpy(options, PQconninfoOptions, sizeof(PQconninfoOptions)); /* Need a modifiable copy of the input string */ if ((buf = strdup(conninfo)) == NULL) @@ -4170,73 +4196,14 @@ conninfo_parse(const char *conninfo, PQExpBuffer errorMessage, free(buf); /* - * Stop here if caller doesn't want defaults filled in. - */ - if (!use_defaults) - return options; - - /* - * If there's a service spec, use it to obtain any not-explicitly-given - * parameters. - */ - if (parseServiceInfo(options, errorMessage)) - { - PQconninfoFree(options); - return NULL; - } - - /* - * Get the fallback resources for parameters not specified in the conninfo - * string nor the service. + * Add in defaults if the caller wants that. */ - for (option = options; option->keyword != NULL; option++) + if (use_defaults) { - if (option->val != NULL) - continue; /* Value was in conninfo or service */ - - /* - * Try to get the environment variable fallback - */ - if (option->envvar != NULL) + if (!conninfo_add_defaults(options, errorMessage)) { - if ((tmp = getenv(option->envvar)) != NULL) - { - option->val = strdup(tmp); - if (!option->val) - { - printfPQExpBuffer(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(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(errorMessage); - continue; + PQconninfoFree(options); + return NULL; } } @@ -4262,7 +4229,6 @@ conninfo_array_parse(const char *const * keywords, const char *const * values, PQExpBuffer errorMessage, bool use_defaults, int expand_dbname) { - char *tmp; PQconninfoOption *options; PQconninfoOption *str_options = NULL; PQconninfoOption *option; @@ -4298,18 +4264,15 @@ conninfo_array_parse(const char *const * keywords, const char *const * values, } /* Make a working copy of PQconninfoOptions */ - options = malloc(sizeof(PQconninfoOptions)); + options = conninfo_init(errorMessage); if (options == NULL) { - printfPQExpBuffer(errorMessage, - libpq_gettext("out of memory\n")); PQconninfoFree(str_options); return NULL; } - memcpy(options, PQconninfoOptions, sizeof(PQconninfoOptions)); - i = 0; /* Parse the keywords/values arrays */ + i = 0; while (keywords[i]) { const char *pname = keywords[i]; @@ -4386,20 +4349,42 @@ conninfo_array_parse(const char *const * keywords, const char *const * values, PQconninfoFree(str_options); /* - * Stop here if caller doesn't want defaults filled in. + * Add in defaults if the caller wants that. */ - if (!use_defaults) - return options; + if (use_defaults) + { + if (!conninfo_add_defaults(options, errorMessage)) + { + PQconninfoFree(options); + return NULL; + } + } + + return options; +} + +/* + * Add the default values for any unspecified options to the connection + * options array. + * + * Defaults are obtained from a service file, environment variables, etc. + * + * Returns TRUE if successful, otherwise FALSE; errorMessage is filled in + * upon failure. Note that failure to locate a default value is not an + * error condition here --- we just leave the option's value as NULL. + */ +static bool +conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage) +{ + PQconninfoOption *option; + char *tmp; /* * If there's a service spec, use it to obtain any not-explicitly-given * parameters. */ - if (parseServiceInfo(options, errorMessage)) - { - PQconninfoFree(options); - return NULL; - } + if (parseServiceInfo(options, errorMessage) != 0) + return false; /* * Get the fallback resources for parameters not specified in the conninfo @@ -4422,16 +4407,15 @@ conninfo_array_parse(const char *const * keywords, const char *const * values, { printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n")); - PQconninfoFree(options); - return NULL; + return false; } continue; } } /* - * No environment variable specified or this one isn't set - try - * compiled in + * No environment variable specified or the variable isn't set - try + * compiled-in default */ if (option->compiled != NULL) { @@ -4440,14 +4424,13 @@ conninfo_array_parse(const char *const * keywords, const char *const * values, { printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n")); - PQconninfoFree(options); - return NULL; + return false; } continue; } /* - * Special handling for user + * Special handling for "user" option */ if (strcmp(option->keyword, "user") == 0) { @@ -4456,7 +4439,7 @@ conninfo_array_parse(const char *const * keywords, const char *const * values, } } - return options; + return true; } static char * -- 2.40.0