diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c index 164918ff675a54558969b197e309565746949ce3..b7aa0a3ba252e785382adebe753ae3a87d30e1d0 100644 --- a/src/bin/psql/common.c +++ b/src/bin/psql/common.c @@ -3,7 +3,7 @@ * * Copyright 2000 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/common.c,v 1.54 2003/02/19 03:54:39 momjian Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/common.c,v 1.55 2003/02/21 21:34:27 tgl Exp $ */ #include "postgres_fe.h" #include "common.h" @@ -42,26 +42,6 @@ #include "print.h" #include "mainloop.h" - -/* Workarounds for Windows */ -/* Probably to be moved up the source tree in the future, perhaps to be replaced by - * more specific checks like configure-style HAVE_GETTIMEOFDAY macros. - */ -#ifndef WIN32 - -typedef struct timeval TimevalStruct; -#define GETTIMEOFDAY(T) gettimeofday(T, NULL) -#define DIFF_MSEC(T, U) ((((T)->tv_sec - (U)->tv_sec) * 1000000.0 + (T)->tv_usec - (U)->tv_usec) / 1000.0) - -#else - -typedef struct _timeb TimevalStruct; -#define GETTIMEOFDAY(T) _ftime(&T) -#define DIFF_MSEC(T, U) ((((T)->time - (U)->time) * 1000.0 + (T)->millitm - (U)->millitm)) - -#endif - - extern bool prompt_state; /* @@ -226,63 +206,6 @@ handle_sigint(SIGNAL_ARGS) #endif /* not WIN32 */ - -/* ConnectionUp - * - * Returns whether our backend connection is still there. - */ -static bool -ConnectionUp() -{ - return PQstatus(pset.db) != CONNECTION_BAD; -} - - - -/* CheckConnection - * - * Verify that we still have a good connection to the backend, and if not, - * see if it can be restored. - * - * Returns true if either the connection was still there, or it could be - * restored successfully; false otherwise. If, however, there was no - * connection and the session is non-interactive, this will exit the program - * with a code of EXIT_BADCONN. - */ -static bool -CheckConnection() -{ - bool OK = ConnectionUp(); - if (!OK) - { - if (!pset.cur_cmd_interactive) - { - psql_error("connection to server was lost\n"); - exit(EXIT_BADCONN); - } - - fputs(gettext("The connection to the server was lost. Attempting reset: "), stderr); - PQreset(pset.db); - OK = ConnectionUp(); - if (!OK) - { - fputs(gettext("Failed.\n"), stderr); - PQfinish(pset.db); - pset.db = NULL; - SetVariable(pset.vars, "DBNAME", NULL); - SetVariable(pset.vars, "HOST", NULL); - SetVariable(pset.vars, "PORT", NULL); - SetVariable(pset.vars, "USER", NULL); - SetVariable(pset.vars, "ENCODING", NULL); - } - else - fputs(gettext("Succeeded.\n"), stderr); - } - - return OK; -} - - /* * PSQLexec * @@ -327,22 +250,19 @@ PSQLexec(const char *query, bool ignore_command_ok) cancelConn = pset.db; if (PQsendQuery(pset.db, query)) { - rstatus = PGRES_EMPTY_QUERY; - - while (((newres = PQgetResult(pset.db)) != NULL) && - (rstatus == PGRES_COPY_IN) && - (rstatus == PGRES_COPY_OUT)) + while ((newres = PQgetResult(pset.db)) != NULL) { rstatus = PQresultStatus(newres); if (ignore_command_ok && rstatus == PGRES_COMMAND_OK) { PQclear(newres); + continue; } - else - { - PQclear(res); - res = newres; - } + PQclear(res); + res = newres; + if (rstatus == PGRES_COPY_IN || + rstatus == PGRES_COPY_OUT) + break; } } rstatus = PQresultStatus(res); @@ -357,147 +277,37 @@ PSQLexec(const char *query, bool ignore_command_ok) rstatus == PGRES_COPY_IN || rstatus == PGRES_COPY_OUT)) return res; - - psql_error("%s", PQerrorMessage(pset.db)); - PQclear(res); - - CheckConnection(); - - return NULL; -} - - - -/* - * PrintNotifications: check for asynchronous notifications, and print them out - * - */ -static void -PrintNotifications(void) -{ - PGnotify *notify; - - while ((notify = PQnotifies(pset.db)) != NULL) - { - fprintf(pset.queryFout, gettext("Asynchronous NOTIFY '%s' from backend with pid %d received.\n"), - notify->relname, notify->be_pid); - free(notify); - fflush(pset.queryFout); - } -} - - -/* - * PrintQueryTuples: assuming query result is OK, print its tuples - * - * Returns true if successful, false otherwise. - */ -static bool -PrintQueryTuples(const PGresult *results) -{ - /* write output to \g argument, if any */ - if (pset.gfname) - { - FILE *queryFout_copy = pset.queryFout; - bool queryFoutPipe_copy = pset.queryFoutPipe; - - pset.queryFout = stdout; /* so it doesn't get - * closed */ - - /* open file/pipe */ - if (!setQFout(pset.gfname)) - { - pset.queryFout = queryFout_copy; - pset.queryFoutPipe = queryFoutPipe_copy; - return false; - } - - printQuery(results, &pset.popt, pset.queryFout); - - /* close file/pipe, restore old setting */ - setQFout(NULL); - - pset.queryFout = queryFout_copy; - pset.queryFoutPipe = queryFoutPipe_copy; - - free(pset.gfname); - pset.gfname = NULL; - } else { - printQuery(results, &pset.popt, pset.queryFout); - } - - return true; -} + psql_error("%s", PQerrorMessage(pset.db)); + PQclear(res); - - -/* - * PrintQueryResults: analyze query results and print them out - * - * Note: Utility function for use by SendQuery() only. - * - * Returns true if the query executed successfully, false otherwise. - */ -static bool -PrintQueryResults(PGresult *results, - const TimevalStruct *before, - const TimevalStruct *after) -{ - bool success = false; - - switch (PQresultStatus(results)) - { - case PGRES_TUPLES_OK: - success = PrintQueryTuples(results); - break; - case PGRES_EMPTY_QUERY: - success = true; - break; - case PGRES_COMMAND_OK: + if (PQstatus(pset.db) == CONNECTION_BAD) + { + if (!pset.cur_cmd_interactive) { - char buf[10]; - - success = true; - sprintf(buf, "%u", (unsigned int) PQoidValue(results)); - if (!QUIET()) - fprintf(pset.queryFout, "%s\n", PQcmdStatus(results)); - SetVariable(pset.vars, "LASTOID", buf); - break; + psql_error("connection to server was lost\n"); + exit(EXIT_BADCONN); } - case PGRES_COPY_OUT: - success = handleCopyOut(pset.db, pset.queryFout); - break; - - case PGRES_COPY_IN: - if (pset.cur_cmd_interactive && !QUIET()) - puts(gettext("Enter data to be copied followed by a newline.\n" - "End with a backslash and a period on a line by itself.")); - - success = handleCopyIn(pset.db, pset.cur_cmd_source, - pset.cur_cmd_interactive ? get_prompt(PROMPT_COPY) : NULL); - break; - - case PGRES_NONFATAL_ERROR: - case PGRES_FATAL_ERROR: - case PGRES_BAD_RESPONSE: - success = false; - psql_error("%s", PQerrorMessage(pset.db)); - break; - } - - fflush(pset.queryFout); - - if (!CheckConnection()) return false; - - PrintNotifications(); - - /* Possible microtiming output */ - if (pset.timing && success) - printf(gettext("Time: %.2f ms\n"), DIFF_MSEC(after, before)); + fputs(gettext("The connection to the server was lost. Attempting reset: "), stderr); + PQreset(pset.db); + if (PQstatus(pset.db) == CONNECTION_BAD) + { + fputs(gettext("Failed.\n"), stderr); + PQfinish(pset.db); + pset.db = NULL; + SetVariable(pset.vars, "DBNAME", NULL); + SetVariable(pset.vars, "HOST", NULL); + SetVariable(pset.vars, "PORT", NULL); + SetVariable(pset.vars, "USER", NULL); + SetVariable(pset.vars, "ENCODING", NULL); + } + else + fputs(gettext("Succeeded.\n"), stderr); + } - return success; + return NULL; + } } @@ -517,8 +327,16 @@ PrintQueryResults(PGresult *results, bool SendQuery(const char *query) { + bool success = false; PGresult *results; - TimevalStruct before, after; + PGnotify *notify; +#ifndef WIN32 + struct timeval before, + after; +#else + struct _timeb before, + after; +#endif if (!pset.db) { @@ -549,11 +367,19 @@ SendQuery(const char *query) cancelConn = pset.db; +#ifndef WIN32 if (pset.timing) - GETTIMEOFDAY(&before); + gettimeofday(&before, NULL); results = PQexec(pset.db, query); if (pset.timing) - GETTIMEOFDAY(&after); + gettimeofday(&after, NULL); +#else + if (pset.timing) + _ftime(&before); + results = PQexec(pset.db, query); + if (pset.timing) + _ftime(&after); +#endif if (PQresultStatus(results) == PGRES_COPY_IN) copy_in_state = true; @@ -564,11 +390,137 @@ SendQuery(const char *query) if (results == NULL) { fputs(PQerrorMessage(pset.db), pset.queryFout); - return false; + success = false; } + else + { + switch (PQresultStatus(results)) + { + case PGRES_TUPLES_OK: + /* write output to \g argument, if any */ + if (pset.gfname) + { + FILE *queryFout_copy = pset.queryFout; + bool queryFoutPipe_copy = pset.queryFoutPipe; + + pset.queryFout = stdout; /* so it doesn't get + * closed */ + + /* open file/pipe */ + if (!setQFout(pset.gfname)) + { + pset.queryFout = queryFout_copy; + pset.queryFoutPipe = queryFoutPipe_copy; + success = false; + break; + } + + printQuery(results, &pset.popt, pset.queryFout); + + /* close file/pipe, restore old setting */ + setQFout(NULL); + + pset.queryFout = queryFout_copy; + pset.queryFoutPipe = queryFoutPipe_copy; + + free(pset.gfname); + pset.gfname = NULL; + + success = true; + } + else + { + printQuery(results, &pset.popt, pset.queryFout); + success = true; + } + break; + case PGRES_EMPTY_QUERY: + success = true; + break; + case PGRES_COMMAND_OK: + { + char buf[10]; + + success = true; + sprintf(buf, "%u", (unsigned int) PQoidValue(results)); + if (!QUIET()) + fprintf(pset.queryFout, "%s\n", PQcmdStatus(results)); + SetVariable(pset.vars, "LASTOID", buf); + break; + } + case PGRES_COPY_OUT: + success = handleCopyOut(pset.db, pset.queryFout); + break; - return PrintQueryResults(results, &before, &after); - PQclear(results); + case PGRES_COPY_IN: + if (pset.cur_cmd_interactive && !QUIET()) + puts(gettext("Enter data to be copied followed by a newline.\n" + "End with a backslash and a period on a line by itself.")); + + success = handleCopyIn(pset.db, pset.cur_cmd_source, + pset.cur_cmd_interactive ? get_prompt(PROMPT_COPY) : NULL); + break; + + case PGRES_NONFATAL_ERROR: + case PGRES_FATAL_ERROR: + case PGRES_BAD_RESPONSE: + success = false; + psql_error("%s", PQerrorMessage(pset.db)); + break; + } + + fflush(pset.queryFout); + + if (PQstatus(pset.db) == CONNECTION_BAD) + { + if (!pset.cur_cmd_interactive) + { + psql_error("connection to server was lost\n"); + exit(EXIT_BADCONN); + } + fputs(gettext("The connection to the server was lost. Attempting reset: "), stderr); + PQreset(pset.db); + if (PQstatus(pset.db) == CONNECTION_BAD) + { + fputs(gettext("Failed.\n"), stderr); + PQfinish(pset.db); + PQclear(results); + pset.db = NULL; + SetVariable(pset.vars, "DBNAME", NULL); + SetVariable(pset.vars, "HOST", NULL); + SetVariable(pset.vars, "PORT", NULL); + SetVariable(pset.vars, "USER", NULL); + SetVariable(pset.vars, "ENCODING", NULL); + return false; + } + else + fputs(gettext("Succeeded.\n"), stderr); + } + + /* check for asynchronous notification returns */ + while ((notify = PQnotifies(pset.db)) != NULL) + { + fprintf(pset.queryFout, gettext("Asynchronous NOTIFY '%s' from backend with pid %d received.\n"), + notify->relname, notify->be_pid); + free(notify); + fflush(pset.queryFout); + } + + if (results) + PQclear(results); + } + + /* Possible microtiming output */ + if (pset.timing && success) +#ifndef WIN32 + printf(gettext("Time: %.2f ms\n"), + ((after.tv_sec - before.tv_sec) * 1000000.0 + after.tv_usec - before.tv_usec) / 1000.0); +#else + printf(gettext("Time: %.2f ms\n"), + ((after.time - before.time) * 1000.0 + after.millitm - before.millitm)); +#endif + + return success; }