Okay, I've had it with PQsetdbLogin having slightly different defaults
authorTom Lane
Mon, 28 Apr 2003 04:29:12 +0000 (04:29 +0000)
committerTom Lane
Mon, 28 Apr 2003 04:29:12 +0000 (04:29 +0000)
than PQconnectdb.  Reimplement the former to use the same code as the
latter.  Fix documentation omissions while at it.

doc/src/sgml/libpq.sgml
src/interfaces/libpq/fe-connect.c
src/test/regress/pg_regress.sh

index 5ba7e6468c313c81085002e0555cde8d2bb41886..b8499f02323275a42db9b09b6069f501b9c20224 100644 (file)
@@ -1,5 +1,5 @@
 
 
  
@@ -114,21 +114,26 @@ PGconn *PQconnectdb(const char *conninfo);
       used.
      
      
-      Using hostaddr instead of host allows the application to avoid a host
-      name look-up, which may be important in applications with time
-      constraints. However, Kerberos authentication requires the host
-      name. The following therefore applies: If host is specified without
-      hostaddr, a host name lookup is forced. If hostaddr is specified without
-      host, the value for hostaddr gives the remote address; if Kerberos is
-      used, this causes a reverse name query. If both host and hostaddr are
-      specified, the value for hostaddr gives the remote address; the value
-      for host is ignored, unless Kerberos is used, in which case that value
-      is used for Kerberos authentication. Note that authentication is likely
-      to fail if libpq is passed a host name that is not the name of the
-      machine at hostaddr.
+      Using hostaddr instead of host allows the
+      application to avoid a host name look-up, which may be important in
+      applications with time constraints. However, Kerberos authentication
+      requires the host name. The following therefore applies: If
+      host is specified without hostaddr, a host name
+      lookup is forced. If hostaddr is specified without
+      host, the value for hostaddr gives the remote
+      address; if Kerberos is used, this causes a reverse name query. If both
+      host and hostaddr are specified, the value for
+      hostaddr gives the remote address; the value for
+      host is ignored, unless Kerberos is used, in which case that
+      value is used for Kerberos authentication. (Note that authentication is
+      likely to fail if libpq is passed a host name
+      that is not the name of the machine at hostaddr.)  Also,
+      host rather than hostaddr is used to identify
+      the connection in $HOME/.pgpass.
      
      
-      Without either a host name or host address, libpq will connect using a
+      Without either a host name or host address,
+      libpq will connect using a
       local Unix domain socket.
      
      
@@ -176,7 +181,8 @@ PGconn *PQconnectdb(const char *conninfo);
      
      
       Maximum wait for connection, in seconds (write as a decimal integer
-      string). Zero or not specified means infinite.
+      string). Zero or not specified means wait indefinitely.  It is not
+      recommended to set the timeout to less than 2 seconds.
      
      
     
@@ -2321,7 +2327,7 @@ information into simple client applications, for example.
 
  PGHOST
 
-PGHOST sets the default server name.
+PGHOST sets the database server name.
 If this begins with a slash, it specifies Unix-domain communication
 rather than TCP/IP communication; the value is the name of the
 directory in which the socket file is stored (default /tmp).
@@ -2329,10 +2335,22 @@ directory in which the socket file is stored (default /tmp)
 
 
 
+
PGHOSTADDR
+
+PGHOSTADDR specifies the numeric IP address of the database
+server.  This can be set instead of PGHOST to avoid DNS
+lookup overhead. See the documentation of
+these parameters, under PQconnectdb above, for details
+on their interaction.
+
+
+
+
 
  PGPORT
 
-PGPORT sets the default TCP port number or Unix-domain
+PGPORT sets the TCP port number or Unix-domain
 socket file extension for communicating with the
 PostgreSQL server.
 
@@ -2342,7 +2360,7 @@ socket file extension for communicating with the
 
  PGDATABASE
 
-PGDATABASE  sets the default 
+PGDATABASE  sets the 
 PostgreSQL database name.
 
 
@@ -2369,6 +2387,19 @@ file (see ).
 
 
 
