diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml index 81fb06e148..4162e51b50 100644 --- a/doc/src/sgml/ref/psql-ref.sgml +++ b/doc/src/sgml/ref/psql-ref.sgml @@ -1,5 +1,5 @@ @@ -222,6 +222,17 @@ PostgreSQL documentation + + + + + + Log all query output into file filename in addition to the regular output source. + + + + diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c index b1cec74499..df17d0404b 100644 --- a/src/bin/psql/common.c +++ b/src/bin/psql/common.c @@ -3,7 +3,7 @@ * * Copyright (c) 2000-2005, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/bin/psql/common.c,v 1.101 2005/06/13 06:36:22 neilc Exp $ + * $PostgreSQL: pgsql/src/bin/psql/common.c,v 1.102 2005/06/14 02:57:41 momjian Exp $ */ #include "postgres_fe.h" #include "common.h" @@ -723,6 +723,13 @@ PSQLexec(const char *query, bool start_xact) "%s\n" "**************************\n\n", query); fflush(stdout); + if (pset.logfile) + { + fprintf(pset.logfile, "********* QUERY **********\n" + "%s\n" + "**************************\n\n", query); + fflush(pset.logfile); + } if (echo_hidden == 1) /* noexec? */ return NULL; @@ -803,7 +810,7 @@ PrintQueryTuples(const PGresult *results) return false; } - printQuery(results, &my_popt, pset.queryFout); + printQuery(results, &my_popt, pset.queryFout, pset.logfile); /* close file/pipe, restore old setting */ setQFout(NULL); @@ -815,7 +822,7 @@ PrintQueryTuples(const PGresult *results) pset.gfname = NULL; } else - printQuery(results, &my_popt, pset.queryFout); + printQuery(results, &my_popt, pset.queryFout, pset.logfile); return true; } @@ -905,6 +912,8 @@ PrintQueryResults(PGresult *results) else fprintf(pset.queryFout, "%s\n", PQcmdStatus(results)); } + if (pset.logfile) + fprintf(pset.logfile, "%s\n", PQcmdStatus(results)); SetVariable(pset.vars, "LASTOID", buf); break; } @@ -976,6 +985,14 @@ SendQuery(const char *query) fflush(stdout); } + if (pset.logfile) + { + fprintf(pset.logfile, "********* QUERY **********\n" + "%s\n" + "**************************\n\n", query); + fflush(pset.logfile); + } + SetCancelConn(); transaction_status = PQtransactionStatus(pset.db); diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 45178c0eeb..17549b2b5f 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -3,7 +3,7 @@ * * Copyright (c) 2000-2005, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.115 2005/04/06 05:23:32 neilc Exp $ + * $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.116 2005/06/14 02:57:41 momjian Exp $ */ #include "postgres_fe.h" #include "describe.h" @@ -94,7 +94,7 @@ describeAggregates(const char *pattern, bool verbose) myopt.nullPrint = NULL; myopt.title = _("List of aggregate functions"); - printQuery(res, &myopt, pset.queryFout); + printQuery(res, &myopt, pset.queryFout, pset.logfile); PQclear(res); return true; @@ -147,7 +147,7 @@ describeTablespaces(const char *pattern, bool verbose) myopt.nullPrint = NULL; myopt.title = _("List of tablespaces"); - printQuery(res, &myopt, pset.queryFout); + printQuery(res, &myopt, pset.queryFout, pset.logfile); PQclear(res); return true; @@ -219,7 +219,7 @@ describeFunctions(const char *pattern, bool verbose) myopt.nullPrint = NULL; myopt.title = _("List of functions"); - printQuery(res, &myopt, pset.queryFout); + printQuery(res, &myopt, pset.queryFout, pset.logfile); PQclear(res); return true; @@ -287,7 +287,7 @@ describeTypes(const char *pattern, bool verbose) myopt.nullPrint = NULL; myopt.title = _("List of data types"); - printQuery(res, &myopt, pset.queryFout); + printQuery(res, &myopt, pset.queryFout, pset.logfile); PQclear(res); return true; @@ -334,7 +334,7 @@ describeOperators(const char *pattern) myopt.nullPrint = NULL; myopt.title = _("List of operators"); - printQuery(res, &myopt, pset.queryFout); + printQuery(res, &myopt, pset.queryFout, pset.logfile); PQclear(res); return true; @@ -379,7 +379,7 @@ listAllDbs(bool verbose) myopt.nullPrint = NULL; myopt.title = _("List of databases"); - printQuery(res, &myopt, pset.queryFout); + printQuery(res, &myopt, pset.queryFout, pset.logfile); PQclear(res); return true; @@ -436,7 +436,7 @@ permissionsList(const char *pattern) printfPQExpBuffer(&buf, _("Access privileges for database \"%s\""), PQdb(pset.db)); myopt.title = buf.data; - printQuery(res, &myopt, pset.queryFout); + printQuery(res, &myopt, pset.queryFout, pset.logfile); termPQExpBuffer(&buf); PQclear(res); @@ -592,7 +592,7 @@ objectDescription(const char *pattern) myopt.nullPrint = NULL; myopt.title = _("Object descriptions"); - printQuery(res, &myopt, pset.queryFout); + printQuery(res, &myopt, pset.queryFout, pset.logfile); PQclear(res); return true; @@ -1279,7 +1279,7 @@ describeOneTableDetails(const char *schemaname, printTable(title.data, headers, (const char **) cells, (const char **) footers, - "llll", &myopt, pset.queryFout); + "llll", &myopt, pset.queryFout, pset.logfile); retval = true; @@ -1391,7 +1391,7 @@ describeUsers(const char *pattern) myopt.nullPrint = NULL; myopt.title = _("List of users"); - printQuery(res, &myopt, pset.queryFout); + printQuery(res, &myopt, pset.queryFout, pset.logfile); PQclear(res); return true; @@ -1431,7 +1431,7 @@ describeGroups(const char *pattern) myopt.nullPrint = NULL; myopt.title = _("List of groups"); - printQuery(res, &myopt, pset.queryFout); + printQuery(res, &myopt, pset.queryFout, pset.logfile); PQclear(res); return true; @@ -1549,7 +1549,7 @@ listTables(const char *tabtypes, const char *pattern, bool verbose) myopt.nullPrint = NULL; myopt.title = _("List of relations"); - printQuery(res, &myopt, pset.queryFout); + printQuery(res, &myopt, pset.queryFout, pset.logfile); } PQclear(res); @@ -1605,7 +1605,7 @@ listDomains(const char *pattern) myopt.nullPrint = NULL; myopt.title = _("List of domains"); - printQuery(res, &myopt, pset.queryFout); + printQuery(res, &myopt, pset.queryFout, pset.logfile); PQclear(res); return true; @@ -1656,7 +1656,7 @@ listConversions(const char *pattern) myopt.nullPrint = NULL; myopt.title = _("List of conversions"); - printQuery(res, &myopt, pset.queryFout); + printQuery(res, &myopt, pset.queryFout, pset.logfile); PQclear(res); return true; @@ -1706,7 +1706,7 @@ listCasts(const char *pattern) myopt.nullPrint = NULL; myopt.title = _("List of casts"); - printQuery(res, &myopt, pset.queryFout); + printQuery(res, &myopt, pset.queryFout, pset.logfile); PQclear(res); return true; @@ -1756,7 +1756,7 @@ listSchemas(const char *pattern, bool verbose) myopt.nullPrint = NULL; myopt.title = _("List of schemas"); - printQuery(res, &myopt, pset.queryFout); + printQuery(res, &myopt, pset.queryFout, pset.logfile); PQclear(res); return true; diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c index 8b3dbcf602..9c1e6d3a57 100644 --- a/src/bin/psql/help.c +++ b/src/bin/psql/help.c @@ -3,7 +3,7 @@ * * Copyright (c) 2000-2005, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/bin/psql/help.c,v 1.101 2005/02/22 04:40:55 momjian Exp $ + * $PostgreSQL: pgsql/src/bin/psql/help.c,v 1.102 2005/06/14 02:57:41 momjian Exp $ */ #include "postgres_fe.h" #include "common.h" @@ -60,7 +60,7 @@ usage(void) user = getenv("PGUSER"); if (!user) { -#ifndef WIN32 +#if !defined(WIN32) && !defined(__OS2__) pw = getpwuid(geteuid()); if (pw) user = pw->pw_name; @@ -107,6 +107,7 @@ usage(void) puts(_(" -n disable enhanced command line editing (readline)")); puts(_(" -s single-step mode (confirm each query)")); puts(_(" -S single-line mode (end of line terminates SQL command)")); + puts(_(" -L FILENAME send session log to file")); puts(_("\nOutput format options:")); puts(_(" -A unaligned table output mode (-P format=unaligned)")); diff --git a/src/bin/psql/large_obj.c b/src/bin/psql/large_obj.c index 624ccd0be6..6606e99849 100644 --- a/src/bin/psql/large_obj.c +++ b/src/bin/psql/large_obj.c @@ -3,7 +3,7 @@ * * Copyright (c) 2000-2005, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/bin/psql/large_obj.c,v 1.36 2005/02/22 04:40:55 momjian Exp $ + * $PostgreSQL: pgsql/src/bin/psql/large_obj.c,v 1.37 2005/06/14 02:57:41 momjian Exp $ */ #include "postgres_fe.h" #include "large_obj.h" @@ -263,7 +263,7 @@ do_lo_list(void) myopt.nullPrint = NULL; myopt.title = _("Large objects"); - printQuery(res, &myopt, pset.queryFout); + printQuery(res, &myopt, pset.queryFout, pset.logfile); PQclear(res); return true; diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c index ede239e2e9..d1ef95f50a 100644 --- a/src/bin/psql/print.c +++ b/src/bin/psql/print.c @@ -3,7 +3,7 @@ * * Copyright (c) 2000-2005, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.58 2005/06/13 06:36:22 neilc Exp $ + * $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.59 2005/06/14 02:57:41 momjian Exp $ */ #include "postgres_fe.h" #include "common.h" @@ -1255,7 +1255,7 @@ printTable(const char *title, const char *const * cells, const char *const * footers, const char *align, - const printTableOpt *opt, FILE *fout) + const printTableOpt *opt, FILE *fout, FILE *flog) { const char *default_footer[] = {NULL}; unsigned short int border = opt->border; @@ -1312,6 +1312,9 @@ printTable(const char *title, /* print the stuff */ + if (flog) + print_aligned_text(title, headers, cells, footers, align, opt->tuples_only, border, opt->encoding, flog); + switch (opt->format) { case PRINT_UNALIGNED: @@ -1380,7 +1383,7 @@ printTable(const char *title, void -printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout) +printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *flog) { int nfields; int ncells; @@ -1476,7 +1479,7 @@ printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout) /* call table printer */ printTable(opt->title, headers, cells, (const char *const *) footers, - align, &opt->topt, fout); + align, &opt->topt, fout, flog); free(headers); free(cells); diff --git a/src/bin/psql/print.h b/src/bin/psql/print.h index f28b7f9d24..7dcc2657f1 100644 --- a/src/bin/psql/print.h +++ b/src/bin/psql/print.h @@ -3,7 +3,7 @@ * * Copyright (c) 2000-2005, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/bin/psql/print.h,v 1.24 2005/06/13 06:36:22 neilc Exp $ + * $PostgreSQL: pgsql/src/bin/psql/print.h,v 1.25 2005/06/14 02:57:41 momjian Exp $ */ #ifndef PRINT_H #define PRINT_H @@ -62,7 +62,7 @@ typedef struct _printTableOpt void printTable(const char *title, const char *const * headers, const char *const * cells, const char *const * footers, const char *align, - const printTableOpt *opt, FILE *fout); + const printTableOpt *opt, FILE *fout, FILE *flog); @@ -82,7 +82,8 @@ typedef struct _printQueryOpt * * It calls the printTable above with all the things set straight. */ -void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout); +void printQuery(const PGresult *result, const printQueryOpt *opt, + FILE *fout, FILE *flog); #ifndef __CYGWIN__ #define DEFAULT_PAGER "more" diff --git a/src/bin/psql/settings.h b/src/bin/psql/settings.h index 5090efd7b6..f4e78f407e 100644 --- a/src/bin/psql/settings.h +++ b/src/bin/psql/settings.h @@ -3,7 +3,7 @@ * * Copyright (c) 2000-2005, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/bin/psql/settings.h,v 1.24 2005/06/09 23:28:10 momjian Exp $ + * $PostgreSQL: pgsql/src/bin/psql/settings.h,v 1.25 2005/06/14 02:57:41 momjian Exp $ */ #ifndef SETTINGS_H #define SETTINGS_H @@ -56,6 +56,7 @@ typedef struct _psqlSettings bool timing; /* enable timing of all queries */ PGVerbosity verbosity; /* current error verbosity level */ + FILE *logfile; /* session log file handle */ } PsqlSettings; extern PsqlSettings pset; diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c index 9e27b8c002..ff8a5c2431 100644 --- a/src/bin/psql/startup.c +++ b/src/bin/psql/startup.c @@ -3,7 +3,7 @@ * * Copyright (c) 2000-2005, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/bin/psql/startup.c,v 1.116 2005/06/13 06:36:22 neilc Exp $ + * $PostgreSQL: pgsql/src/bin/psql/startup.c,v 1.117 2005/06/14 02:57:41 momjian Exp $ */ #include "postgres_fe.h" @@ -71,6 +71,7 @@ struct adhoc_opts char *host; char *port; char *username; + char *logfilename; enum _actions action; char *action_string; bool no_readline; @@ -109,8 +110,6 @@ main(int argc, char *argv[]) set_pglocale_pgservice(argv[0], "psql"); - pset.progname = get_progname(argv[0]); - if (argc > 1) { if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0) @@ -125,6 +124,8 @@ main(int argc, char *argv[]) } } + pset.progname = get_progname(argv[0]); + #ifdef WIN32 setvbuf(stderr, NULL, _IONBF, 0); setup_win32_locks(); @@ -234,6 +235,13 @@ main(int argc, char *argv[]) exit(success ? EXIT_SUCCESS : EXIT_FAILURE); } + if (options.logfilename) + { + pset.logfile = fopen(options.logfilename, "a"); + if (!pset.logfile) + fprintf(stderr, gettext("logfile open failed for %s\n\n"), options.logfilename); + } + /* * Now find something to do */ @@ -316,6 +324,8 @@ main(int argc, char *argv[]) } /* clean up */ + if (pset.logfile) + fclose(pset.logfile); PQfinish(pset.db); setQFout(NULL); @@ -344,6 +354,7 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options) {"host", required_argument, NULL, 'h'}, {"html", no_argument, NULL, 'H'}, {"list", no_argument, NULL, 'l'}, + {"log", required_argument, NULL, 'L'}, {"no-readline", no_argument, NULL, 'n'}, {"output", required_argument, NULL, 'o'}, {"port", required_argument, NULL, 'p'}, @@ -373,7 +384,7 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options) memset(options, 0, sizeof *options); - while ((c = getopt_long(argc, argv, "aAc:d:eEf:F:h:Hlno:p:P:qR:sStT:uU:v:VWxX?", + while ((c = getopt_long(argc, argv, "aAc:d:eEf:F:h:HlL:no:p:P:qR:sStT:uU:v:VWxX?", long_options, &optindex)) != -1) { switch (c) @@ -419,6 +430,9 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options) case 'l': options->action = ACT_LIST_DB; break; + case 'L': + options->logfilename = optarg; + break; case 'n': options->no_readline = true; break; diff --git a/src/bin/scripts/createlang.c b/src/bin/scripts/createlang.c index b5ab23818f..e8015089c9 100644 --- a/src/bin/scripts/createlang.c +++ b/src/bin/scripts/createlang.c @@ -5,7 +5,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/bin/scripts/createlang.c,v 1.15 2004/12/31 22:03:17 pgsql Exp $ + * $PostgreSQL: pgsql/src/bin/scripts/createlang.c,v 1.16 2005/06/14 02:57:45 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -148,7 +148,7 @@ main(int argc, char *argv[]) popt.topt.border = 1; popt.topt.encoding = PQclientEncoding(conn); popt.title = _("Procedural Languages"); - printQuery(result, &popt, stdout); + printQuery(result, &popt, stdout, NULL); PQfinish(conn); exit(0); diff --git a/src/bin/scripts/droplang.c b/src/bin/scripts/droplang.c index cbd7dc9199..5be336dd6d 100644 --- a/src/bin/scripts/droplang.c +++ b/src/bin/scripts/droplang.c @@ -5,7 +5,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/bin/scripts/droplang.c,v 1.14 2004/12/31 22:03:17 pgsql Exp $ + * $PostgreSQL: pgsql/src/bin/scripts/droplang.c,v 1.15 2005/06/14 02:57:45 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -145,7 +145,7 @@ main(int argc, char *argv[]) popt.topt.border = 1; popt.topt.encoding = PQclientEncoding(conn); popt.title = _("Procedural Languages"); - printQuery(result, &popt, stdout); + printQuery(result, &popt, stdout, NULL); PQfinish(conn); exit(0);