Fix libpq startup code to work correctly in autocommit off mode.

In passing, fix breakage for case where PGCLIENTENCODING is set in
environment.
This commit is contained in:
Tom Lane 2002-10-15 01:48:25 +00:00
parent 9ff695c944
commit e258a2b436

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.209 2002/10/14 17:15:11 momjian Exp $ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.210 2002/10/15 01:48:25 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -1583,8 +1583,6 @@ PQsetenvPoll(PGconn *conn)
{ {
PGresult *res; PGresult *res;
static const char envname[] = "PGCLIENTENCODING";
if (conn == NULL || conn->status == CONNECTION_BAD) if (conn == NULL || conn->status == CONNECTION_BAD)
return PGRES_POLLING_FAILED; return PGRES_POLLING_FAILED;
@ -1625,25 +1623,23 @@ PQsetenvPoll(PGconn *conn)
goto error_return; goto error_return;
} }
/* We will loop here until there is nothing left to do in this call. */
keep_going: /* We will come back to here until there for (;;)
* is nothing left to parse. */
switch (conn->setenv_state)
{ {
switch (conn->setenv_state)
case SETENV_STATE_ENCODINGS_SEND: {
case SETENV_STATE_ENCODINGS_SEND:
{ {
const char *env; const char *env = getenv("PGCLIENTENCODING");
env = getenv(envname);
if (!env || *env == '\0') if (!env || *env == '\0')
{ {
/* /*
* query server encoding if PGCLIENTENCODING is not * PGCLIENTENCODING is not specified, so query server
* specified * for it. We must use begin/commit in case autocommit
* is off by default.
*/ */
if (!PQsendQuery(conn, if (!PQsendQuery(conn, "begin; select getdatabaseencoding(); commit"))
"select getdatabaseencoding()"))
goto error_return; goto error_return;
conn->setenv_state = SETENV_STATE_ENCODINGS_WAIT; conn->setenv_state = SETENV_STATE_ENCODINGS_WAIT;
@ -1662,11 +1658,14 @@ keep_going: /* We will come back to here until there
goto error_return; goto error_return;
} }
conn->client_encoding = encoding; conn->client_encoding = encoding;
}
/* Move on to setting the environment options */
conn->setenv_state = SETENV_STATE_OPTION_SEND;
}
break;
} }
case SETENV_STATE_ENCODINGS_WAIT: case SETENV_STATE_ENCODINGS_WAIT:
{ {
if (PQisBusy(conn)) if (PQisBusy(conn))
return PGRES_POLLING_READING; return PGRES_POLLING_READING;
@ -1675,37 +1674,35 @@ keep_going: /* We will come back to here until there
if (res) if (res)
{ {
char *encoding; if (PQresultStatus(res) == PGRES_TUPLES_OK)
{
/* set client encoding in pg_conn struct */
char *encoding;
if (PQresultStatus(res) != PGRES_TUPLES_OK) encoding = PQgetvalue(res, 0, 0);
if (!encoding) /* this should not happen */
conn->client_encoding = PG_SQL_ASCII;
else
conn->client_encoding = pg_char_to_encoding(encoding);
}
else if (PQresultStatus(res) != PGRES_COMMAND_OK)
{ {
PQclear(res); PQclear(res);
goto error_return; goto error_return;
} }
/* set client encoding in pg_conn struct */
encoding = PQgetvalue(res, 0, 0);
if (!encoding) /* this should not happen */
conn->client_encoding = PG_SQL_ASCII;
else
conn->client_encoding = pg_char_to_encoding(encoding);
PQclear(res); PQclear(res);
/* Keep reading until PQgetResult returns NULL */
/*
* We have to keep going in order to clear up the
* query
*/
goto keep_going;
} }
else
/* NULL result indicates that the query is finished */ {
/* NULL result indicates that the query is finished */
/* Move on to setting the environment options */ /* Move on to setting the environment options */
conn->setenv_state = SETENV_STATE_OPTION_SEND; conn->setenv_state = SETENV_STATE_OPTION_SEND;
goto keep_going; }
break;
} }
case SETENV_STATE_OPTION_SEND: case SETENV_STATE_OPTION_SEND:
{ {
/* Send an Environment Option */ /* Send an Environment Option */
char setQuery[100]; /* note length limits in char setQuery[100]; /* note length limits in
@ -1740,11 +1737,10 @@ keep_going: /* We will come back to here until there
/* No more options to send, so we are done. */ /* No more options to send, so we are done. */
conn->setenv_state = SETENV_STATE_IDLE; conn->setenv_state = SETENV_STATE_IDLE;
} }
break;
goto keep_going;
} }
case SETENV_STATE_OPTION_WAIT: case SETENV_STATE_OPTION_WAIT:
{ {
if (PQisBusy(conn)) if (PQisBusy(conn))
return PGRES_POLLING_READING; return PGRES_POLLING_READING;
@ -1758,33 +1754,29 @@ keep_going: /* We will come back to here until there
PQclear(res); PQclear(res);
goto error_return; goto error_return;
} }
/* Don't need the result */
PQclear(res); PQclear(res);
/* Keep reading until PQgetResult returns NULL */
/*
* We have to keep going in order to clear up the
* query
*/
goto keep_going;
} }
else
/* NULL result indicates that the query is finished */ {
/* NULL result indicates that the query is finished */
/* Send the next option */ /* Send the next option */
conn->next_eo++; conn->next_eo++;
conn->setenv_state = SETENV_STATE_OPTION_SEND; conn->setenv_state = SETENV_STATE_OPTION_SEND;
goto keep_going; }
break;
} }
case SETENV_STATE_IDLE: case SETENV_STATE_IDLE:
return PGRES_POLLING_OK; return PGRES_POLLING_OK;
default: default:
printfPQExpBuffer(&conn->errorMessage, printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("invalid state %c, " libpq_gettext("invalid state %c, "
"probably indicative of memory corruption\n"), "probably indicative of memory corruption\n"),
conn->setenv_state); conn->setenv_state);
goto error_return; goto error_return;
}
} }
/* Unreachable */ /* Unreachable */