+
PGSERVICE
+
+PGSERVICE
+sets the service name to be looked up in pg_service.conf.
+This offers a shorthand way of setting all the parameters.
+
+
+
+
+
PGREALM
+
 PGREALM sets the Kerberos realm to  use  with  
 PostgreSQL, if  it is different from the local realm.
 If PGREALM is set, libpq
@@ -2380,12 +2411,18 @@ used if Kerberos authentication is selected by the server.
 
 
 
+
PGOPTIONS
+
 PGOPTIONS sets additional run-time  options  for  
 the PostgreSQL server.
 
 
 
 
+
PGREQUIRESSL
+
 PGREQUIRESSL sets whether or not the connection must be
 made over SSL. If set to
 1libpq
@@ -2397,10 +2434,14 @@ This option is only available if
 
 
 
+
PGCONNECT_TIMEOUT
+
 PGCONNECT_TIMEOUT sets the maximum number of seconds
 that libpq will wait when attempting to
-connect to the PostgreSQL server. This
-option should be set to at least 2 seconds.
+connect to the PostgreSQL server.  If unset
+or set to zero, libpq will wait indefinitely.
+It is not recommended to set the timeout to less than 2 seconds.
 
 
 
@@ -2413,6 +2454,9 @@ behavior for every PostgreSQL session.
 
 
 
+
PGDATESTYLE
+
 PGDATESTYLE
 sets the default style of date/time representation.
 (Equivalent to SET datestyle TO ....)
@@ -2420,6 +2464,9 @@ sets the default style of date/time representation.
 
 
 
+
PGTZ
+
 PGTZ
 sets the default time zone.
 (Equivalent to SET timezone TO ....)
@@ -2427,6 +2474,9 @@ sets the default time zone.
 
 
 
+
PGCLIENTENCODING
+
 PGCLIENTENCODING
 sets the default client character set encoding.
 (Equivalent to SET client_encoding TO ....)
@@ -2434,6 +2484,9 @@ sets the default client character set encoding.
 
 
 
+
PGGEQO
+
 PGGEQO
 sets the default mode for the genetic query optimizer.
 (Equivalent to SET geqo TO ....)
index e2df4de859a8021b8b146ad6e5f250fc7303f3e2..704935ec60ef9692871a3f160855546a8b140091 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.237 2003/04/25 19:45:09 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.238 2003/04/28 04:29:12 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -172,6 +172,8 @@ static const struct EnvironmentOptions
 };
 
 
+static bool connectOptions1(PGconn *conn, const char *conninfo);
+static bool connectOptions2(PGconn *conn);
 static int connectDBStart(PGconn *conn);
 static int connectDBComplete(PGconn *conn);
 static PGconn *makeEmptyPGconn(void);
@@ -264,17 +266,55 @@ PGconn *
 PQconnectStart(const char *conninfo)
 {
    PGconn     *conn;
-   PQconninfoOption *connOptions;
-   char       *tmp;
 
    /*
     * Allocate memory for the conn structure
     */
-
    conn = makeEmptyPGconn();
    if (conn == NULL)
        return (PGconn *) 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;
+}
+
+/*
+ *     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
     */
@@ -283,11 +323,14 @@ PQconnectStart(const char *conninfo)
    {
        conn->status = CONNECTION_BAD;
        /* errorMessage is already set */
-       return conn;
+       return false;
    }
 
    /*
     * Move option values into conn structure
+    *
+    * Don't put anything cute here --- intelligence should be in
+    * connectOptions2 ...
     */
    tmp = conninfo_getval(connOptions, "hostaddr");
    conn->pghostaddr = tmp ? strdup(tmp) : NULL;
@@ -305,15 +348,6 @@ PQconnectStart(const char *conninfo)
    conn->pguser = tmp ? strdup(tmp) : NULL;
    tmp = conninfo_getval(connOptions, "password");
    conn->pgpass = tmp ? strdup(tmp) : NULL;
-   if (conn->pgpass == NULL || conn->pgpass[0] == '\0')
-   {
-       if (conn->pgpass)
-           free(conn->pgpass);
-       conn->pgpass = PasswordFromFile(conn->pghost, conn->pgport,
-                                       conn->dbName, conn->pguser);
-       if (conn->pgpass == NULL)
-           conn->pgpass = strdup(DefaultPassword);
-   }
    tmp = conninfo_getval(connOptions, "connect_timeout");
    conn->connect_timeout = tmp ? strdup(tmp) : NULL;
 #ifdef USE_SSL
