From 8fadc245dff6f71a420c1a13b9648b000600065f Mon Sep 17 00:00:00 2001 From: Mark Dilger Date: Wed, 6 Jan 2021 13:01:02 -0800 Subject: [PATCH v3 3/9] Creating query_utils frontend utility Moving the ExecuteSqlQuery, ExecuteSqlQueryForSingleRow, and ExecuteSqlStatement out of the pg_dump project into a new shared location. --- src/bin/pg_dump/pg_backup_db.c | 102 +------------------------- src/bin/pg_dump/pg_backup_db.h | 17 ----- src/fe_utils/Makefile | 1 + src/fe_utils/query_utils.c | 114 +++++++++++++++++++++++++++++ src/include/fe_utils/query_utils.h | 34 +++++++++ 5 files changed, 150 insertions(+), 118 deletions(-) create mode 100644 src/fe_utils/query_utils.c create mode 100644 src/include/fe_utils/query_utils.h diff --git a/src/bin/pg_dump/pg_backup_db.c b/src/bin/pg_dump/pg_backup_db.c index b55a968da2..38402d0831 100644 --- a/src/bin/pg_dump/pg_backup_db.c +++ b/src/bin/pg_dump/pg_backup_db.c @@ -20,6 +20,7 @@ #include "common/connect.h" #include "common/string.h" #include "dumputils.h" +#include "fe_utils/query_utils.h" #include "fe_utils/string_utils.h" #include "parallel.h" #include "pg_backup_archiver.h" @@ -271,107 +272,6 @@ notice_processor(void *arg, const char *message) pg_log_generic(PG_LOG_INFO, "%s", message); } -/* - * The exiting query result handler embeds the historical pg_dump behavior - * under query error conditions, including exiting nicely. The 'conn' object - * is unused here, but is included in the interface for alternate query result - * handler implementations. - * - * Whether the query was successful is determined by comparing the returned - * status code against the expected status code, and by comparing the number of - * tuples returned from the query against expected_ntups. Special negative - * values of expected_ntups can be used to require at least one row or to - * disables ntup checking. - * - * Exits on failure. On successful query completion, returns the 'res' - * argument as a notational convenience. - */ -PGresult * -exiting_handler(PGresult *res, PGconn *conn, ExecStatusType expected_status, - int expected_ntups, const char *query) -{ - if (PQresultStatus(res) != expected_status) - { - pg_log_error("query failed: %s", PQerrorMessage(conn)); - pg_log_error("query was: %s", query); - PQfinish(conn); - exit_nicely(1); - } - if (expected_ntups == POSITIVE_NTUPS || expected_ntups >= 0) - { - int ntups = PQntuples(res); - - if (expected_ntups == POSITIVE_NTUPS) - { - if (ntups == 0) - fatal("query returned no rows: %s", query); - } - else if (ntups != expected_ntups) - { - /* - * Preserve historical message behavior of spelling "one" as the - * expected row count. - */ - if (expected_ntups == 1) - fatal(ngettext("query returned %d row instead of one: %s", - "query returned %d rows instead of one: %s", - ntups), - ntups, query); - fatal(ngettext("query returned %d row instead of %d: %s", - "query returned %d rows instead of %d: %s", - ntups), - ntups, expected_ntups, query); - } - } - return res; -} - -/* - * Executes the given SQL query statement. - * - * Invokes the exiting handler for any but PGRES_COMMAND_OK status. - */ -void -ExecuteSqlStatement(PGconn *conn, const char *query) -{ - PQclear(exiting_handler(PQexec(conn, query), - conn, - PGRES_COMMAND_OK, - ANY_NTUPS, - query)); -} - -/* - * Executes the given SQL query. - * - * Invokes the exiting handler unless the given 'status' results. - * - * If successful, returns the query result. - */ -PGresult * -ExecuteSqlQuery(PGconn *conn, const char *query, ExecStatusType status) -{ - return exiting_handler(PQexec(conn, query), - conn, - status, - ANY_NTUPS, - query); -} - -/* - * Like ExecuteSqlQuery, but requires PGRES_TUPLES_OK status and - * requires that exactly one row be returned. - */ -PGresult * -ExecuteSqlQueryForSingleRow(PGconn *conn, const char *query) -{ - return exiting_handler(PQexec(conn, query), - conn, - PGRES_TUPLES_OK, - 1, - query); -} - void ExecuteSqlStatementAH(Archive *AHX, const char *query) { diff --git a/src/bin/pg_dump/pg_backup_db.h b/src/bin/pg_dump/pg_backup_db.h index 1aac600ece..018a28908e 100644 --- a/src/bin/pg_dump/pg_backup_db.h +++ b/src/bin/pg_dump/pg_backup_db.h @@ -13,23 +13,6 @@ extern int ExecuteSqlCommandBuf(Archive *AHX, const char *buf, size_t bufLen); -#define POSITIVE_NTUPS (-1) -#define ANY_NTUPS (-2) -typedef PGresult *(*PGresultHandler) (PGresult *res, - PGconn *conn, - ExecStatusType expected_status, - int expected_ntups, - const char *query); - -extern PGresult *exiting_handler(PGresult *res, PGconn *conn, - ExecStatusType expected_status, - int expected_ntups, const char *query); - -extern void ExecuteSqlStatement(PGconn *conn, const char *query); -extern PGresult *ExecuteSqlQuery(PGconn *conn, const char *query, - ExecStatusType expected_status); -extern PGresult *ExecuteSqlQueryForSingleRow(PGconn *conn, const char *query); - extern void ExecuteSqlStatementAH(Archive *AHX, const char *query); extern PGresult *ExecuteSqlQueryAH(Archive *AHX, const char *query, ExecStatusType status); diff --git a/src/fe_utils/Makefile b/src/fe_utils/Makefile index d6c328faf1..7fdbe08e11 100644 --- a/src/fe_utils/Makefile +++ b/src/fe_utils/Makefile @@ -27,6 +27,7 @@ OBJS = \ mbprint.o \ print.o \ psqlscan.o \ + query_utils.o \ recovery_gen.o \ simple_list.o \ string_utils.o diff --git a/src/fe_utils/query_utils.c b/src/fe_utils/query_utils.c new file mode 100644 index 0000000000..b28750f4b2 --- /dev/null +++ b/src/fe_utils/query_utils.c @@ -0,0 +1,114 @@ +/*------------------------------------------------------------------------- + * + * Query executing routines with facilities for modular error handling. + * + * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/fe_utils/query_utils.c + * + *------------------------------------------------------------------------- + */ +#include "fe_utils/exit_utils.h" +#include "fe_utils/query_utils.h" + +/* + * The exiting query result handler embeds the historical pg_dump behavior + * under query error conditions, including exiting nicely. The 'conn' object + * is unused here, but is included in the interface for alternate query result + * handler implementations. + * + * Whether the query was successful is determined by comparing the returned + * status code against the expected status code, and by comparing the number of + * tuples returned from the query against expected_ntups. Special negative + * values of expected_ntups can be used to require at least one row or to + * disables ntup checking. + * + * Exits on failure. On successful query completion, returns the 'res' + * argument as a notational convenience. + */ +PGresult * +exiting_handler(PGresult *res, PGconn *conn, ExecStatusType expected_status, + int expected_ntups, const char *query) +{ + if (PQresultStatus(res) != expected_status) + { + pg_log_error("query failed: %s", PQerrorMessage(conn)); + pg_log_error("query was: %s", query); + PQfinish(conn); + exit_nicely(1); + } + if (expected_ntups == POSITIVE_NTUPS || expected_ntups >= 0) + { + int ntups = PQntuples(res); + + if (expected_ntups == POSITIVE_NTUPS) + { + if (ntups == 0) + fatal("query returned no rows: %s", query); + } + else if (ntups != expected_ntups) + { + /* + * Preserve historical message behavior of spelling "one" as the + * expected row count. + */ + if (expected_ntups == 1) + fatal(ngettext("query returned %d row instead of one: %s", + "query returned %d rows instead of one: %s", + ntups), + ntups, query); + fatal(ngettext("query returned %d row instead of %d: %s", + "query returned %d rows instead of %d: %s", + ntups), + ntups, expected_ntups, query); + } + } + return res; +} + +/* + * Executes the given SQL query statement. + * + * Invokes the exiting handler for any but PGRES_COMMAND_OK status. + */ +void +ExecuteSqlStatement(PGconn *conn, const char *query) +{ + PQclear(exiting_handler(PQexec(conn, query), + conn, + PGRES_COMMAND_OK, + ANY_NTUPS, + query)); +} + +/* + * Executes the given SQL query. + * + * Invokes the exiting handler unless the given 'status' results. + * + * If successful, returns the query result. + */ +PGresult * +ExecuteSqlQuery(PGconn *conn, const char *query, ExecStatusType status) +{ + return exiting_handler(PQexec(conn, query), + conn, + status, + ANY_NTUPS, + query); +} + +/* + * Like ExecuteSqlQuery, but requires PGRES_TUPLES_OK status and + * requires that exactly one row be returned. + */ +PGresult * +ExecuteSqlQueryForSingleRow(PGconn *conn, const char *query) +{ + return exiting_handler(PQexec(conn, query), + conn, + PGRES_TUPLES_OK, + 1, + query); +} diff --git a/src/include/fe_utils/query_utils.h b/src/include/fe_utils/query_utils.h new file mode 100644 index 0000000000..f03d17b1ed --- /dev/null +++ b/src/include/fe_utils/query_utils.h @@ -0,0 +1,34 @@ +/*------------------------------------------------------------------------- + * + * Query executing routines with facilities for modular error handling. + * + * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/fe_utils/query_utils.h + * + *------------------------------------------------------------------------- + */ +#ifndef QUERY_UTILS_H +#define QUERY_UTILS_H + +#include "libpq-fe.h" + +#define POSITIVE_NTUPS (-1) +#define ANY_NTUPS (-2) +typedef PGresult *(*PGresultHandler) (PGresult *res, + PGconn *conn, + ExecStatusType expected_status, + int expected_ntups, + const char *query); + +extern PGresult *exiting_handler(PGresult *res, PGconn *conn, + ExecStatusType expected_status, + int expected_ntups, const char *query); + +extern void ExecuteSqlStatement(PGconn *conn, const char *query); +extern PGresult *ExecuteSqlQuery(PGconn *conn, const char *query, + ExecStatusType expected_status); +extern PGresult *ExecuteSqlQueryForSingleRow(PGconn *conn, const char *query); + +#endif /* QUERY_UTILS_H */ -- 2.21.1 (Apple Git-122.3)