psql output locations

Started by Magnus Haganderabout 14 years ago8 messages
#1Magnus Hagander
magnus@hagander.net

We're either pretty inconsistent with our output in psql, or I'm not
completely understanding it.. I was trying to implement a switch that
would let me put all the output in the query output channel controlled
by \o, and not just the output of the query itself. Because that would
make it possible to control it from inside the script. Now, this made
me notice:

* There are 102 calls to psql_error(), 42 direct uses of
fprintf(stderr), and 7 uses of fputs(stderr). And there is also
write_stderr() used in the cancel handler. Is there actually a point
behind all those direct uses, or should they really be psql_error()
calls?

* There are a number of things that are always written to stdout, that
there is no way to redirect. In some cases it's interactive prompts -
makes sense - but also for example the output of \timing goes to
stdout always. Is there some specific logic behind what/when this
should be done?

--
 Magnus Hagander
 Me: http://www.hagander.net/
 Work: http://www.redpill-linpro.com/

#2Peter Eisentraut
peter_e@gmx.net
In reply to: Magnus Hagander (#1)
Re: psql output locations

On mån, 2011-12-12 at 14:47 +0100, Magnus Hagander wrote:

We're either pretty inconsistent with our output in psql, or I'm not
completely understanding it.. I was trying to implement a switch that
would let me put all the output in the query output channel controlled
by \o, and not just the output of the query itself. Because that would
make it possible to control it from inside the script. Now, this made
me notice:

* There are 102 calls to psql_error(), 42 direct uses of
fprintf(stderr), and 7 uses of fputs(stderr). And there is also
write_stderr() used in the cancel handler. Is there actually a point
behind all those direct uses, or should they really be psql_error()
calls?

Some of this could probably be more more uniform. But I don't see how
this related to your question. All the output goes uniformly to stderr,
which is what matters.

* There are a number of things that are always written to stdout, that
there is no way to redirect. In some cases it's interactive prompts -
makes sense - but also for example the output of \timing goes to
stdout always. Is there some specific logic behind what/when this
should be done?

Everything that is not an error goes to stdout, no? Except the query
output, if you change it.

Maybe the way to do what you want is to invent a new setting that
temporarily changes stdout.

#3Magnus Hagander
magnus@hagander.net
In reply to: Peter Eisentraut (#2)
Re: psql output locations

On Mon, Dec 12, 2011 at 21:04, Peter Eisentraut <peter_e@gmx.net> wrote:

On mån, 2011-12-12 at 14:47 +0100, Magnus Hagander wrote:

We're either pretty inconsistent with our output in psql, or I'm not
completely understanding it.. I was trying to implement a switch that
would let me put all the output in the query output channel controlled
by \o, and not just the output of the query itself. Because that would
make it possible to control it from inside the script. Now, this made
me notice:

* There are 102 calls to psql_error(), 42 direct uses of
fprintf(stderr), and 7 uses of fputs(stderr). And there is also
write_stderr() used in the cancel handler. Is there actually a point
behind all those direct uses, or should they really be psql_error()
calls?

Some of this could probably be more more uniform.  But I don't see how
this related to your question.  All the output goes uniformly to stderr,
which is what matters.

I was overriding psql_error() to write it to the same file as the \o
output was written too - and that only worked for some of the errors.
It seemed like the logical place to put such a redirection...

* There are a number of things that are always written to stdout, that
there is no way to redirect. In some cases it's interactive prompts -
makes sense - but also for example the output of \timing goes to
stdout always. Is there some specific logic behind what/when this
should be done?

Everything that is not an error goes to stdout, no?  Except the query
output, if you change it.

Maybe the way to do what you want is to invent a new setting that
temporarily changes stdout.

Yeah, that might be it. Or I need separate settings for "put errors in
the query output stream" and "put non-query-output-but-also-non-errors
in the query output stream". The effect would be the same, I guess...

--
 Magnus Hagander
 Me: http://www.hagander.net/
 Work: http://www.redpill-linpro.com/

#4Robert Haas
robertmhaas@gmail.com
In reply to: Magnus Hagander (#3)
Re: psql output locations

On Wed, Dec 14, 2011 at 4:45 AM, Magnus Hagander <magnus@hagander.net> wrote:

* There are a number of things that are always written to stdout, that
there is no way to redirect. In some cases it's interactive prompts -
makes sense - but also for example the output of \timing goes to
stdout always. Is there some specific logic behind what/when this
should be done?

Everything that is not an error goes to stdout, no?  Except the query
output, if you change it.

Maybe the way to do what you want is to invent a new setting that
temporarily changes stdout.

Yeah, that might be it. Or I need separate settings for "put errors in
the query output stream" and "put non-query-output-but-also-non-errors
in the query output stream". The effect would be the same, I guess...

That seems an awful lot harder (and messier) than just changing the
all the call sites to use the same error-reporting function.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#5Bruce Momjian
bruce@momjian.us
In reply to: Robert Haas (#4)
1 attachment(s)
Re: psql output locations

On Wed, Dec 14, 2011 at 10:57:25AM -0500, Robert Haas wrote:

On Wed, Dec 14, 2011 at 4:45 AM, Magnus Hagander <magnus@hagander.net> wrote:

* There are a number of things that are always written to stdout, that
there is no way to redirect. In some cases it's interactive prompts -
makes sense - but also for example the output of \timing goes to
stdout always. Is there some specific logic behind what/when this
should be done?

Everything that is not an error goes to stdout, no? �Except the query
output, if you change it.

Maybe the way to do what you want is to invent a new setting that
temporarily changes stdout.

Yeah, that might be it. Or I need separate settings for "put errors in
the query output stream" and "put non-query-output-but-also-non-errors
in the query output stream". The effect would be the same, I guess...

That seems an awful lot harder (and messier) than just changing the
all the call sites to use the same error-reporting function.

I have done as you suggested with the attached patch.

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ It's impossible for everything to be true. +

Attachments:

psql.difftext/x-diff; charset=us-asciiDownload
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
new file mode 100644
index 205bb50..dc04399
*** a/src/bin/psql/command.c
--- b/src/bin/psql/command.c
*************** HandleSlashCmds(PsqlScanState scan_state
*** 110,116 ****
  	if (status == PSQL_CMD_UNKNOWN)
  	{
  		if (pset.cur_cmd_interactive)
! 			fprintf(stderr, _("Invalid command \\%s. Try \\? for help.\n"), cmd);
  		else
  			psql_error("invalid command \\%s\n", cmd);
  		status = PSQL_CMD_ERROR;
--- 110,116 ----
  	if (status == PSQL_CMD_UNKNOWN)
  	{
  		if (pset.cur_cmd_interactive)
! 			psql_error("Invalid command \\%s. Try \\? for help.\n", cmd);
  		else
  			psql_error("invalid command \\%s\n", cmd);
  		status = PSQL_CMD_ERROR;
*************** exec_command(const char *cmd,
*** 904,910 ****
  
  		if (strcmp(pw1, pw2) != 0)
  		{
! 			fprintf(stderr, _("Passwords didn't match.\n"));
  			success = false;
  		}
  		else
--- 904,910 ----
  
  		if (strcmp(pw1, pw2) != 0)
  		{
! 			psql_error("Passwords didn't match.\n");
  			success = false;
  		}
  		else
*************** exec_command(const char *cmd,
*** 922,928 ****
  
  			if (!encrypted_password)
  			{
! 				fprintf(stderr, _("Password encryption failed.\n"));
  				success = false;
  			}
  			else
--- 922,928 ----
  
  			if (!encrypted_password)
  			{
! 				psql_error("Password encryption failed.\n");
  				success = false;
  			}
  			else
*************** exec_command(const char *cmd,
*** 1441,1447 ****
  		while ((value = psql_scan_slash_option(scan_state,
  											   OT_NORMAL, NULL, true)))
  		{
! 			fprintf(stderr, "+ opt(%d) = |%s|\n", i++, value);
  			free(value);
  		}
  	}
--- 1441,1447 ----
  		while ((value = psql_scan_slash_option(scan_state,
  											   OT_NORMAL, NULL, true)))
  		{
! 			psql_error("+ opt(%d) = |%s|\n", i++, value);
  			free(value);
  		}
  	}
*************** do_connect(char *dbname, char *user, cha
*** 1519,1525 ****
  		 *	to connect to the wrong database by using defaults, so require
  		 *	all parameters to be specified.
  		 */
! 		fputs(_("All connection parameters must be supplied because no database connection exists\n"), stderr);
  		return false;
  	}
  
--- 1519,1526 ----
  		 *	to connect to the wrong database by using defaults, so require
  		 *	all parameters to be specified.
  		 */
! 		psql_error("All connection parameters must be supplied because no "
! 				   "database connection exists\n");
  		return false;
  	}
  
*************** do_connect(char *dbname, char *user, cha
*** 1608,1614 ****
  
  			/* pset.db is left unmodified */
  			if (o_conn)
! 				fputs(_("Previous connection kept\n"), stderr);
  		}
  		else
  		{
--- 1609,1615 ----
  
  			/* pset.db is left unmodified */
  			if (o_conn)
! 				psql_error("Previous connection kept\n");
  		}
  		else
  		{
diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c
new file mode 100644
index 330d5ce..f5bd0f6
*** a/src/bin/psql/common.c
--- b/src/bin/psql/common.c
*************** pg_strdup(const char *string)
*** 42,48 ****
  
  	if (!string)
  	{
! 		fprintf(stderr, _("%s: pg_strdup: cannot duplicate null pointer (internal error)\n"),
  				pset.progname);
  		exit(EXIT_FAILURE);
  	}
--- 42,48 ----
  
  	if (!string)
  	{
! 		psql_error("%s: pg_strdup: cannot duplicate null pointer (internal error)\n",
  				pset.progname);
  		exit(EXIT_FAILURE);
  	}
*************** psql_error(const char *fmt,...)
*** 161,167 ****
  	va_list		ap;
  
  	fflush(stdout);
! 	if (pset.queryFout != stdout)
  		fflush(pset.queryFout);
  
  	if (pset.inputfile)
--- 161,167 ----
  	va_list		ap;
  
  	fflush(stdout);
! 	if (pset.queryFout && pset.queryFout != stdout)
  		fflush(pset.queryFout);
  
  	if (pset.inputfile)
*************** static PGcancel *volatile cancelConn = N
*** 219,224 ****
--- 219,225 ----
  static CRITICAL_SECTION cancelConnLock;
  #endif
  
+ /* Used from signal handlers, no buffering */
  #define write_stderr(str)	write(fileno(stderr), str, strlen(str))
  
  
*************** CheckConnection(void)
*** 350,368 ****
  			exit(EXIT_BADCONN);
  		}
  
! 		fputs(_("The connection to the server was lost. Attempting reset: "), stderr);
  		PQreset(pset.db);
  		OK = ConnectionUp();
  		if (!OK)
  		{
! 			fputs(_("Failed.\n"), stderr);
  			PQfinish(pset.db);
  			pset.db = NULL;
  			ResetCancelConn();
  			UnsyncVariables();
  		}
  		else
! 			fputs(_("Succeeded.\n"), stderr);
  	}
  
  	return OK;
--- 351,369 ----
  			exit(EXIT_BADCONN);
  		}
  
! 		psql_error("The connection to the server was lost. Attempting reset: ");
  		PQreset(pset.db);
  		OK = ConnectionUp();
  		if (!OK)
  		{
! 			psql_error("Failed.\n");
  			PQfinish(pset.db);
  			pset.db = NULL;
  			ResetCancelConn();
  			UnsyncVariables();
  		}
  		else
! 			psql_error("Succeeded.\n");
  	}
  
  	return OK;
*************** SendQuery(const char *query)
*** 910,916 ****
  	{
  		if (on_error_rollback_warning == false && pset.sversion < 80000)
  		{
! 			fprintf(stderr, _("The server (version %d.%d) does not support savepoints for ON_ERROR_ROLLBACK.\n"),
  					pset.sversion / 10000, (pset.sversion / 100) % 100);
  			on_error_rollback_warning = true;
  		}
--- 911,917 ----
  	{
  		if (on_error_rollback_warning == false && pset.sversion < 80000)
  		{
! 			psql_error("The server (version %d.%d) does not support savepoints for ON_ERROR_ROLLBACK.\n",
  					pset.sversion / 10000, (pset.sversion / 100) % 100);
  			on_error_rollback_warning = true;
  		}
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
new file mode 100644
index 14985ba..c2bcc5a
*** a/src/bin/psql/describe.c
--- b/src/bin/psql/describe.c
*************** describeTablespaces(const char *pattern,
*** 132,138 ****
  
  	if (pset.sversion < 80000)
  	{
! 		fprintf(stderr, _("The server (version %d.%d) does not support tablespaces.\n"),
  				pset.sversion / 10000, (pset.sversion / 100) % 100);
  		return true;
  	}
--- 132,138 ----
  
  	if (pset.sversion < 80000)
  	{
! 		psql_error("The server (version %d.%d) does not support tablespaces.\n",
  				pset.sversion / 10000, (pset.sversion / 100) % 100);
  		return true;
  	}
*************** describeFunctions(const char *functypes,
*** 219,231 ****
  
  	if (strlen(functypes) != strspn(functypes, "antwS+"))
  	{
! 		fprintf(stderr, _("\\df only takes [antwS+] as options\n"));
  		return true;
  	}
  
  	if (showWindow && pset.sversion < 80400)
  	{
! 		fprintf(stderr, _("\\df does not take a \"w\" option with server version %d.%d\n"),
  				pset.sversion / 10000, (pset.sversion / 100) % 100);
  		return true;
  	}
--- 219,231 ----
  
  	if (strlen(functypes) != strspn(functypes, "antwS+"))
  	{
! 		psql_error("\\df only takes [antwS+] as options\n");
  		return true;
  	}
  
  	if (showWindow && pset.sversion < 80400)
  	{
! 		psql_error("\\df does not take a \"w\" option with server version %d.%d\n",
  				pset.sversion / 10000, (pset.sversion / 100) % 100);
  		return true;
  	}
*************** listDefaultACLs(const char *pattern)
*** 786,792 ****
  
  	if (pset.sversion < 90000)
  	{
! 		fprintf(stderr, _("The server (version %d.%d) does not support altering default privileges.\n"),
  				pset.sversion / 10000, (pset.sversion / 100) % 100);
  		return true;
  	}
--- 786,792 ----
  
  	if (pset.sversion < 90000)
  	{
! 		psql_error("The server (version %d.%d) does not support altering default privileges.\n",
  				pset.sversion / 10000, (pset.sversion / 100) % 100);
  		return true;
  	}
*************** describeTableDetails(const char *pattern
*** 1052,1058 ****
  	if (PQntuples(res) == 0)
  	{
  		if (!pset.quiet)
! 			fprintf(stderr, _("Did not find any relation named \"%s\".\n"),
  					pattern);
  		PQclear(res);
  		return false;
--- 1052,1058 ----
  	if (PQntuples(res) == 0)
  	{
  		if (!pset.quiet)
! 			psql_error("Did not find any relation named \"%s\".\n",
  					pattern);
  		PQclear(res);
  		return false;
*************** describeOneTableDetails(const char *sche
*** 1225,1232 ****
  	if (PQntuples(res) == 0)
  	{
  		if (!pset.quiet)
! 			fprintf(stderr, _("Did not find any relation with OID %s.\n"),
! 					oid);
  		goto error_return;
  	}
  
--- 1225,1231 ----
  	if (PQntuples(res) == 0)
  	{
  		if (!pset.quiet)
! 			psql_error("Did not find any relation with OID %s.\n", oid);
  		goto error_return;
  	}
  
*************** listCollations(const char *pattern, bool
*** 3126,3132 ****
  
  	if (pset.sversion < 90100)
  	{
! 		fprintf(stderr, _("The server (version %d.%d) does not support collations.\n"),
  				pset.sversion / 10000, (pset.sversion / 100) % 100);
  		return true;
  	}
--- 3125,3131 ----
  
  	if (pset.sversion < 90100)
  	{
! 		psql_error("The server (version %d.%d) does not support collations.\n",
  				pset.sversion / 10000, (pset.sversion / 100) % 100);
  		return true;
  	}
*************** listTSParsers(const char *pattern, bool
*** 3257,3263 ****
  
  	if (pset.sversion < 80300)
  	{
! 		fprintf(stderr, _("The server (version %d.%d) does not support full text search.\n"),
  				pset.sversion / 10000, (pset.sversion / 100) % 100);
  		return true;
  	}
--- 3256,3262 ----
  
  	if (pset.sversion < 80300)
  	{
! 		psql_error("The server (version %d.%d) does not support full text search.\n",
  				pset.sversion / 10000, (pset.sversion / 100) % 100);
  		return true;
  	}
*************** listTSParsersVerbose(const char *pattern
*** 3334,3340 ****
  	if (PQntuples(res) == 0)
  	{
  		if (!pset.quiet)
! 			fprintf(stderr, _("Did not find any text search parser named \"%s\".\n"),
  					pattern);
  		PQclear(res);
  		return false;
--- 3333,3339 ----
  	if (PQntuples(res) == 0)
  	{
  		if (!pset.quiet)
! 			psql_error("Did not find any text search parser named \"%s\".\n",
  					pattern);
  		PQclear(res);
  		return false;
*************** listTSDictionaries(const char *pattern,
*** 3490,3496 ****
  
  	if (pset.sversion < 80300)
  	{
! 		fprintf(stderr, _("The server (version %d.%d) does not support full text search.\n"),
  				pset.sversion / 10000, (pset.sversion / 100) % 100);
  		return true;
  	}
--- 3489,3495 ----
  
  	if (pset.sversion < 80300)
  	{
! 		psql_error("The server (version %d.%d) does not support full text search.\n",
  				pset.sversion / 10000, (pset.sversion / 100) % 100);
  		return true;
  	}
*************** listTSTemplates(const char *pattern, boo
*** 3558,3564 ****
  
  	if (pset.sversion < 80300)
  	{
! 		fprintf(stderr, _("The server (version %d.%d) does not support full text search.\n"),
  				pset.sversion / 10000, (pset.sversion / 100) % 100);
  		return true;
  	}
--- 3557,3563 ----
  
  	if (pset.sversion < 80300)
  	{
! 		psql_error("The server (version %d.%d) does not support full text search.\n",
  				pset.sversion / 10000, (pset.sversion / 100) % 100);
  		return true;
  	}
*************** listTSConfigs(const char *pattern, bool
*** 3626,3632 ****
  
  	if (pset.sversion < 80300)
  	{
! 		fprintf(stderr, _("The server (version %d.%d) does not support full text search.\n"),
  				pset.sversion / 10000, (pset.sversion / 100) % 100);
  		return true;
  	}
--- 3625,3631 ----
  
  	if (pset.sversion < 80300)
  	{
! 		psql_error("The server (version %d.%d) does not support full text search.\n",
  				pset.sversion / 10000, (pset.sversion / 100) % 100);
  		return true;
  	}
*************** listTSConfigsVerbose(const char *pattern
*** 3704,3710 ****
  	if (PQntuples(res) == 0)
  	{
  		if (!pset.quiet)
! 			fprintf(stderr, _("Did not find any text search configuration named \"%s\".\n"),
  					pattern);
  		PQclear(res);
  		return false;
--- 3703,3709 ----
  	if (PQntuples(res) == 0)
  	{
  		if (!pset.quiet)
! 			psql_error("Did not find any text search configuration named \"%s\".\n",
  					pattern);
  		PQclear(res);
  		return false;
*************** listForeignDataWrappers(const char *patt
*** 3824,3830 ****
  
  	if (pset.sversion < 80400)
  	{
! 		fprintf(stderr, _("The server (version %d.%d) does not support foreign-data wrappers.\n"),
  				pset.sversion / 10000, (pset.sversion / 100) % 100);
  		return true;
  	}
--- 3823,3829 ----
  
  	if (pset.sversion < 80400)
  	{
! 		psql_error("The server (version %d.%d) does not support foreign-data wrappers.\n",
  				pset.sversion / 10000, (pset.sversion / 100) % 100);
  		return true;
  	}
*************** listForeignServers(const char *pattern,
*** 3904,3910 ****
  
  	if (pset.sversion < 80400)
  	{
! 		fprintf(stderr, _("The server (version %d.%d) does not support foreign servers.\n"),
  				pset.sversion / 10000, (pset.sversion / 100) % 100);
  		return true;
  	}
--- 3903,3909 ----
  
  	if (pset.sversion < 80400)
  	{
! 		psql_error("The server (version %d.%d) does not support foreign servers.\n",
  				pset.sversion / 10000, (pset.sversion / 100) % 100);
  		return true;
  	}
*************** listUserMappings(const char *pattern, bo
*** 3983,3989 ****
  
  	if (pset.sversion < 80400)
  	{
! 		fprintf(stderr, _("The server (version %d.%d) does not support user mappings.\n"),
  				pset.sversion / 10000, (pset.sversion / 100) % 100);
  		return true;
  	}
--- 3982,3988 ----
  
  	if (pset.sversion < 80400)
  	{
! 		psql_error("The server (version %d.%d) does not support user mappings.\n",
  				pset.sversion / 10000, (pset.sversion / 100) % 100);
  		return true;
  	}
*************** listForeignTables(const char *pattern, b
*** 4041,4047 ****
  
  	if (pset.sversion < 90100)
  	{
! 		fprintf(stderr, _("The server (version %d.%d) does not support foreign tables.\n"),
  				pset.sversion / 10000, (pset.sversion / 100) % 100);
  		return true;
  	}
--- 4040,4046 ----
  
  	if (pset.sversion < 90100)
  	{
! 		psql_error("The server (version %d.%d) does not support foreign tables.\n",
  				pset.sversion / 10000, (pset.sversion / 100) % 100);
  		return true;
  	}
*************** listExtensions(const char *pattern)
*** 4115,4121 ****
  
  	if (pset.sversion < 90100)
  	{
! 		fprintf(stderr, _("The server (version %d.%d) does not support extensions.\n"),
  				pset.sversion / 10000, (pset.sversion / 100) % 100);
  		return true;
  	}
--- 4114,4120 ----
  
  	if (pset.sversion < 90100)
  	{
! 		psql_error("The server (version %d.%d) does not support extensions.\n",
  				pset.sversion / 10000, (pset.sversion / 100) % 100);
  		return true;
  	}
*************** listExtensionContents(const char *patter
*** 4169,4175 ****
  
  	if (pset.sversion < 90100)
  	{
! 		fprintf(stderr, _("The server (version %d.%d) does not support extensions.\n"),
  				pset.sversion / 10000, (pset.sversion / 100) % 100);
  		return true;
  	}
--- 4168,4174 ----
  
  	if (pset.sversion < 90100)
  	{
! 		psql_error("The server (version %d.%d) does not support extensions.\n",
  				pset.sversion / 10000, (pset.sversion / 100) % 100);
  		return true;
  	}
*************** listExtensionContents(const char *patter
*** 4196,4205 ****
  		if (!pset.quiet)
  		{
  			if (pattern)
! 				fprintf(stderr, _("Did not find any extension named \"%s\".\n"),
  						pattern);
  			else
! 				fprintf(stderr, _("Did not find any extensions.\n"));
  		}
  		PQclear(res);
  		return false;
--- 4195,4204 ----
  		if (!pset.quiet)
  		{
  			if (pattern)
! 				psql_error("Did not find any extension named \"%s\".\n",
  						pattern);
  			else
! 				psql_error("Did not find any extensions.\n");
  		}
  		PQclear(res);
  		return false;
diff --git a/src/bin/psql/large_obj.c b/src/bin/psql/large_obj.c
new file mode 100644
index ea95be1..dc6ff37
*** a/src/bin/psql/large_obj.c
--- b/src/bin/psql/large_obj.c
*************** do_lo_export(const char *loid_arg, const
*** 155,161 ****
  	/* of course this status is documented nowhere :( */
  	if (status != 1)
  	{
! 		fputs(PQerrorMessage(pset.db), stderr);
  		return fail_lo_xact("\\lo_export", own_transaction);
  	}
  
--- 155,161 ----
  	/* of course this status is documented nowhere :( */
  	if (status != 1)
  	{
! 		psql_error("%s", PQerrorMessage(pset.db));
  		return fail_lo_xact("\\lo_export", own_transaction);
  	}
  
*************** do_lo_import(const char *filename_arg, c
*** 190,196 ****
  
  	if (loid == InvalidOid)
  	{
! 		fputs(PQerrorMessage(pset.db), stderr);
  		return fail_lo_xact("\\lo_import", own_transaction);
  	}
  
--- 190,196 ----
  
  	if (loid == InvalidOid)
  	{
! 		psql_error("%s", PQerrorMessage(pset.db));
  		return fail_lo_xact("\\lo_import", own_transaction);
  	}
  
*************** do_lo_unlink(const char *loid_arg)
*** 252,258 ****
  
  	if (status == -1)
  	{
! 		fputs(PQerrorMessage(pset.db), stderr);
  		return fail_lo_xact("\\lo_unlink", own_transaction);
  	}
  
--- 252,258 ----
  
  	if (status == -1)
  	{
! 		psql_error("%s", PQerrorMessage(pset.db));
  		return fail_lo_xact("\\lo_unlink", own_transaction);
  	}
  
#6Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Bruce Momjian (#5)
Re: psql output locations

Excerpts from Bruce Momjian's message of vie ago 17 11:17:58 -0400 2012:

On Wed, Dec 14, 2011 at 10:57:25AM -0500, Robert Haas wrote:

On Wed, Dec 14, 2011 at 4:45 AM, Magnus Hagander <magnus@hagander.net> wrote:

* There are a number of things that are always written to stdout, that
there is no way to redirect. In some cases it's interactive prompts -
makes sense - but also for example the output of \timing goes to
stdout always. Is there some specific logic behind what/when this
should be done?

Everything that is not an error goes to stdout, no?  Except the query
output, if you change it.

Maybe the way to do what you want is to invent a new setting that
temporarily changes stdout.

Yeah, that might be it. Or I need separate settings for "put errors in
the query output stream" and "put non-query-output-but-also-non-errors
in the query output stream". The effect would be the same, I guess...

That seems an awful lot harder (and messier) than just changing the
all the call sites to use the same error-reporting function.

I have done as you suggested with the attached patch.

The very first hunk in your patch changes code that seems to be
explicitely checking the "interactive" flag. Is the change really
wanted there? Note Magnus explicitely commented about those in his
original post.

--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

#7Bruce Momjian
bruce@momjian.us
In reply to: Alvaro Herrera (#6)
Re: psql output locations

On Fri, Aug 17, 2012 at 12:22:38PM -0400, Alvaro Herrera wrote:

Excerpts from Bruce Momjian's message of vie ago 17 11:17:58 -0400 2012:

On Wed, Dec 14, 2011 at 10:57:25AM -0500, Robert Haas wrote:

On Wed, Dec 14, 2011 at 4:45 AM, Magnus Hagander <magnus@hagander.net> wrote:

* There are a number of things that are always written to stdout, that
there is no way to redirect. In some cases it's interactive prompts -
makes sense - but also for example the output of \timing goes to
stdout always. Is there some specific logic behind what/when this
should be done?

Everything that is not an error goes to stdout, no? �Except the query
output, if you change it.

Maybe the way to do what you want is to invent a new setting that
temporarily changes stdout.

Yeah, that might be it. Or I need separate settings for "put errors in
the query output stream" and "put non-query-output-but-also-non-errors
in the query output stream". The effect would be the same, I guess...

That seems an awful lot harder (and messier) than just changing the
all the call sites to use the same error-reporting function.

I have done as you suggested with the attached patch.

The very first hunk in your patch changes code that seems to be
explicitely checking the "interactive" flag. Is the change really
wanted there? Note Magnus explicitely commented about those in his
original post.

I noticed that but the output would be the same because there is no
input file location to trigger. I thought the interactive flag was
there just to provide more customized text.

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ It's impossible for everything to be true. +

#8Bruce Momjian
bruce@momjian.us
In reply to: Bruce Momjian (#7)
Re: psql output locations

On Fri, Aug 17, 2012 at 12:28:58PM -0400, Bruce Momjian wrote:

On Fri, Aug 17, 2012 at 12:22:38PM -0400, Alvaro Herrera wrote:

Excerpts from Bruce Momjian's message of vie ago 17 11:17:58 -0400 2012:

On Wed, Dec 14, 2011 at 10:57:25AM -0500, Robert Haas wrote:

On Wed, Dec 14, 2011 at 4:45 AM, Magnus Hagander <magnus@hagander.net> wrote:

* There are a number of things that are always written to stdout, that
there is no way to redirect. In some cases it's interactive prompts -
makes sense - but also for example the output of \timing goes to
stdout always. Is there some specific logic behind what/when this
should be done?

Everything that is not an error goes to stdout, no? �Except the query
output, if you change it.

Maybe the way to do what you want is to invent a new setting that
temporarily changes stdout.

Yeah, that might be it. Or I need separate settings for "put errors in
the query output stream" and "put non-query-output-but-also-non-errors
in the query output stream". The effect would be the same, I guess...

That seems an awful lot harder (and messier) than just changing the
all the call sites to use the same error-reporting function.

I have done as you suggested with the attached patch.

The very first hunk in your patch changes code that seems to be
explicitely checking the "interactive" flag. Is the change really
wanted there? Note Magnus explicitely commented about those in his
original post.

I noticed that but the output would be the same because there is no
input file location to trigger. I thought the interactive flag was
there just to provide more customized text.

Applied.

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ It's impossible for everything to be true. +