@@ -327,6 +361,33 @@ PQconnectStart(const char *conninfo)
     */
    PQconninfoFree(connOptions);
 
+   return true;
+}
+
+/*
+ *     connectOptions2
+ *
+ * Compute derived connection options after absorbing all user-supplied info.
+ *
+ * Returns true if OK, false if trouble (in which case errorMessage is set
+ * and so is conn->status).
+ */
+static bool
+connectOptions2(PGconn *conn)
+{
+   /*
+    * Supply default password if none given
+    */
+   if (conn->pgpass == NULL || conn->pgpass[0] == '\0')
+   {
+       if (conn->pgpass)
+           free(conn->pgpass);
+       conn->pgpass = PasswordFromFile(conn->pghost, conn->pgport,
+                                       conn->dbName, conn->pguser);
+       if (conn->pgpass == NULL)
+           conn->pgpass = strdup(DefaultPassword);
+   }
+
    /*
     * Allow unix socket specification in the host name
     */
@@ -338,16 +399,19 @@ PQconnectStart(const char *conninfo)
        conn->pghost = NULL;
    }
 
+#ifdef NOT_USED
    /*
-    * Connect to the database
+    * parse dbName to get all additional info in it, if any
     */
-   if (!connectDBStart(conn))
+   if (update_db_info(conn) != 0)
    {
-       /* Just in case we failed to set it in connectDBStart */
        conn->status = CONNECTION_BAD;
+       /* errorMessage is already set */
+       return false;
    }
+#endif
 
-   return conn;
+   return true;
 }
 
 /*
@@ -384,36 +448,9 @@ PQconndefaults(void)
  * at the specified host and port.
  *
  * 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
- *
- * Uses these environment variables:
- *
- *   PGHOST       identifies host to which to connect if  argument
- *                is NULL or a null string.
- *
- *   PGPORT       identifies TCP port to which to connect if  argument
- *                is NULL or a null string.
- *
- *   PGTTY        identifies tty to which to send messages if  argument
- *                is NULL or a null string.  (No longer used by backend.)
- *
- *   PGOPTIONS    identifies connection options if  argument is
- *                NULL or a null string.
- *
- *   PGUSER       Postgres username to associate with the connection.
- *
- *   PGPASSWORD   The user's password.
  *
- *   PGDATABASE   name of database to which to connect if 
- *                argument is NULL or a null string
- *
- *   None of the above need be defined.  There are defaults for all of them.
- *
- * To support "delimited identifiers" for database names, only convert
- * the database name to lower case if it is not surrounded by double quotes.
- * Otherwise, strip the double quotes but leave the reset of the string intact.
- * - thomas 1997-11-08
+ * if the status field of the connection returned is CONNECTION_BAD,
+ * then only the errorMessage is likely to be useful.
  * ----------------
  */
 PGconn *
