8
8
*
9
9
*
10
10
* 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 $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -83,8 +83,18 @@ static int ldapServiceLookup(const char *purl, PQconninfoOption *options,
83
83
#define PGPASSFILE "pgpass.conf"
84
84
#endif
85
85
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
+ */
88
98
#define DefaultHost "localhost"
89
99
#define DefaultTty ""
90
100
#define DefaultOption ""
@@ -262,7 +272,6 @@ static int parseServiceInfo(PQconninfoOption *options,
262
272
static char * pwdfMatchesString (char * buf , char * token );
263
273
static char * PasswordFromFile (char * hostname , char * port , char * dbname ,
264
274
char * username );
265
- static PostgresPollingStatusType pqAppnamePoll (PGconn * conn );
266
275
static void default_threadlock (int acquire );
267
276
268
277
@@ -901,6 +910,7 @@ connectDBStart(PGconn *conn)
901
910
conn -> addr_cur = addrs ;
902
911
conn -> addrlist_family = hint .ai_family ;
903
912
conn -> pversion = PG_PROTOCOL (3 , 0 );
913
+ conn -> send_appname = true;
904
914
conn -> status = CONNECTION_NEEDED ;
905
915
906
916
/*
@@ -1075,7 +1085,7 @@ PQconnectPoll(PGconn *conn)
1075
1085
case CONNECTION_MADE :
1076
1086
break ;
1077
1087
1078
- /* pqSetenvPoll/pqAppnamePoll will decide whether to proceed. */
1088
+ /* We allow pqSetenvPoll to decide whether to proceed. */
1079
1089
case CONNECTION_SETENV :
1080
1090
break ;
1081
1091
@@ -1880,6 +1890,35 @@ PQconnectPoll(PGconn *conn)
1880
1890
if (res -> resultStatus != PGRES_FATAL_ERROR )
1881
1891
appendPQExpBuffer (& conn -> errorMessage ,
1882
1892
libpq_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
+ goto keep_going ;
1920
+ }
1921
+ }
1883
1922
1884
1923
/*
1885
1924
* if the resultStatus is FATAL, then conn->errorMessage
@@ -1899,12 +1938,6 @@ PQconnectPoll(PGconn *conn)
1899
1938
conn -> addrlist = NULL ;
1900
1939
conn -> addr_cur = NULL ;
1901
1940
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
-
1908
1941
/* Fire up post-connection housekeeping if needed */
1909
1942
if (PG_PROTOCOL_MAJOR (conn -> pversion ) < 3 )
1910
1943
{
@@ -1913,59 +1946,43 @@ PQconnectPoll(PGconn *conn)
1913
1946
conn -> next_eo = EnvironmentOptions ;
1914
1947
return PGRES_POLLING_WRITING ;
1915
1948
}
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
- }
1923
1949
1924
1950
/* Otherwise, we are open for business! */
1925
1951
conn -> status = CONNECTION_OK ;
1926
1952
return PGRES_POLLING_OK ;
1927
1953
}
1928
1954
1929
1955
case CONNECTION_SETENV :
1930
- {
1931
- PostgresPollingStatusType ret ;
1932
1956
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 ;
1951
1964
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 ;
1955
1969
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 ;
1959
1973
1960
- default :
1961
- goto error_return ;
1962
- }
1974
+ case PGRES_POLLING_WRITING : /* Still going */
1975
+ conn -> status = CONNECTION_SETENV ;
1976
+ return PGRES_POLLING_WRITING ;
1963
1977
1964
- /* We are open for business! */
1965
- conn -> status = CONNECTION_OK ;
1966
- return PGRES_POLLING_OK ;
1978
+ default :
1979
+ goto error_return ;
1967
1980
}
1968
1981
1982
+ /* We are open for business! */
1983
+ conn -> status = CONNECTION_OK ;
1984
+ return PGRES_POLLING_OK ;
1985
+
1969
1986
default :
1970
1987
appendPQExpBuffer (& conn -> errorMessage ,
1971
1988
libpq_gettext ("invalid connection state %d, "
@@ -2031,7 +2048,6 @@ makeEmptyPGconn(void)
2031
2048
conn -> options_valid = false;
2032
2049
conn -> nonblocking = false;
2033
2050
conn -> setenv_state = SETENV_STATE_IDLE ;
2034
- conn -> appname_state = APPNAME_STATE_IDLE ;
2035
2051
conn -> client_encoding = PG_SQL_ASCII ;
2036
2052
conn -> std_strings = false; /* unless server says differently */
2037
2053
conn -> verbosity = PQERRORS_DEFAULT ;
@@ -4048,129 +4064,6 @@ pqGetHomeDirectory(char *buf, int bufsize)
4048
4064
#endif
4049
4065
}
4050
4066
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
- goto error_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
- goto error_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
- goto error_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
- goto error_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
- goto error_return ;
4164
- }
4165
- }
4166
-
4167
- /* Unreachable */
4168
-
4169
- error_return :
4170
- conn -> appname_state = APPNAME_STATE_IDLE ;
4171
- return PGRES_POLLING_FAILED ;
4172
- }
4173
-
4174
4067
/*
4175
4068
* To keep the API consistent, the locking stubs are always provided, even
4176
4069
* if they are not required.
0 commit comments