diff -cpr head/src/bin/scripts/clusterdb.c working/src/bin/scripts/clusterdb.c *** head/src/bin/scripts/clusterdb.c 2007-02-14 03:06:18.000000000 +0900 --- working/src/bin/scripts/clusterdb.c 2007-03-19 10:08:40.000000000 +0900 *************** main(int argc, char *argv[]) *** 111,116 **** --- 111,118 ---- exit(1); } + setup_cancel_handler(); + if (alldb) { if (dbname) *************** cluster_one_database(const char *dbname, *** 159,165 **** PQExpBufferData sql; PGconn *conn; - PGresult *result; initPQExpBuffer(&sql); --- 161,166 ---- *************** cluster_one_database(const char *dbname, *** 169,180 **** appendPQExpBuffer(&sql, ";\n"); conn = connectDatabase(dbname, host, port, username, password, progname); ! ! if (echo) ! printf("%s", sql.data); ! result = PQexec(conn, sql.data); ! ! if (PQresultStatus(result) != PGRES_COMMAND_OK) { if (table) fprintf(stderr, _("%s: clustering of table \"%s\" in database \"%s\" failed: %s"), --- 170,176 ---- appendPQExpBuffer(&sql, ";\n"); conn = connectDatabase(dbname, host, port, username, password, progname); ! if (!executeMaintenance(conn, sql.data, echo)) { if (table) fprintf(stderr, _("%s: clustering of table \"%s\" in database \"%s\" failed: %s"), *************** cluster_one_database(const char *dbname, *** 185,192 **** PQfinish(conn); exit(1); } - - PQclear(result); PQfinish(conn); termPQExpBuffer(&sql); --- 181,186 ---- diff -cpr head/src/bin/scripts/common.c working/src/bin/scripts/common.c *** head/src/bin/scripts/common.c 2007-01-06 07:19:50.000000000 +0900 --- working/src/bin/scripts/common.c 2007-03-19 10:08:00.000000000 +0900 *************** *** 15,28 **** --- 15,38 ---- #include "postgres_fe.h" #include + #include #include #include "common.h" + #include "libpq/pqsignal.h" + + static void SetCancelConn(PGconn *conn); + static void ResetCancelConn(void); #ifndef HAVE_INT_OPTRESET int optreset; #endif + static PGcancel *volatile cancelConn = NULL; + + #ifdef WIN32 + static CRITICAL_SECTION cancelConnLock; + #endif /* * Returns the current user name. *************** executeCommand(PGconn *conn, const char *** 195,200 **** --- 205,231 ---- /* + * As above for a SQL command (returns succeeded status). + */ + bool + executeMaintenance(PGconn *conn, const char *query, bool echo) + { + PGresult *res; + bool r; + + if (echo) + printf("%s\n", query); + + SetCancelConn(conn); + res = PQexec(conn, query); + ResetCancelConn(); + r = (res && PQresultStatus(res) == PGRES_COMMAND_OK); + PQclear(res); + return r; + } + + + /* * Check yes/no answer in a localized way. 1=yes, 0=no, -1=neither. */ *************** yesno_prompt(const char *question) *** 237,239 **** --- 268,396 ---- _(PG_YESLETTER), _(PG_NOLETTER)); } } + + + /* + * SetCancelConn + * + * Set cancelConn to point to the current database connection. + */ + static void + SetCancelConn(PGconn *conn) + { + PGcancel *oldCancelConn; + + #ifdef WIN32 + EnterCriticalSection(&cancelConnLock); + #endif + + /* Free the old one if we have one */ + oldCancelConn = cancelConn; + /* be sure handle_sigint doesn't use pointer while freeing */ + cancelConn = NULL; + + if (oldCancelConn != NULL) + PQfreeCancel(oldCancelConn); + + cancelConn = PQgetCancel(conn); + + #ifdef WIN32 + LeaveCriticalSection(&cancelConnLock); + #endif + } + + /* + * ResetCancelConn + * + * Free the current cancel connection, if any, and set to NULL. + */ + static void + ResetCancelConn(void) + { + PGcancel *oldCancelConn; + + #ifdef WIN32 + EnterCriticalSection(&cancelConnLock); + #endif + + oldCancelConn = cancelConn; + /* be sure handle_sigint doesn't use pointer while freeing */ + cancelConn = NULL; + + if (oldCancelConn != NULL) + PQfreeCancel(oldCancelConn); + + #ifdef WIN32 + LeaveCriticalSection(&cancelConnLock); + #endif + } + + #ifndef WIN32 + + static void + handle_sigint(SIGNAL_ARGS) + { + int save_errno = errno; + char errbuf[256]; + + /* Send QueryCancel if we are processing a database query */ + if (cancelConn != NULL) + { + if (PQcancel(cancelConn, errbuf, sizeof(errbuf))) + fprintf(stderr, _("Cancel request sent\n")); + else + { + fprintf(stderr, _("Could not send cancel request: ")); + fprintf(stderr, errbuf); + } + } + + errno = save_errno; /* just in case the write changed it */ + } + + void + setup_cancel_handler(void) + { + pqsignal(SIGINT, handle_sigint); + } + + #else /* WIN32 */ + + static BOOL WINAPI + consoleHandler(DWORD dwCtrlType) + { + char errbuf[256]; + + if (dwCtrlType == CTRL_C_EVENT || + dwCtrlType == CTRL_BREAK_EVENT) + { + /* Send QueryCancel if we are processing a database query */ + EnterCriticalSection(&cancelConnLock); + if (cancelConn != NULL) + { + if (PQcancel(cancelConn, errbuf, sizeof(errbuf))) + fprintf(stderr, _("Cancel request sent\n")); + else + { + fprintf(stderr, _("Could not send cancel request: ")); + fprintf(stderr, errbuf); + } + } + LeaveCriticalSection(&cancelConnLock); + + return TRUE; + } + else + /* Return FALSE for any signals not being handled */ + return FALSE; + } + + void + setup_cancel_handler(void) + { + InitializeCriticalSection(&cancelConnLock); + + SetConsoleCtrlHandler(consoleHandler, TRUE); + } + + #endif /* WIN32 */ diff -cpr head/src/bin/scripts/common.h working/src/bin/scripts/common.h *** head/src/bin/scripts/common.h 2007-01-06 07:19:50.000000000 +0900 --- working/src/bin/scripts/common.h 2007-03-19 10:02:27.000000000 +0900 *************** *** 17,22 **** --- 17,24 ---- extern int optreset; #endif + extern bool cancel_pressed; + typedef void (*help_handler) (const char *progname); extern const char *get_user_name(const char *progname); *************** extern PGresult *executeQuery(PGconn *co *** 35,40 **** --- 37,47 ---- extern void executeCommand(PGconn *conn, const char *query, const char *progname, bool echo); + extern bool executeMaintenance(PGconn *conn, const char *query, + bool echo); + extern bool yesno_prompt(const char *question); + extern void setup_cancel_handler(void); + #endif /* COMMON_H */ diff -cpr head/src/bin/scripts/reindexdb.c working/src/bin/scripts/reindexdb.c *** head/src/bin/scripts/reindexdb.c 2007-02-14 03:06:18.000000000 +0900 --- working/src/bin/scripts/reindexdb.c 2007-03-19 10:09:05.000000000 +0900 *************** main(int argc, char *argv[]) *** 126,131 **** --- 126,133 ---- exit(1); } + setup_cancel_handler(); + if (alldb) { if (dbname) *************** reindex_one_database(const char *name, c *** 214,220 **** PQExpBufferData sql; PGconn *conn; - PGresult *result; initPQExpBuffer(&sql); --- 216,221 ---- *************** reindex_one_database(const char *name, c *** 229,239 **** conn = connectDatabase(dbname, host, port, username, password, progname); ! if (echo) ! printf("%s", sql.data); ! result = PQexec(conn, sql.data); ! ! if (PQresultStatus(result) != PGRES_COMMAND_OK) { if (strcmp(type, "TABLE") == 0) fprintf(stderr, _("%s: reindexing of table \"%s\" in database \"%s\" failed: %s"), --- 230,236 ---- conn = connectDatabase(dbname, host, port, username, password, progname); ! if (!executeMaintenance(conn, sql.data, echo)) { if (strcmp(type, "TABLE") == 0) fprintf(stderr, _("%s: reindexing of table \"%s\" in database \"%s\" failed: %s"), *************** reindex_one_database(const char *name, c *** 248,254 **** exit(1); } - PQclear(result); PQfinish(conn); termPQExpBuffer(&sql); --- 245,250 ---- *************** reindex_system_catalogs(const char *dbna *** 294,320 **** PQExpBufferData sql; PGconn *conn; - PGresult *result; initPQExpBuffer(&sql); appendPQExpBuffer(&sql, "REINDEX SYSTEM %s;\n", dbname); conn = connectDatabase(dbname, host, port, username, password, progname); ! ! if (echo) ! printf("%s", sql.data); ! result = PQexec(conn, sql.data); ! ! if (PQresultStatus(result) != PGRES_COMMAND_OK) { fprintf(stderr, _("%s: reindexing of system catalogs failed: %s"), progname, PQerrorMessage(conn)); PQfinish(conn); exit(1); } - - PQclear(result); PQfinish(conn); termPQExpBuffer(&sql); --- 290,308 ---- PQExpBufferData sql; PGconn *conn; initPQExpBuffer(&sql); appendPQExpBuffer(&sql, "REINDEX SYSTEM %s;\n", dbname); conn = connectDatabase(dbname, host, port, username, password, progname); ! if (!executeMaintenance(conn, sql.data, echo)) { fprintf(stderr, _("%s: reindexing of system catalogs failed: %s"), progname, PQerrorMessage(conn)); PQfinish(conn); exit(1); } PQfinish(conn); termPQExpBuffer(&sql); diff -cpr head/src/bin/scripts/vacuumdb.c working/src/bin/scripts/vacuumdb.c *** head/src/bin/scripts/vacuumdb.c 2007-02-14 02:39:39.000000000 +0900 --- working/src/bin/scripts/vacuumdb.c 2007-03-19 10:08:21.000000000 +0900 *************** main(int argc, char *argv[]) *** 128,133 **** --- 128,135 ---- exit(1); } + setup_cancel_handler(); + if (alldb) { if (dbname) *************** vacuum_one_database(const char *dbname, *** 178,184 **** PQExpBufferData sql; PGconn *conn; - PGresult *result; initPQExpBuffer(&sql); --- 180,185 ---- *************** vacuum_one_database(const char *dbname, *** 194,205 **** appendPQExpBuffer(&sql, ";\n"); conn = connectDatabase(dbname, host, port, username, password, progname); ! ! if (echo) ! printf("%s", sql.data); ! result = PQexec(conn, sql.data); ! ! if (PQresultStatus(result) != PGRES_COMMAND_OK) { if (table) fprintf(stderr, _("%s: vacuuming of table \"%s\" in database \"%s\" failed: %s"), --- 195,201 ---- appendPQExpBuffer(&sql, ";\n"); conn = connectDatabase(dbname, host, port, username, password, progname); ! if (!executeMaintenance(conn, sql.data, echo)) { if (table) fprintf(stderr, _("%s: vacuuming of table \"%s\" in database \"%s\" failed: %s"), *************** vacuum_one_database(const char *dbname, *** 210,217 **** PQfinish(conn); exit(1); } - - PQclear(result); PQfinish(conn); termPQExpBuffer(&sql); --- 206,211 ----