@@ -422,112 +459,84 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
             const char *pwd)
 {
    PGconn     *conn;
-   char       *tmp;            /* An error message from some service we
-                                * call. */
-   bool        error = FALSE;  /* We encountered an error. */
 
+   /*
+    * Allocate memory for the conn structure
+    */
    conn = makeEmptyPGconn();
    if (conn == NULL)
        return (PGconn *) NULL;
 
-   if (pghost)
-       conn->pghost = strdup(pghost);
-   else if ((tmp = getenv("PGHOST")) != NULL)
-       conn->pghost = strdup(tmp);
-
-   if (pgport == NULL || pgport[0] == '\0')
-   {
-       tmp = getenv("PGPORT");
-       if (tmp == NULL || tmp[0] == '\0')
-           tmp = DEF_PGPORT_STR;
-       conn->pgport = strdup(tmp);
-   }
-   else
-       conn->pgport = strdup(pgport);
+   /*
+    * Parse an empty conninfo string in order to set up the same defaults
+    * that PQconnectdb() would use.
+    */
+   if (!connectOptions1(conn, ""))
+       return conn;
 
    /*
-    * We don't allow unix socket path as a function parameter. This
-    * allows unix socket specification in the host name.
+    * Absorb specified options into conn structure, overriding defaults
     */
-   if (conn->pghost && is_absolute_path(conn->pghost))
+   if (pghost && pghost[0] != '\0')
    {
-       if (conn->pgunixsocket)
-           free(conn->pgunixsocket);
-       conn->pgunixsocket = conn->pghost;
-       conn->pghost = NULL;
+       if (conn->pghost)
+           free(conn->pghost);
+       conn->pghost = strdup(pghost);
    }
 
-   if (pgtty == NULL)
+   if (pgport && pgport[0] != '\0')
    {
-       if ((tmp = getenv("PGTTY")) == NULL)
-           tmp = DefaultTty;
-       conn->pgtty = strdup(tmp);
+       if (conn->pgport)
+           free(conn->pgport);
+       conn->pgport = strdup(pgport);
    }
-   else
-       conn->pgtty = strdup(pgtty);
 
-   if (pgoptions == NULL)
+   if (pgoptions && pgoptions[0] != '\0')
    {
-       if ((tmp = getenv("PGOPTIONS")) == NULL)
-           tmp = DefaultOption;
-       conn->pgoptions = strdup(tmp);
-   }
-   else
+       if (conn->pgoptions)
+           free(conn->pgoptions);
        conn->pgoptions = strdup(pgoptions);
+   }
 
-   if (login)
-       conn->pguser = strdup(login);
-   else if ((tmp = getenv("PGUSER")) != NULL)
-       conn->pguser = strdup(tmp);
-   else
+   if (pgtty && pgtty[0] != '\0')
    {
-       /* fe-auth.c has not been fixed to support PQExpBuffers, so: */
-       conn->pguser = fe_getauthname(conn->errorMessage.data);
-       conn->errorMessage.len = strlen(conn->errorMessage.data);
+       if (conn->pgtty)
+           free(conn->pgtty);
+       conn->pgtty = strdup(pgtty);
    }
 
-   if (conn->pguser == NULL)
+   if (dbName && dbName[0] != '\0')
    {
-       error = TRUE;
-       printfPQExpBuffer(&conn->errorMessage,
-                         libpq_gettext("could not determine the PostgreSQL user name to use\n"));
+       if (conn->dbName)
+           free(conn->dbName);
+       conn->dbName = strdup(dbName);
    }
 
-   if (dbName == NULL)
+   if (login && login[0] != '\0')
    {
-       if ((tmp = getenv("PGDATABASE")) != NULL)
-           conn->dbName = strdup(tmp);
-       else if (conn->pguser)
-           conn->dbName = strdup(conn->pguser);
+       if (conn->pguser)
+           free(conn->pguser);
+       conn->pguser = strdup(login);
    }
-   else
-       conn->dbName = strdup(dbName);
 
-   if (pwd)
+   if (pwd && pwd[0] != '\0')
+   {
+       if (conn->pgpass)
+           free(conn->pgpass);
        conn->pgpass = strdup(pwd);
-   else if ((tmp = getenv("PGPASSWORD")) != NULL)
-       conn->pgpass = strdup(tmp);
-   else if ((tmp = PasswordFromFile(conn->pghost, conn->pgport,
-                                    conn->dbName, conn->pguser)) != NULL)
-       conn->pgpass = tmp;
-   else
-       conn->pgpass = strdup(DefaultPassword);
-
-   if ((tmp = getenv("PGCONNECT_TIMEOUT")) != NULL)
-       conn->connect_timeout = strdup(tmp);
+   }
 
-#ifdef USE_SSL
-   if ((tmp = getenv("PGREQUIRESSL")) != NULL)
-       conn->require_ssl = (tmp[0] == '1') ? true : false;
-#endif
+   /*
+    * Compute derived options
+    */
+   if (!connectOptions2(conn))
+       return conn;
 
