88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.380 2009/11/29 20:14:53 petere Exp $
11+ * $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.381 2009/12/02 04:38:35 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -83,8 +83,18 @@ static int ldapServiceLookup(const char *purl, PQconninfoOption *options,
8383#define PGPASSFILE "pgpass.conf"
8484#endif
8585
86- /* fall back options if they are not specified by arguments or defined
87- by environment variables */
86+ /*
87+ * Pre-8.5 servers will return this SQLSTATE if asked to set
88+ * application_name in a startup packet. We hard-wire the value rather
89+ * than looking into errcodes.h since it reflects historical behavior
90+ * rather than that of the current code.
91+ */
92+ #define ERRCODE_APPNAME_UNKNOWN "42704"
93+
94+ /*
95+ * fall back options if they are not specified by arguments or defined
96+ * by environment variables
97+ */
8898#define DefaultHost "localhost"
8999#define DefaultTty ""
90100#define DefaultOption ""
@@ -262,7 +272,6 @@ static int parseServiceInfo(PQconninfoOption *options,
262272static char * pwdfMatchesString (char * buf ,char * token );
263273static char * PasswordFromFile (char * hostname ,char * port ,char * dbname ,
264274char * username );
265- static PostgresPollingStatusType pqAppnamePoll (PGconn * conn );
266275static void default_threadlock (int acquire );
267276
268277
@@ -901,6 +910,7 @@ connectDBStart(PGconn *conn)
901910conn -> addr_cur = addrs ;
902911conn -> addrlist_family = hint .ai_family ;
903912conn -> pversion = PG_PROTOCOL (3 ,0 );
913+ conn -> send_appname = true;
904914conn -> status = CONNECTION_NEEDED ;
905915
906916/*
@@ -1075,7 +1085,7 @@ PQconnectPoll(PGconn *conn)
10751085case CONNECTION_MADE :
10761086break ;
10771087
1078- /* pqSetenvPoll/pqAppnamePoll will decide whether to proceed. */
1088+ /*We allow pqSetenvPoll to decide whether to proceed. */
10791089case CONNECTION_SETENV :
10801090break ;
10811091
@@ -1880,6 +1890,35 @@ PQconnectPoll(PGconn *conn)
18801890if (res -> resultStatus != PGRES_FATAL_ERROR )
18811891appendPQExpBuffer (& conn -> errorMessage ,
18821892libpq_gettext ("unexpected message from server during startup\n" ));
1893+ else if (conn -> send_appname &&
1894+ (conn -> appname || conn -> fbappname ))
1895+ {
1896+ /*
1897+ * If we tried to send application_name, check to see
1898+ * if the error is about that --- pre-8.5 servers will
1899+ * reject it at this stage of the process. If so,
1900+ * close the connection and retry without sending
1901+ * application_name. We could possibly get a false
1902+ * SQLSTATE match here and retry uselessly, but there
1903+ * seems no great harm in that; we'll just get the
1904+ * same error again if it's unrelated.
1905+ */
1906+ const char * sqlstate ;
1907+
1908+ sqlstate = PQresultErrorField (res ,PG_DIAG_SQLSTATE );
1909+ if (sqlstate &&
1910+ strcmp (sqlstate ,ERRCODE_APPNAME_UNKNOWN )== 0 )
1911+ {
1912+ PQclear (res );
1913+ conn -> send_appname = false;
1914+ /* Must drop the old connection */
1915+ pqsecure_close (conn );
1916+ closesocket (conn -> sock );
1917+ conn -> sock = -1 ;
1918+ conn -> status = CONNECTION_NEEDED ;
1919+ gotokeep_going ;
1920+ }
1921+ }
18831922
18841923/*
18851924 * if the resultStatus is FATAL, then conn->errorMessage
@@ -1899,12 +1938,6 @@ PQconnectPoll(PGconn *conn)
18991938conn -> addrlist = NULL ;
19001939conn -> addr_cur = NULL ;
19011940
1902- /*
1903- * Note: To avoid changing the set of application-visible
1904- * connection states, v2 environment setup and v3 application
1905- * name setup both happen in the CONNECTION_SETENV state.
1906- */
1907-
19081941/* Fire up post-connection housekeeping if needed */
19091942if (PG_PROTOCOL_MAJOR (conn -> pversion )< 3 )
19101943{
@@ -1913,59 +1946,43 @@ PQconnectPoll(PGconn *conn)
19131946conn -> next_eo = EnvironmentOptions ;
19141947return PGRES_POLLING_WRITING ;
19151948}
1916- else if (conn -> sversion >=80500 &&
1917- (conn -> appname || conn -> fbappname ))
1918- {
1919- conn -> status = CONNECTION_SETENV ;
1920- conn -> appname_state = APPNAME_STATE_CMD_SEND ;
1921- return PGRES_POLLING_WRITING ;
1922- }
19231949
19241950/* Otherwise, we are open for business! */
19251951conn -> status = CONNECTION_OK ;
19261952return PGRES_POLLING_OK ;
19271953}
19281954
19291955case CONNECTION_SETENV :
1930- {
1931- PostgresPollingStatusType ret ;
19321956
1933- /*
1934- * Do post-connection housekeeping (only needed in protocol
1935- * 2.0), or send the application name in PG8.5+.
1936- *
1937- * We pretend that the connection is OK for the duration of
1938- * these queries.
1939- */
1940- conn -> status = CONNECTION_OK ;
1941-
1942- if (PG_PROTOCOL_MAJOR (conn -> pversion )< 3 )
1943- ret = pqSetenvPoll (conn );
1944- else /* must be here to send app name */
1945- ret = pqAppnamePoll (conn );
1946-
1947- switch (ret )
1948- {
1949- case PGRES_POLLING_OK :/* Success */
1950- break ;
1957+ /*
1958+ * Do post-connection housekeeping (only needed in protocol 2.0).
1959+ *
1960+ * We pretend that the connection is OK for the duration of these
1961+ * queries.
1962+ */
1963+ conn -> status = CONNECTION_OK ;
19511964
1952- case PGRES_POLLING_READING :/* Still going */
1953- conn -> status = CONNECTION_SETENV ;
1954- return PGRES_POLLING_READING ;
1965+ switch (pqSetenvPoll (conn ))
1966+ {
1967+ case PGRES_POLLING_OK :/* Success */
1968+ break ;
19551969
1956- case PGRES_POLLING_WRITING :/* Still going */
1957- conn -> status = CONNECTION_SETENV ;
1958- return PGRES_POLLING_WRITING ;
1970+ case PGRES_POLLING_READING :/* Still going */
1971+ conn -> status = CONNECTION_SETENV ;
1972+ return PGRES_POLLING_READING ;
19591973
1960- default :
1961- goto error_return ;
1962- }
1974+ case PGRES_POLLING_WRITING : /* Still going */
1975+ conn -> status = CONNECTION_SETENV ;
1976+ return PGRES_POLLING_WRITING ;
19631977
1964- /* We are open for business! */
1965- conn -> status = CONNECTION_OK ;
1966- return PGRES_POLLING_OK ;
1978+ default :
1979+ gotoerror_return ;
19671980}
19681981
1982+ /* We are open for business! */
1983+ conn -> status = CONNECTION_OK ;
1984+ return PGRES_POLLING_OK ;
1985+
19691986default :
19701987appendPQExpBuffer (& conn -> errorMessage ,
19711988libpq_gettext ("invalid connection state %d, "
@@ -2031,7 +2048,6 @@ makeEmptyPGconn(void)
20312048conn -> options_valid = false;
20322049conn -> nonblocking = false;
20332050conn -> setenv_state = SETENV_STATE_IDLE ;
2034- conn -> appname_state = APPNAME_STATE_IDLE ;
20352051conn -> client_encoding = PG_SQL_ASCII ;
20362052conn -> std_strings = false;/* unless server says differently */
20372053conn -> verbosity = PQERRORS_DEFAULT ;
@@ -4048,129 +4064,6 @@ pqGetHomeDirectory(char *buf, int bufsize)
40484064#endif
40494065}
40504066
4051- /*
4052- *pqAppnamePoll
4053- *
4054- * Polls the process of passing the application name to the backend.
4055- *
4056- * Ideally, we'd include the appname in the startup packet, but that would
4057- * cause old backends to reject the unknown parameter. So we send it in a
4058- * separate query after we have determined the backend version. Once there
4059- * is no interest in pre-8.5 backends, this should be folded into the startup
4060- * packet logic.
4061- */
4062- static PostgresPollingStatusType
4063- pqAppnamePoll (PGconn * conn )
4064- {
4065- PGresult * res ;
4066-
4067- if (conn == NULL || conn -> status == CONNECTION_BAD )
4068- return PGRES_POLLING_FAILED ;
4069-
4070- /* Check whether there is any data for us */
4071- switch (conn -> appname_state )
4072- {
4073- /* This is a reading state. */
4074- case APPNAME_STATE_CMD_WAIT :
4075- {
4076- /* Load waiting data */
4077- int n = pqReadData (conn );
4078-
4079- if (n < 0 )
4080- gotoerror_return ;
4081- if (n == 0 )
4082- return PGRES_POLLING_READING ;
4083-
4084- break ;
4085- }
4086-
4087- /* This is a writing state, so we just proceed. */
4088- case APPNAME_STATE_CMD_SEND :
4089- break ;
4090-
4091- /* Should we raise an error if called when not active? */
4092- case APPNAME_STATE_IDLE :
4093- return PGRES_POLLING_OK ;
4094-
4095- default :
4096- printfPQExpBuffer (& conn -> errorMessage ,
4097- libpq_gettext ("invalid appname state %d, "
4098- "probably indicative of memory corruption\n" ),
4099- conn -> appname_state );
4100- gotoerror_return ;
4101- }
4102-
4103- /* We will loop here until there is nothing left to do in this call. */
4104- for (;;)
4105- {
4106- switch (conn -> appname_state )
4107- {
4108- case APPNAME_STATE_CMD_SEND :
4109- {
4110- const char * val ;
4111- char escVal [NAMEDATALEN * 2 + 1 ];
4112- char setQuery [NAMEDATALEN * 2 + 26 + 1 ];
4113-
4114- /* Use appname if present, otherwise use fallback */
4115- val = conn -> appname ?conn -> appname :conn -> fbappname ;
4116-
4117- /*
4118- * Escape the data as needed. We can truncate to NAMEDATALEN,
4119- * so there's no need to cope with malloc.
4120- */
4121- PQescapeStringConn (conn ,escVal ,val ,NAMEDATALEN ,NULL );
4122-
4123- sprintf (setQuery ,"SET application_name = '%s'" ,escVal );
4124-
4125- if (!PQsendQuery (conn ,setQuery ))
4126- gotoerror_return ;
4127-
4128- conn -> appname_state = APPNAME_STATE_CMD_WAIT ;
4129- break ;
4130- }
4131-
4132- case APPNAME_STATE_CMD_WAIT :
4133- {
4134- if (PQisBusy (conn ))
4135- return PGRES_POLLING_READING ;
4136-
4137- res = PQgetResult (conn );
4138-
4139- if (res )
4140- {
4141- if (PQresultStatus (res )!= PGRES_COMMAND_OK )
4142- {
4143- PQclear (res );
4144- gotoerror_return ;
4145- }
4146- PQclear (res );
4147- /* Keep reading until PQgetResult returns NULL */
4148- }
4149- else
4150- {
4151- /* Query finished, so we're done */
4152- conn -> appname_state = APPNAME_STATE_IDLE ;
4153- return PGRES_POLLING_OK ;
4154- }
4155- break ;
4156- }
4157-
4158- default :
4159- printfPQExpBuffer (& conn -> errorMessage ,
4160- libpq_gettext ("invalid appname state %d, "
4161- "probably indicative of memory corruption\n" ),
4162- conn -> appname_state );
4163- gotoerror_return ;
4164- }
4165- }
4166-
4167- /* Unreachable */
4168-
4169- error_return :
4170- conn -> appname_state = APPNAME_STATE_IDLE ;
4171- return PGRES_POLLING_FAILED ;
4172- }
4173-
41744067/*
41754068 * To keep the API consistent, the locking stubs are always provided, even
41764069 * if they are not required.