From 951ec872c703886626c56d08254d38c0cd88fc9e Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 15 Oct 2002 02:24:16 +0000 Subject: [PATCH] Fix psql to cope with autocommit off, at least during startup. Behavior of backslash commands (especially for large objects) may still require some thought. --- src/bin/psql/command.c | 12 +++++++---- src/bin/psql/common.c | 44 +++++++++++++++++++++++++++----------- src/bin/psql/common.h | 4 ++-- src/bin/psql/copy.c | 4 ++-- src/bin/psql/describe.c | 46 ++++++++++++++++++++-------------------- src/bin/psql/large_obj.c | 22 +++++++++---------- 6 files changed, 78 insertions(+), 54 deletions(-) diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index a9477c68ed..963c3aed3b 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -3,7 +3,7 @@ * * Copyright 2000-2002 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/command.c,v 1.82 2002/10/03 17:09:41 momjian Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/command.c,v 1.83 2002/10/15 02:24:15 tgl Exp $ */ #include "postgres_fe.h" #include "command.h" @@ -1464,13 +1464,17 @@ test_superuser(const char *username) if (!username) return false; + /* + * Use begin/commit to avoid starting a transaction block if server + * has autocommit off by default. + */ initPQExpBuffer(&buf); - printfPQExpBuffer(&buf, "SELECT usesuper FROM pg_catalog.pg_user WHERE usename = '%s'", username); - res = PSQLexec(buf.data); + printfPQExpBuffer(&buf, "BEGIN; SELECT usesuper FROM pg_catalog.pg_user WHERE usename = '%s'; COMMIT", username); + res = PSQLexec(buf.data, true); termPQExpBuffer(&buf); answer = - (PQntuples(res) > 0 && PQnfields(res) > 0 + (res && PQntuples(res) > 0 && PQnfields(res) > 0 && !PQgetisnull(res, 0, 0) && PQgetvalue(res, 0, 0) && strcmp(PQgetvalue(res, 0, 0), "t") == 0); diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c index c451640ee0..46186e5569 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.46 2002/10/03 17:09:41 momjian Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/common.c,v 1.47 2002/10/15 02:24:16 tgl Exp $ */ #include "postgres_fe.h" @@ -204,12 +204,19 @@ handle_sigint(SIGNAL_ARGS) * * This is the way to send "backdoor" queries (those not directly entered * by the user). It is subject to -E but not -e. + * + * If the given querystring generates multiple PGresults, normally the last + * one is returned to the caller. However, if ignore_command_ok is TRUE, + * then PGresults with status PGRES_COMMAND_OK are ignored. This is intended + * mainly to allow locutions such as "begin; select ...; commit". */ PGresult * -PSQLexec(const char *query) +PSQLexec(const char *query, bool ignore_command_ok) { - PGresult *res; + PGresult *res = NULL; + PGresult *newres; const char *var; + ExecStatusType rstatus; if (!pset.db) { @@ -230,18 +237,31 @@ PSQLexec(const char *query) return NULL; cancelConn = pset.db; - res = PQexec(pset.db, query); - if (PQresultStatus(res) == PGRES_COPY_IN) - copy_in_state = true; + if (PQsendQuery(pset.db, query)) + { + while ((newres = PQgetResult(pset.db)) != NULL) + { + if (ignore_command_ok && + PQresultStatus(newres) == PGRES_COMMAND_OK) + { + PQclear(newres); + continue; + } + PQclear(res); + res = newres; + } + } + rstatus = PQresultStatus(res); /* keep cancel connection for copy out state */ - if (PQresultStatus(res) != PGRES_COPY_OUT) + if (rstatus != PGRES_COPY_OUT) cancelConn = NULL; + if (rstatus == PGRES_COPY_IN) + copy_in_state = true; - if (res && (PQresultStatus(res) == PGRES_COMMAND_OK || - PQresultStatus(res) == PGRES_TUPLES_OK || - PQresultStatus(res) == PGRES_COPY_IN || - PQresultStatus(res) == PGRES_COPY_OUT) - ) + if (res && (rstatus == PGRES_COMMAND_OK || + rstatus == PGRES_TUPLES_OK || + rstatus == PGRES_COPY_IN || + rstatus == PGRES_COPY_OUT)) return res; else { diff --git a/src/bin/psql/common.h b/src/bin/psql/common.h index f11a798127..a5b0881245 100644 --- a/src/bin/psql/common.h +++ b/src/bin/psql/common.h @@ -3,7 +3,7 @@ * * Copyright 2000 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/common.h,v 1.18 2002/07/06 20:12:30 momjian Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/common.h,v 1.19 2002/10/15 02:24:16 tgl Exp $ */ #ifndef COMMON_H #define COMMON_H @@ -33,7 +33,7 @@ extern PGconn *cancelConn; extern void handle_sigint(SIGNAL_ARGS); #endif /* not WIN32 */ -extern PGresult *PSQLexec(const char *query); +extern PGresult *PSQLexec(const char *query, bool ignore_command_ok); extern bool SendQuery(const char *query); diff --git a/src/bin/psql/copy.c b/src/bin/psql/copy.c index 926641f5f4..7e1b05d5fe 100644 --- a/src/bin/psql/copy.c +++ b/src/bin/psql/copy.c @@ -3,7 +3,7 @@ * * Copyright 2000 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/copy.c,v 1.26 2002/10/03 17:09:41 momjian Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/copy.c,v 1.27 2002/10/15 02:24:16 tgl Exp $ */ #include "postgres_fe.h" #include "copy.h" @@ -324,7 +324,7 @@ do_copy(const char *args) return false; } - result = PSQLexec(query.data); + result = PSQLexec(query.data, false); termPQExpBuffer(&query); switch (PQresultStatus(result)) diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 9c4c93c0df..017afbc83c 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -3,7 +3,7 @@ * * Copyright 2000-2002 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.69 2002/09/22 20:44:22 tgl Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.70 2002/10/15 02:24:16 tgl Exp $ */ #include "postgres_fe.h" #include "describe.h" @@ -91,7 +91,7 @@ describeAggregates(const char *pattern, bool verbose) appendPQExpBuffer(&buf, "ORDER BY 1, 2, 3;"); - res = PSQLexec(buf.data); + res = PSQLexec(buf.data, false); termPQExpBuffer(&buf); if (!res) return false; @@ -161,7 +161,7 @@ describeFunctions(const char *pattern, bool verbose) appendPQExpBuffer(&buf, "ORDER BY 2, 3, 1, 4;"); - res = PSQLexec(buf.data); + res = PSQLexec(buf.data, false); termPQExpBuffer(&buf); if (!res) return false; @@ -229,7 +229,7 @@ describeTypes(const char *pattern, bool verbose) appendPQExpBuffer(&buf, "ORDER BY 1, 2;"); - res = PSQLexec(buf.data); + res = PSQLexec(buf.data, false); termPQExpBuffer(&buf); if (!res) return false; @@ -276,7 +276,7 @@ describeOperators(const char *pattern) appendPQExpBuffer(&buf, "ORDER BY 1, 2, 3, 4;"); - res = PSQLexec(buf.data); + res = PSQLexec(buf.data, false); termPQExpBuffer(&buf); if (!res) return false; @@ -321,7 +321,7 @@ listAllDbs(bool verbose) "\n LEFT JOIN pg_catalog.pg_user u ON d.datdba = u.usesysid\n" "ORDER BY 1;"); - res = PSQLexec(buf.data); + res = PSQLexec(buf.data, false); termPQExpBuffer(&buf); if (!res) return false; @@ -374,7 +374,7 @@ permissionsList(const char *pattern) appendPQExpBuffer(&buf, "ORDER BY 1, 2;"); - res = PSQLexec(buf.data); + res = PSQLexec(buf.data, false); if (!res) { termPQExpBuffer(&buf); @@ -532,7 +532,7 @@ objectDescription(const char *pattern) appendPQExpBuffer(&buf, "ORDER BY 1, 2, 3;"); - res = PSQLexec(buf.data); + res = PSQLexec(buf.data, false); termPQExpBuffer(&buf); if (!res) return false; @@ -576,7 +576,7 @@ describeTableDetails(const char *pattern, bool verbose) appendPQExpBuffer(&buf, "ORDER BY 2, 3;"); - res = PSQLexec(buf.data); + res = PSQLexec(buf.data, false); termPQExpBuffer(&buf); if (!res) return false; @@ -655,7 +655,7 @@ describeOneTableDetails(const char *schemaname, "SELECT relhasindex, relkind, relchecks, reltriggers, relhasrules\n" "FROM pg_catalog.pg_class WHERE oid = '%s'", oid); - res = PSQLexec(buf.data); + res = PSQLexec(buf.data, false); if (!res) goto error_return; @@ -711,7 +711,7 @@ describeOneTableDetails(const char *schemaname, appendPQExpBuffer(&buf, " AND a.attrelid = i.indexrelid"); appendPQExpBuffer(&buf, "\nORDER BY a.attnum"); - res = PSQLexec(buf.data); + res = PSQLexec(buf.data, false); if (!res) goto error_return; @@ -721,7 +721,7 @@ describeOneTableDetails(const char *schemaname, PGresult *result; printfPQExpBuffer(&buf, "SELECT pg_catalog.pg_get_viewdef('%s'::pg_catalog.oid)", oid); - result = PSQLexec(buf.data); + result = PSQLexec(buf.data, false); if (!result) goto error_return; @@ -763,7 +763,7 @@ describeOneTableDetails(const char *schemaname, "WHERE d.adrelid = '%s' AND d.adnum = %s", oid, PQgetvalue(res, i, 4)); - result = PSQLexec(buf.data); + result = PSQLexec(buf.data, false); if (cells[i * cols + 2][0]) strcat(cells[i * cols + 2], " "); @@ -830,7 +830,7 @@ describeOneTableDetails(const char *schemaname, "AND i.indrelid = c2.oid", oid); - result = PSQLexec(buf.data); + result = PSQLexec(buf.data, false); if (!result) goto error_return; else if (PQntuples(result) != 1) @@ -886,7 +886,7 @@ describeOneTableDetails(const char *schemaname, "FROM pg_catalog.pg_rewrite r\n" "WHERE r.ev_class = '%s' AND r.rulename != '_RETURN'", oid); - result = PSQLexec(buf.data); + result = PSQLexec(buf.data, false); if (!result) goto error_return; else @@ -944,7 +944,7 @@ describeOneTableDetails(const char *schemaname, "WHERE c.oid = '%s' AND c.oid = i.indrelid AND i.indexrelid = c2.oid\n" "ORDER BY i.indisprimary DESC, i.indisunique DESC, c2.relname", oid); - result1 = PSQLexec(buf.data); + result1 = PSQLexec(buf.data, false); if (!result1) goto error_return; else @@ -959,7 +959,7 @@ describeOneTableDetails(const char *schemaname, "FROM pg_catalog.pg_constraint r\n" "WHERE r.conrelid = '%s' AND r.contype = 'c'", oid); - result2 = PSQLexec(buf.data); + result2 = PSQLexec(buf.data, false); if (!result2) goto error_return; else @@ -974,7 +974,7 @@ describeOneTableDetails(const char *schemaname, "FROM pg_catalog.pg_rewrite r\n" "WHERE r.ev_class = '%s'", oid); - result3 = PSQLexec(buf.data); + result3 = PSQLexec(buf.data, false); if (!result3) goto error_return; else @@ -994,7 +994,7 @@ describeOneTableDetails(const char *schemaname, " JOIN pg_catalog.pg_constraint c ON (d.refclassid = c.tableoid AND d.refobjid = c.oid) " " WHERE d.classid = t.tableoid AND d.objid = t.oid AND d.deptype = 'i' AND c.contype = 'f'))", oid); - result4 = PSQLexec(buf.data); + result4 = PSQLexec(buf.data, false); if (!result4) goto error_return; else @@ -1010,7 +1010,7 @@ describeOneTableDetails(const char *schemaname, "FROM pg_catalog.pg_constraint r\n" "WHERE r.conrelid = '%s' AND r.contype = 'f'", oid); - result5 = PSQLexec(buf.data); + result5 = PSQLexec(buf.data, false); if (!result5) goto error_return; else @@ -1206,7 +1206,7 @@ describeUsers(const char *pattern) appendPQExpBuffer(&buf, "ORDER BY 1;"); - res = PSQLexec(buf.data); + res = PSQLexec(buf.data, false); termPQExpBuffer(&buf); if (!res) return false; @@ -1312,7 +1312,7 @@ listTables(const char *tabtypes, const char *pattern, bool verbose) appendPQExpBuffer(&buf, "ORDER BY 1,2;"); - res = PSQLexec(buf.data); + res = PSQLexec(buf.data, false); termPQExpBuffer(&buf); if (!res) return false; @@ -1374,7 +1374,7 @@ listDomains(const char *pattern) appendPQExpBuffer(&buf, "ORDER BY 1, 2;"); - res = PSQLexec(buf.data); + res = PSQLexec(buf.data, false); termPQExpBuffer(&buf); if (!res) return false; diff --git a/src/bin/psql/large_obj.c b/src/bin/psql/large_obj.c index 9bf51622cc..fbe8a32a18 100644 --- a/src/bin/psql/large_obj.c +++ b/src/bin/psql/large_obj.c @@ -3,7 +3,7 @@ * * Copyright 2000-2002 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/large_obj.c,v 1.22 2002/10/03 17:09:41 momjian Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/large_obj.c,v 1.23 2002/10/15 02:24:16 tgl Exp $ */ #include "postgres_fe.h" #include "large_obj.h" @@ -53,7 +53,7 @@ handle_transaction(void) notice[0] = '\0'; old_notice_hook = PQsetNoticeProcessor(pset.db, _my_notice_handler, NULL); - res = PSQLexec(commit ? "COMMIT" : "ROLLBACK"); + res = PSQLexec(commit ? "COMMIT" : "ROLLBACK", false); if (!res) return false; @@ -104,7 +104,7 @@ do_lo_export(const char *loid_arg, const char *filename_arg) if (!handle_transaction()) return false; - if (!(res = PSQLexec("BEGIN"))) + if (!(res = PSQLexec("BEGIN", false))) return false; PQclear(res); @@ -125,7 +125,7 @@ do_lo_export(const char *loid_arg, const char *filename_arg) if (own_transaction) { - if (!(res = PSQLexec("COMMIT"))) + if (!(res = PSQLexec("COMMIT", false))) { res = PQexec(pset.db, "ROLLBACK"); PQclear(res); @@ -171,7 +171,7 @@ do_lo_import(const char *filename_arg, const char *comment_arg) if (!handle_transaction()) return false; - if (!(res = PSQLexec("BEGIN"))) + if (!(res = PSQLexec("BEGIN", false))) return false; PQclear(res); @@ -222,7 +222,7 @@ do_lo_import(const char *filename_arg, const char *comment_arg) } strcpy(bufptr, "')"); - if (!(res = PSQLexec(cmdbuf))) + if (!(res = PSQLexec(cmdbuf, false))) { if (own_transaction) { @@ -239,7 +239,7 @@ do_lo_import(const char *filename_arg, const char *comment_arg) if (own_transaction) { - if (!(res = PSQLexec("COMMIT"))) + if (!(res = PSQLexec("COMMIT", false))) { res = PQexec(pset.db, "ROLLBACK"); PQclear(res); @@ -288,7 +288,7 @@ do_lo_unlink(const char *loid_arg) if (!handle_transaction()) return false; - if (!(res = PSQLexec("BEGIN"))) + if (!(res = PSQLexec("BEGIN", false))) return false; PQclear(res); @@ -314,7 +314,7 @@ do_lo_unlink(const char *loid_arg) sprintf(buf, "DELETE FROM pg_catalog.pg_description WHERE objoid = '%u' " "AND classoid = 'pg_catalog.pg_largeobject'::regclass", loid); - if (!(res = PSQLexec(buf))) + if (!(res = PSQLexec(buf, false))) { if (own_transaction) { @@ -327,7 +327,7 @@ do_lo_unlink(const char *loid_arg) if (own_transaction) { - if (!(res = PSQLexec("COMMIT"))) + if (!(res = PSQLexec("COMMIT", false))) { res = PQexec(pset.db, "ROLLBACK"); PQclear(res); @@ -362,7 +362,7 @@ do_lo_list(void) "ORDER BY \"ID\"", gettext("Description")); - res = PSQLexec(buf); + res = PSQLexec(buf, false); if (!res) return false; -- 2.40.0