-   if (error)
-       conn->status = CONNECTION_BAD;
-   else
-   {
-       if (connectDBStart(conn))
-           (void) connectDBComplete(conn);
-   }
+   /*
+    * Connect to the database
+    */
+   if (connectDBStart(conn))
+       (void) connectDBComplete(conn);
 
    return conn;
 }
@@ -537,7 +546,6 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
 /*
  * update_db_info -
  * get all additional info out of dbName
- *
  */
 static int
 update_db_info(PGconn *conn)
@@ -771,10 +779,10 @@ connectFailureMessage(PGconn *conn, int errorno)
                                     "\tTCP/IP connections on port %s?\n"
                                        ),
                          SOCK_STRERROR(errorno),
-                         conn->pghost
-                         ? conn->pghost
-                         : (conn->pghostaddr
-                            ? conn->pghostaddr
+                         conn->pghostaddr
+                         ? conn->pghostaddr
+                         : (conn->pghost
+                            ? conn->pghost
                             : "???"),
                          conn->pgport);
 }
@@ -799,20 +807,12 @@ connectDBStart(PGconn *conn)
    const char *unix_node = "unix";
    int         ret;
 
-   /* Initialize hint structure */
-   MemSet(&hint, 0, sizeof(hint));
-   hint.ai_socktype = SOCK_STREAM;
-
    if (!conn)
        return 0;
 
-#ifdef NOT_USED
-   /*
-    * parse dbName to get all additional info in it, if any
-    */
-   if (update_db_info(conn) != 0)
-       goto connect_errReturn;
-#endif
+   /* Initialize hint structure */
+   MemSet(&hint, 0, sizeof(hint));
+   hint.ai_socktype = SOCK_STREAM;
 
    /* Ensure our buffers are empty */
    conn->inStart = conn->inCursor = conn->inEnd = 0;
@@ -2116,7 +2116,7 @@ conninfo_parse(const char *conninfo, PQExpBuffer errorMessage)
    char       *cp2;
    PQconninfoOption *options;
    PQconninfoOption *option;
-   char        errortmp[INITIAL_EXPBUFFER_SIZE];
+   char        errortmp[PQERRORMSG_LENGTH];
 
    /* Make a working copy of PQconninfoOptions */
    options = malloc(sizeof(PQconninfoOptions));
@@ -2270,17 +2270,16 @@ conninfo_parse(const char *conninfo, PQExpBuffer errorMessage)
 
    }
 
+   /* Done with the modifiable input string */
+   free(buf);
+
    /* Now check for service info */
    if (parseServiceInfo(options, errorMessage))
    {
        PQconninfoFree(options);
-       free(buf);
        return NULL;
    }
 
-   /* Done with the modifiable input string */
-   free(buf);
-
    /*
     * Get the fallback resources for parameters not specified in the
     * conninfo string.
index d5291a17526c86448a97bbcb1e7bfb292bcfb82f..63991ad5ec08c90f3e65b4c0c4b5ff076c499cb3 100644 (file)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# $Header: /cvsroot/pgsql/src/test/regress/Attic/pg_regress.sh,v 1.29 2002/11/13 16:40:23 tgl Exp $
+# $Header: /cvsroot/pgsql/src/test/regress/Attic/pg_regress.sh,v 1.30 2003/04/28 04:29:12 tgl Exp $
 
 me=`basename $0`
 : ${TMPDIR=/tmp}
@@ -137,6 +137,7 @@ do
         --host=*)
                 PGHOST=`expr "x$1" : "x--host=\(.*\)"`
                 export PGHOST
+                unset PGHOSTADDR
                 shift;;
         --port=*)
                 PGPORT=`expr "x$1" : "x--port=\(.*\)"`
@@ -279,8 +280,10 @@ then
     if [ "$unix_sockets" = no ]; then
         PGHOST=$hostname
         export PGHOST
+        unset PGHOSTADDR
     else
         unset PGHOST
+        unset PGHOSTADDR
     fi
     PGPORT=65432
     export PGPORT
@@ -397,6 +400,7 @@ else # not temp-install
     if [ "$unix_sockets" = no ]; then
         PGHOST=$hostname
         export PGHOST
+        unset PGHOSTADDR
     fi
 
     if [ -n "$PGPORT" ]; then