From 2ab0f11a796a7afa11bf22f59ffe5ebcc1bbf2ab Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter_e@gmx.net>
Date: Sat, 30 Jun 2001 17:26:12 +0000
Subject: [PATCH] NLS for the psql \d family of commands.  (E.g., the column
 headers will have localized strings.)  Also, modernize the system catalog
 queries where appropriate, e.g., with outer joins.

---
 src/bin/psql/describe.c | 745 ++++++++++++++--------------------------
 src/bin/psql/nls.mk     |   5 +-
 src/bin/psql/startup.c  |   4 +-
 3 files changed, 268 insertions(+), 486 deletions(-)

diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index f9b599f941b..9e88a8f7c57 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -3,7 +3,7 @@
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.33 2001/05/28 02:01:22 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.34 2001/06/30 17:26:11 petere Exp $
  */
 #include "postgres_fe.h"
 #include "describe.h"
@@ -15,6 +15,8 @@
 #include "print.h"
 #include "variables.h"
 
+#define _(x) gettext((x))
+
 
 /*----------------
  * Handlers for various slash commands displaying some sort of list
@@ -35,7 +37,7 @@
 bool
 describeAggregates(const char *name)
 {
-	char		buf[384 + 2 * REGEXP_CUTOFF];
+	char		buf[384 + REGEXP_CUTOFF];
 	PGresult   *res;
 	printQueryOpt myopt = pset.popt;
 
@@ -43,43 +45,32 @@ describeAggregates(const char *name)
 	 * There are two kinds of aggregates: ones that work on particular
 	 * types ones that work on all
 	 */
-	strcpy(buf,
-		   "SELECT a.aggname AS \"Name\", format_type(a.aggbasetype, NULL) AS \"Type\",\n"
-		   "  obj_description(a.oid) as \"Description\"\n"
-		   "FROM pg_aggregate a\n"
-		   "WHERE a.aggbasetype <> 0\n"
-		);
+	snprintf(buf, sizeof(buf),
+			 "SELECT a.aggname AS \"%s\",\n"
+			 "  CASE a.aggbasetype\n"
+			 "    WHEN 0 THEN CAST('%s' AS text)\n"
+			 "    ELSE format_type(a.aggbasetype, NULL)\n"
+			 "  END AS \"%s\",\n"
+			 "  obj_description(a.oid) as \"%s\"\n"
+			 "FROM pg_aggregate a\n",
+			 _("Name"), _("(all types)"),
+			 _("Data type"), _("Description") );
 
 	if (name)
 	{
-		strcat(buf, "  AND a.aggname ~ '^");
+		strcat(buf, "WHERE a.aggname ~ '^");
 		strncat(buf, name, REGEXP_CUTOFF);
 		strcat(buf, "'\n");
 	}
 
-	strcat(buf,
-		   "UNION\n"
-		   "SELECT a.aggname AS \"Name\", '(all types)' as \"Type\",\n"
-		   "  obj_description(a.oid) as \"Description\"\n"
-		   "FROM pg_aggregate a\n"
-		   "WHERE a.aggbasetype = 0\n"
-		);
-
-	if (name)
-	{
-		strcat(buf, "  AND a.aggname ~ '^");
-		strncat(buf, name, REGEXP_CUTOFF);
-		strcat(buf, "'\n");
-	}
-
-	strcat(buf, "ORDER BY \"Name\", \"Type\"");
+	strcat(buf, "ORDER BY 1, 2;");
 
 	res = PSQLexec(buf);
 	if (!res)
 		return false;
 
 	myopt.nullPrint = NULL;
-	myopt.title = "List of aggregates";
+	myopt.title = _("List of aggregate functions");
 
 	printQuery(res, &myopt, pset.queryFout);
 
@@ -102,22 +93,31 @@ describeFunctions(const char *name, bool verbose)
 	 * we skip in/out funcs by excluding functions that take some
 	 * arguments, but have no types defined for those arguments
 	 */
-	strcpy(buf,
-		   "SELECT format_type(p.prorettype, NULL) as \"Result\", p.proname as \"Function\",\n"
-		   "       oidvectortypes(p.proargtypes) as \"Arguments\"");
+	snprintf(buf, sizeof(buf),
+			 "SELECT format_type(p.prorettype, NULL) as \"%s\",\n"
+			 "  p.proname as \"%s\",\n"
+			 "  oidvectortypes(p.proargtypes) as \"%s\"",
+			 _("Result data type"), _("Name"),
+			 _("Argument data types") );
+
 	if (verbose)
-		strcat(buf, ",\n       u.usename as \"Owner\", l.lanname as \"Language\", p.prosrc as \"Source\",\n"
-			   "       obj_description(p.oid) as \"Description\"");
+		snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
+				 ",\n  u.usename as \"%s\",\n"
+				 "  l.lanname as \"%s\",\n"
+				 "  p.prosrc as \"%s\",\n"
+				 "  obj_description(p.oid) as \"%s\"",
+				 _("Owner"), _("Language"),
+				 _("Source code"), _("Description") );
 
 	if (!verbose)
 		strcat(buf,
 			   "\nFROM pg_proc p\n"
-			   "WHERE p.prorettype <> 0 and (pronargs = 0 or oidvectortypes(p.proargtypes) <> '')\n");
+			   "WHERE p.prorettype <> 0 AND (pronargs = 0 OR oidvectortypes(p.proargtypes) <> '')\n");
 	else
 		strcat(buf,
 			   "\nFROM pg_proc p,  pg_language l, pg_user u\n"
 			   "WHERE p.prolang = l.oid AND p.proowner = u.usesysid\n"
-			   "  AND p.prorettype <> 0 and (pronargs = 0 or oidvectortypes(p.proargtypes) <> '')\n");
+			   "  AND p.prorettype <> 0 AND (pronargs = 0 OR oidvectortypes(p.proargtypes) <> '')\n");
 
 	if (name)
 	{
@@ -125,14 +125,14 @@ describeFunctions(const char *name, bool verbose)
 		strncat(buf, name, REGEXP_CUTOFF);
 		strcat(buf, "'\n");
 	}
-	strcat(buf, "ORDER BY \"Function\", \"Result\", \"Arguments\"");
+	strcat(buf, "ORDER BY 2, 1, 3;");
 
 	res = PSQLexec(buf);
 	if (!res)
 		return false;
 
 	myopt.nullPrint = NULL;
-	myopt.title = "List of functions";
+	myopt.title = _("List of functions");
 
 	printQuery(res, &myopt, pset.queryFout);
 
@@ -153,19 +153,26 @@ describeTypes(const char *name, bool verbose)
 	PGresult   *res;
 	printQueryOpt myopt = pset.popt;
 
-	strcpy(buf, "SELECT format_type(t.oid, NULL) AS \"Type\"");
+	snprintf(buf, sizeof(buf),
+			 "SELECT format_type(t.oid, NULL) AS \"%s\",\n",
+			 _("Name") );
 	if (verbose)
-	{
-		strcat(buf, ",\n  t.typname AS \"Internal name\"");
-		strcat(buf, ",\n  (CASE WHEN t.typlen = -1 THEN 'var'::text ELSE t.typlen::text END) as \"Size\"");
-	}
-	strcat(buf, ",\n  obj_description(t.oid) as \"Description\"");
+		snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
+				 "  t.typname AS \"%s\",\n"
+				 "  CASE WHEN t.typlen = -1\n"
+				 "    THEN CAST('var' AS text)\n"
+				 "    ELSE CAST(t.typlen AS text)\n"
+				 "  END AS \"%s\",\n",
+				 _("Internal name"), _("Size") );
+	snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),	
+			 "  obj_description(t.oid) as \"%s\"\n",
+			 _("Description") );
 
 	/*
 	 * do not include array types (start with underscore), do not include
 	 * user relations (typrelid!=0)
 	 */
-	strcat(buf, "\nFROM pg_type t\nWHERE t.typrelid = 0 AND t.typname !~ '^_.*'\n");
+	strcat(buf, "FROM pg_type t\nWHERE t.typrelid = 0 AND t.typname !~ '^_.*'\n");
 
 	if (name)
 	{
@@ -174,16 +181,16 @@ describeTypes(const char *name, bool verbose)
 		strncat(buf, name, REGEXP_CUTOFF);
 		strcat(buf, "' OR t.typname ~ '^");
 		strncat(buf, name, REGEXP_CUTOFF);
-		strcat(buf, "')");
+		strcat(buf, "')\n");
 	}
-	strcat(buf, "\nORDER BY \"Type\";");
+	strcat(buf, "ORDER BY 1;");
 
 	res = PSQLexec(buf);
 	if (!res)
 		return false;
 
 	myopt.nullPrint = NULL;
-	myopt.title = "List of types";
+	myopt.title = _("List of data types");
 
 	printQuery(res, &myopt, pset.queryFout);
 
@@ -198,19 +205,20 @@ describeTypes(const char *name, bool verbose)
 bool
 describeOperators(const char *name)
 {
-	char		buf[1536 + 3 * REGEXP_CUTOFF];
+	char		buf[384 + REGEXP_CUTOFF];
 	PGresult   *res;
 	printQueryOpt myopt = pset.popt;
 
-	strcpy(buf,
-		   "SELECT o.oprname AS \"Op\",\n"
-		   "       format_type(o.oprleft, NULL) AS \"Left arg\",\n"
-		   "       format_type(o.oprright, NULL) AS \"Right arg\",\n"
-		   "       format_type(p.prorettype, NULL) AS \"Result\",\n"
-		   "       obj_description(p.oid) as \"Description\"\n"
-		   "FROM   pg_proc p, pg_operator o\n"
-		   "WHERE  RegprocToOid(o.oprcode) = p.oid AND\n"
-		   "       p.pronargs = 2\n");
+	snprintf(buf, sizeof(buf),
+			 "SELECT o.oprname AS \"%s\",\n"
+			 "  CASE WHEN o.oprkind='l' THEN NULL ELSE format_type(o.oprleft, NULL) END AS \"%s\",\n"
+			 "  CASE WHEN o.oprkind='r' THEN NULL ELSE format_type(o.oprright, NULL) END AS \"%s\",\n"
+			 "  format_type(p.prorettype, NULL) AS \"%s\",\n"
+			 "  obj_description(p.oid) as \"%s\"\n"
+			 "FROM pg_proc p, pg_operator o\n"
+			 "WHERE RegprocToOid(o.oprcode) = p.oid\n",
+			 _("Name"), _("Left arg type"), _("Right arg type"),
+			 _("Result type"), _("Description") );
 	if (name)
 	{
 		strcat(buf, "  AND o.oprname = '");
@@ -218,45 +226,14 @@ describeOperators(const char *name)
 		strcat(buf, "'\n");
 	}
 
-	strcat(buf, "\nUNION\n\n"
-		   "SELECT o.oprname as \"Op\",\n"
-		   "       ''::name AS \"Left arg\",\n"
-		   "       format_type(o.oprright, NULL) AS \"Right arg\",\n"
-		   "       format_type(o.oprresult, NULL) AS \"Result\",\n"
-		   "       obj_description(p.oid) as \"Description\"\n"
-		   "FROM   pg_operator o, pg_proc p\n"
-		   "WHERE  RegprocToOid(o.oprcode) = p.oid AND\n"
-		   "       o.oprkind = 'l'\n");
-	if (name)
-	{
-		strcat(buf, "AND o.oprname = '");
-		strncat(buf, name, REGEXP_CUTOFF);
-		strcat(buf, "'\n");
-	}
-
-	strcat(buf, "\nUNION\n\n"
-		   "SELECT o.oprname  as \"Op\",\n"
-		   "       format_type(o.oprleft, NULL) AS \"Left arg\",\n"
-		   "       ''::name AS \"Right arg\",\n"
-		   "       format_type(o.oprresult, NULL) AS \"Result\",\n"
-		   "       obj_description(p.oid) as \"Description\"\n"
-		   "FROM   pg_operator o, pg_proc p\n"
-		   "WHERE  RegprocToOid(o.oprcode) = p.oid AND\n"
-		   "       o.oprkind = 'r'\n");
-	if (name)
-	{
-		strcat(buf, "AND o.oprname = '");
-		strncat(buf, name, REGEXP_CUTOFF);
-		strcat(buf, "'\n");
-	}
-	strcat(buf, "\nORDER BY \"Op\", \"Left arg\", \"Right arg\", \"Result\"");
+	strcat(buf, "ORDER BY 1, 2, 3, 4;");
 
 	res = PSQLexec(buf);
 	if (!res)
 		return false;
 
 	myopt.nullPrint = NULL;
-	myopt.title = "List of operators";
+	myopt.title = _("List of operators");
 
 	printQuery(res, &myopt, pset.queryFout);
 
@@ -277,41 +254,29 @@ listAllDbs(bool desc)
 	char		buf[1024];
 	printQueryOpt myopt = pset.popt;
 
-	strcpy(buf,
-		   "SELECT pg_database.datname as \"Database\",\n"
-		   "       pg_user.usename as \"Owner\"");
+	snprintf(buf, sizeof(buf),
+			 "SELECT d.datname as \"%s\",\n"
+			 "       u.usename as \"%s\"",
+			 _("Name"), _("Owner"));
 #ifdef MULTIBYTE
-	strcat(buf,
-		   ",\n       pg_encoding_to_char(pg_database.encoding) as \"Encoding\"");
+	snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
+			 ",\n       pg_encoding_to_char(d.encoding) as \"%s\"",
+			 _("Encoding"));
 #endif
 	if (desc)
-		strcat(buf, ",\n       obj_description(pg_database.oid) as \"Description\"\n");
-	strcat(buf, "FROM pg_database, pg_user\n"
-		   "WHERE pg_database.datdba = pg_user.usesysid\n");
-
-	/* Also include databases that have no valid owner. */
-	strcat(buf, "\nUNION\n\n");
-
-	strcat(buf,
-		   "SELECT pg_database.datname as \"Database\",\n"
-		   "       NULL as \"Owner\"");
-#ifdef MULTIBYTE
+		snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
+				 ",\n       obj_description(d.oid) as \"%s\"",
+				 _("Description"));
 	strcat(buf,
-		   ",\n       pg_encoding_to_char(pg_database.encoding) as \"Encoding\"");
-#endif
-	if (desc)
-		strcat(buf, ",\n       obj_description(pg_database.oid) as \"Description\"\n");
-	strcat(buf, "FROM pg_database\n"
-	 "WHERE pg_database.datdba NOT IN (SELECT usesysid FROM pg_user)\n");
-
-	strcat(buf, "ORDER BY \"Database\"");
+		   "\nFROM pg_database d LEFT JOIN pg_user u ON d.datdba = u.usesysid\n"
+		   "ORDER BY 1;");
 
 	res = PSQLexec(buf);
 	if (!res)
 		return false;
 
 	myopt.nullPrint = NULL;
-	myopt.title = "List of databases";
+	myopt.title = _("List of databases");
 
 	printQuery(res, &myopt, pset.queryFout);
 
@@ -320,39 +285,40 @@ listAllDbs(bool desc)
 }
 
 
-/* List Tables Grant/Revoke Permissions
+/*
+ * List Tables Grant/Revoke Permissions
  * \z (now also \dp -- perhaps more mnemonic)
- *
  */
 bool
 permissionsList(const char *name)
 {
-	char		descbuf[256 + REGEXP_CUTOFF];
+	char		buf[256 + REGEXP_CUTOFF];
 	PGresult   *res;
 	printQueryOpt myopt = pset.popt;
 
-	descbuf[0] = '\0';
 	/* Currently, we ignore indexes since they have no meaningful rights */
-	strcat(descbuf, "SELECT relname as \"Relation\",\n"
-		   "       relacl as \"Access permissions\"\n"
-		   "FROM   pg_class\n"
-		   "WHERE  relkind in ('r', 'v', 'S') AND\n"
-		   "       relname !~ '^pg_'\n");
+	snprintf(buf, sizeof(buf),
+			 "SELECT relname as \"%s\",\n"
+			 "       relacl as \"%s\"\n"
+			 "FROM   pg_class\n"
+			 "WHERE  relkind in ('r', 'v', 'S') AND\n"
+			 "       relname NOT LIKE 'pg$_%%' ESCAPE '$'\n",
+			 _("Table"), _("Access privileges"));
 	if (name)
 	{
-		strcat(descbuf, "  AND relname ~ '^");
-		strncat(descbuf, name, REGEXP_CUTOFF);
-		strcat(descbuf, "'\n");
+		strcat(buf, "  AND relname ~ '^");
+		strncat(buf, name, REGEXP_CUTOFF);
+		strcat(buf, "'\n");
 	}
-	strcat(descbuf, "ORDER BY relname");
+	strcat(buf, "ORDER BY 1;");
 
-	res = PSQLexec(descbuf);
+	res = PSQLexec(buf);
 	if (!res)
 		return false;
 
 	myopt.nullPrint = NULL;
-	sprintf(descbuf, "Access permissions for database \"%s\"", PQdb(pset.db));
-	myopt.title = descbuf;
+	sprintf(buf, _("Access privileges for database \"%s\""), PQdb(pset.db));
+	myopt.title = buf;
 
 	printQuery(res, &myopt, pset.queryFout);
 
@@ -373,97 +339,71 @@ permissionsList(const char *name)
 bool
 objectDescription(const char *object)
 {
-	char		descbuf[2048 + 7 * REGEXP_CUTOFF];
+	char		descbuf[2048 + REGEXP_CUTOFF];
 	PGresult   *res;
 	printQueryOpt myopt = pset.popt;
 
-	descbuf[0] = '\0';
-
-	/* Aggregate descriptions */
-	strcat(descbuf, "SELECT DISTINCT a.aggname::text as \"Name\", 'aggregate'::text as \"Object\", d.description as \"Description\"\n"
-		   "FROM pg_aggregate a, pg_description d\n"
-		   "WHERE a.oid = d.objoid\n");
-	if (object)
-	{
-		strcat(descbuf, "  AND a.aggname ~ '^");
-		strncat(descbuf, object, REGEXP_CUTOFF);
-		strcat(descbuf, "'\n");
-	}
-
-	/* Function descriptions (except in/outs for datatypes) */
-	strcat(descbuf, "\nUNION ALL\n\n");
-	strcat(descbuf, "SELECT DISTINCT p.proname::text as \"Name\", 'function'::text as \"Object\", d.description as \"Description\"\n"
-		   "FROM pg_proc p, pg_description d\n"
-		   "WHERE p.oid = d.objoid AND (p.pronargs = 0 or oidvectortypes(p.proargtypes) != '')\n");
-	if (object)
-	{
-		strcat(descbuf, "  AND p.proname ~ '^");
-		strncat(descbuf, object, REGEXP_CUTOFF);
-		strcat(descbuf, "'\n");
-	}
-
-	/* Operator descriptions */
-	strcat(descbuf, "\nUNION ALL\n\n");
-	strcat(descbuf, "SELECT DISTINCT o.oprname::text as \"Name\", 'operator'::text as \"Object\", d.description as \"Description\"\n"
-		   "FROM pg_operator o, pg_description d\n"
-	/* must get comment via associated function */
-		   "WHERE RegprocToOid(o.oprcode) = d.objoid\n");
-	if (object)
-	{
-		strcat(descbuf, "  AND o.oprname = '");
-		strncat(descbuf, object, REGEXP_CUTOFF);
-		strcat(descbuf, "'\n");
-	}
-
-	/* Type description */
-	strcat(descbuf, "\nUNION ALL\n\n");
-	strcat(descbuf, "SELECT DISTINCT format_type(t.oid, NULL) as \"Name\", 'type'::text as \"Object\", d.description as \"Description\"\n"
-		   "FROM pg_type t, pg_description d\n"
-		   "WHERE t.oid = d.objoid\n");
-	if (object)
-	{
-		strcat(descbuf, "  AND t.typname ~ '^");
-		strncat(descbuf, object, REGEXP_CUTOFF);
-		strcat(descbuf, "'\n");
-	}
-
-	/* Relation (tables, views, indices, sequences) descriptions */
-	strcat(descbuf, "\nUNION ALL\n\n");
-	strcat(descbuf, "SELECT DISTINCT c.relname::text as \"Name\", 'relation'::text||'('||c.relkind||')' as \"Object\", d.description as \"Description\"\n"
-		   "FROM pg_class c, pg_description d\n"
-		   "WHERE c.oid = d.objoid\n");
-	if (object)
-	{
-		strcat(descbuf, "  AND c.relname ~ '^");
-		strncat(descbuf, object, REGEXP_CUTOFF);
-		strcat(descbuf, "'\n");
-	}
-
-	/* Rule description (ignore rules for views) */
-	strcat(descbuf, "\nUNION ALL\n\n");
-	strcat(descbuf, "SELECT DISTINCT r.rulename::text as \"Name\", 'rule'::text as \"Object\", d.description as \"Description\"\n"
-		   "FROM pg_rewrite r, pg_description d\n"
-		   "WHERE r.oid = d.objoid AND r.rulename !~ '^_RET'\n");
-	if (object)
-	{
-		strcat(descbuf, "  AND r.rulename ~ '^");
-		strncat(descbuf, object, REGEXP_CUTOFF);
-		strcat(descbuf, "'\n");
-	}
+	snprintf(descbuf, sizeof(descbuf),
+			 "SELECT DISTINCT tt.name AS \"%s\", tt.object AS \"%s\", d.description AS \"%s\"\n"
+			 "FROM (\n"
+
+			 /* Aggregate descriptions */
+			 "  SELECT a.oid as oid, CAST(a.aggname AS text) as name, CAST('%s' AS text) as object\n"
+			 "  FROM pg_aggregate a\n"
+
+			 /* Function descriptions (except in/outs for datatypes) */
+			 "UNION ALL\n"
+			 "  SELECT p.oid as oid, CAST(p.proname AS text) as name, CAST('%s' AS text) as object\n"
+			 "  FROM pg_proc p\n"
+			 "  WHERE p.pronargs = 0 or oidvectortypes(p.proargtypes) <> ''\n"
+
+			 /* Operator descriptions (must get comment via associated function) */
+			 "UNION ALL\n"
+			 "  SELECT RegprocToOid(o.oprcode) as oid, CAST(o.oprname AS text) as name, CAST('%s' AS text) as object\n"
+			 "  FROM pg_operator o\n"
+
+			 /* Type description */
+			 "UNION ALL\n"
+			 "  SELECT t.oid as oid, format_type(t.oid, NULL) as name, CAST('%s' AS text) as object\n"
+			 "  FROM pg_type t\n"
+
+			 /* Relation (tables, views, indexes, sequences) descriptions */
+			 "UNION ALL\n"
+			 "  SELECT c.oid as oid, CAST(c.relname AS text) as name,\n"
+			 "  CAST(\n"
+			 "    CASE c.relkind WHEN 'r' THEN '%s' WHEN 'v' THEN '%s' WHEN 'i' THEN '%s' WHEN 'S' THEN '%s' END"
+			 "  AS text) as object\n"
+			 "  FROM pg_class c\n"
+
+			 /* Rule description (ignore rules for views) */
+			 "UNION ALL\n"
+			 "  SELECT r.oid as oid, CAST(r.rulename AS text) as name, CAST('%s' AS text) as object\n"
+			 "  FROM pg_rewrite r\n"
+			 "  WHERE r.rulename !~ '^_RET'\n"
+
+			 /* Trigger description */
+			 "UNION ALL\n"
+			 "  SELECT t.oid as oid, CAST(t.tgname AS text) as name, CAST('%s' AS text) as object\n"
+			 "  FROM pg_trigger t\n"
+
+			 ") AS tt,\n"
+			 "pg_description d\n"
+			 "WHERE tt.oid = d.objoid\n",
+
+			 _("Name"), _("Object"), _("Description"),
+			 _("aggregate"), _("function"), _("operator"),
+			 _("data type"), _("table"), _("view"),
+			 _("index"), _("sequence"), _("rule"),
+			 _("trigger")
+		);
 
-	/* Trigger description */
-	strcat(descbuf, "\nUNION ALL\n\n");
-	strcat(descbuf, "SELECT DISTINCT t.tgname::text as \"Name\", 'trigger'::text as \"Object\", d.description as \"Description\"\n"
-		   "FROM pg_trigger t, pg_description d\n"
-		   "WHERE t.oid = d.objoid\n");
 	if (object)
 	{
-		strcat(descbuf, "  AND t.tgname ~ '^");
+		strcat(descbuf, "  AND tt.name ~ '^");
 		strncat(descbuf, object, REGEXP_CUTOFF);
 		strcat(descbuf, "'\n");
 	}
-
-	strcat(descbuf, "\nORDER BY \"Name\"");
+	strcat(descbuf, "ORDER BY 1;");
 
 
 	res = PSQLexec(descbuf);
@@ -471,7 +411,7 @@ objectDescription(const char *object)
 		return false;
 
 	myopt.nullPrint = NULL;
-	myopt.title = "Object descriptions";
+	myopt.title = _("Object descriptions");
 
 	printQuery(res, &myopt, pset.queryFout);
 
@@ -552,7 +492,7 @@ describeTableDetails(const char *name, bool desc)
 	if (PQntuples(res) == 0)
 	{
 		if (!QUIET())
-			fprintf(stderr, "Did not find any relation named \"%s\".\n", name);
+			fprintf(stderr, _("Did not find any relation named \"%s\".\n"), name);
 		PQclear(res);
 		return false;
 	}
@@ -566,20 +506,20 @@ describeTableDetails(const char *name, bool desc)
 	PQclear(res);
 
 
-	headers[0] = "Attribute";
-	headers[1] = "Type";
+	headers[0] = _("Column");
+	headers[1] = _("Type");
 	cols = 2;
 
 	if (tableinfo.relkind == 'r' || tableinfo.relkind == 'v')
 	{
 		cols++;
-		headers[cols - 1] = "Modifier";
+		headers[cols - 1] = _("Modifiers");
 	}
 
 	if (desc)
 	{
 		cols++;
-		headers[cols - 1] = "Description";
+		headers[cols - 1] = _("Description");
 	}
 
 	headers[cols] = NULL;
@@ -673,26 +613,26 @@ describeTableDetails(const char *name, bool desc)
 	}
 
 	/* Make title */
-	title = xmalloc(22 + strlen(name));
+	title = xmalloc(32 + NAMEDATALEN);
 	switch (tableinfo.relkind)
 	{
 		case 'r':
-			sprintf(title, "Table \"%s\"", name);
+			snprintf(title, 32 + NAMEDATALEN, _("Table \"%s\""), name);
 			break;
 		case 'v':
-			sprintf(title, "View \"%s\"", name);
+			snprintf(title, 32 + NAMEDATALEN, _("View \"%s\""), name);
 			break;
 		case 'S':
-			sprintf(title, "Sequence \"%s\"", name);
+			snprintf(title, 32 + NAMEDATALEN, _("Sequence \"%s\""), name);
 			break;
 		case 'i':
-			sprintf(title, "Index \"%s\"", name);
+			snprintf(title, 32 + NAMEDATALEN, _("Index \"%s\""), name);
 			break;
 		case 's':
-			sprintf(title, "Special relation \"%s\"", name);
+			snprintf(title, 32 + NAMEDATALEN, _("Special relation \"%s\""), name);
 			break;
 		default:
-			sprintf(title, "?%c? \"%s\"", tableinfo.relkind, name);
+			snprintf(title, 32 + NAMEDATALEN, _("?%c? \"%s\""), tableinfo.relkind, name);
 			break;
 	}
 
@@ -727,8 +667,9 @@ describeTableDetails(const char *name, bool desc)
 	else if (view_def)
 	{
 		footers = xmalloc(2 * sizeof(*footers));
-		footers[0] = xmalloc(20 + strlen(view_def));
-		sprintf(footers[0], "View definition: %s", view_def);
+		footers[0] = xmalloc(64 + strlen(view_def));
+		snprintf(footers[0], 64 + strlen(view_def),
+				 _("View definition: %s"), view_def);
 		footers[1] = NULL;
 	}
 
@@ -749,7 +690,7 @@ describeTableDetails(const char *name, bool desc)
 						trigger_count = 0;
 		int			count_footers = 0;
 
-		/* count indices */
+		/* count indexes */
 		if (!error && tableinfo.hasindex)
 		{
 			sprintf(buf, "SELECT c2.relname\n"
@@ -842,13 +783,15 @@ describeTableDetails(const char *name, bool desc)
 									constr_count + rule_count + trigger_count + 1)
 									* sizeof(*footers));
 
-		/* print indices */
+		/* print indexes */
 		for (i = 0; i < index_count; i++)
 		{
-			sprintf(buf, "%s %s",
-					index_count == 1 ? "Index:" : (i == 0 ? "Indices:" : "        "),
-					PQgetvalue(result1, i, 0)
-				);
+			char   *s = _("Indexes");
+
+			if (i == 0)
+				snprintf(buf, sizeof(buf), "%s: %s", s, PQgetvalue(result1, i, 0));
+			else
+				snprintf(buf, sizeof(buf), "%*s  %s", (int)strlen(s), "", PQgetvalue(result1, i, 0));
 			if (i < index_count - 1)
 				strcat(buf, ",");
 
@@ -858,10 +801,12 @@ describeTableDetails(const char *name, bool desc)
 		/* print primary keys */
 		for (i = 0; i < primary_count; i++)
 		{
-			sprintf(buf, "%s %s",
-					primary_count == 1 ? "Primary Key:" : (i == 0 ? "Primary Keys:" : "             "),
-					PQgetvalue(result5, i, 0)
-				);
+			char   *s = _("Primary key");
+
+			if (i == 0)
+				snprintf(buf, sizeof(buf), "%s: %s", s, PQgetvalue(result5, i, 0));
+			else
+				snprintf(buf, sizeof(buf), "%*s  %s", (int)strlen(s), "", PQgetvalue(result5, i, 0));
 			if (i < primary_count - 1)
 				strcat(buf, ",");
 
@@ -871,10 +816,12 @@ describeTableDetails(const char *name, bool desc)
 		/* print unique constraints */
 		for (i = 0; i < unique_count; i++)
 		{
-			sprintf(buf, "%s %s",
-					unique_count == 1 ? "Unique Key:" : (i == 0 ? "Unique Keys:" : "            "),
-					PQgetvalue(result6, i, 0)
-				);
+			char   *s = _("Unique keys");
+
+			if (i == 0)
+				snprintf(buf, sizeof(buf), "%s: %s", s, PQgetvalue(result6, i, 0));
+			else
+				snprintf(buf, sizeof(buf), "%*s  %s", (int)strlen(s), "", PQgetvalue(result6, i, 0));
 			if (i < unique_count - 1)
 				strcat(buf, ",");
 
@@ -884,21 +831,26 @@ describeTableDetails(const char *name, bool desc)
 		/* print constraints */
 		for (i = 0; i < constr_count; i++)
 		{
-			sprintf(buf, "%s \"%s\" %s",
-					constr_count == 1 ? "Constraint:" : (i == 0 ? "Constraints:" : "            "),
-					PQgetvalue(result2, i, 1),
-               PQgetvalue(result2, i, 0)
-				);
+			char   *s = _("Check constraints");
+
+			if (i == 0)
+				snprintf(buf, sizeof(buf), _("%s: \"%s\" %s"), s,
+						 PQgetvalue(result2, i, 1), PQgetvalue(result2, i, 0));
+			else
+				snprintf(buf, sizeof(buf), _("%*s  \"%s\" %s"), (int)strlen(s), "",
+						 PQgetvalue(result2, i, 1), PQgetvalue(result2, i, 0));
 			footers[count_footers++] = xstrdup(buf);
 		}
 
 		/* print rules */
 		for (i = 0; i < rule_count; i++)
 		{
-			sprintf(buf, "%s %s",
-			  rule_count == 1 ? "Rule:" : (i == 0 ? "Rules:" : "      "),
-					PQgetvalue(result3, i, 0)
-				);
+			char   *s = _("Rules");
+
+			if (i == 0)
+				snprintf(buf, sizeof(buf), "%s: %s", s, PQgetvalue(result3, i, 0));
+			else
+				snprintf(buf, sizeof(buf), "%*s  %s", (int)strlen(s), "", PQgetvalue(result3, i, 0));
 			if (i < rule_count - 1)
 				strcat(buf, ",");
 
@@ -908,10 +860,12 @@ describeTableDetails(const char *name, bool desc)
 		/* print triggers */
 		for (i = 0; i < trigger_count; i++)
 		{
-			sprintf(buf, "%s %s",
-					trigger_count == 1 ? "Trigger:" : (i == 0 ? "Triggers:" : "         "),
-					PQgetvalue(result4, i, 0)
-				);
+			char   *s = _("Triggers");
+
+			if (i == 0)
+				snprintf(buf, sizeof(buf), "%s: %s", s, PQgetvalue(result4, i, 0));
+			else
+				snprintf(buf, sizeof(buf), "%*s  %s", (int)strlen(s), "", PQgetvalue(result4, i, 0));
 			if (i < trigger_count - 1)
 				strcat(buf, ",");
 
@@ -955,8 +909,6 @@ describeTableDetails(const char *name, bool desc)
 
 
 /*
- * describeUsers()
- *
  * \du [user]
  *
  * Describes users, possibly based on a simplistic prefix search on the
@@ -968,86 +920,37 @@ describeUsers (const char *name)
 {
 	char		buf[384 + REGEXP_CUTOFF];
 	PGresult   *res;
-	printTableOpt myopt = pset.popt.topt;
-	int 		i;
-	char 	   *title;
-    const char *headers[4];
-	char	  **cells	= NULL;
-	unsigned int cols;
+	printQueryOpt myopt = pset.popt;
 	
-	/*
-	 * All we want to know is the user names and permissions
-	 * for the system.
-	 */
-
-	title = "List of Users";
-
-	cols = 0;
-	headers[cols++] = "User Name";
-	headers[cols++] = "User ID";
-	headers[cols++] = "Attributes";
-	headers[cols] = NULL;
-
-	strcpy(buf,
-		   "SELECT u.usename AS \"User Name\",\n"
-           "       u.usesysid AS \"User ID\",\n"
-           "       u.usesuper AS \"Super User\",\n"
-           "       u.usecreatedb AS \"Create DB\"\n"
-           "FROM pg_user u\n");
+	snprintf(buf, sizeof(buf),
+			 "SELECT u.usename AS \"%s\",\n"
+			 "  u.usesysid AS \"%s\",\n"
+			 "  CASE WHEN u.usesuper AND u.usecreatedb THEN CAST('%s' AS text)\n"
+			 "       WHEN u.usesuper THEN CAST('%s' AS text)\n"
+			 "       WHEN u.usecreatedb THEN CAST('%s' AS text)\n"
+			 "       ELSE CAST('' AS text)\n"
+			 "  END AS \"%s\"\n"
+			 "FROM pg_user u\n",
+			 _("User name"), _("User ID"),
+			 _("superuser, create database"),
+			 _("superuser"), _("create database"),
+			 _("Attributes") );
 	if (name)
 	{
 		strcat(buf, "WHERE u.usename ~ '^");
 		strncat(buf, name, REGEXP_CUTOFF);
 		strcat(buf, "'\n");
 	}
-	strcat(buf, "ORDER BY \"User Name\"\n");
+	strcat(buf, "ORDER BY 1;");
 
 	res = PSQLexec(buf);
 	if (!res)
 		return false;
 
-	cells = xmalloc((PQntuples(res) * cols + 1) * sizeof(*cells));
-	cells[PQntuples(res) * cols] = NULL;
-
-	for (i = 0; i < PQntuples(res); i++)
-	{
-		char createuser[2] = "";
-		char createdb[2]  = "";
-
-		/* Name */
-		cells[i * cols + 0] = PQgetvalue(res, i, 0);
-
-		/* ID */
-		cells[i * cols + 1] = PQgetvalue(res, i, 1);
-
-		/* Super */
-		strcpy(createuser, PQgetvalue(res, i, 2));
-
-		/* Create DB */
-		strcpy(createdb, PQgetvalue(res, i, 3));
-
-		cells[i * cols + 2] = xmalloc((strlen("create user, create DB") * sizeof(char)) + 1);
-		strcpy(cells[i * cols + 2], "");
-		
- 		if (strcmp(createuser, "t") == 0)
- 			strcat(cells[i * cols + 2], "create user");
-		
- 		if (strcmp(createdb, "t") == 0) {
-			if (strcmp(createuser, "t") == 0) 
-				strcat(cells[i * cols + 2], ", ");
- 			strcat(cells[i * cols + 2], "create DB");
-		}
-	}	   
-
-	printTable(title, headers,
-			   (const char **) cells,
-			   NULL,
-			   "lrl", &myopt, pset.queryFout);
+	myopt.nullPrint = NULL;
+	myopt.title = _("List of database users");
 
-	/* clean up */
-	for (i = 0; i < PQntuples(res); i++)
-		free(cells[i * cols + 2]);
-	free(cells);
+	printQuery(res, &myopt, pset.queryFout);
 
 	PQclear(res);
 	return true;
@@ -1061,7 +964,7 @@ describeUsers (const char *name)
  *
  * The infotype is an array of characters, specifying what info is desired:
  * t - tables
- * i - indices
+ * i - indexes
  * v - views
  * s - sequences
  * S - systems tables (~ '^pg_')
@@ -1075,7 +978,7 @@ bool
 listTables(const char *infotype, const char *name, bool desc)
 {
 	bool		showTables = strchr(infotype, 't') != NULL;
-	bool		showIndices = strchr(infotype, 'i') != NULL;
+	bool		showIndexes = strchr(infotype, 'i') != NULL;
 	bool		showViews = strchr(infotype, 'v') != NULL;
 	bool		showSeq = strchr(infotype, 's') != NULL;
 	bool		showSystem = strchr(infotype, 'S') != NULL;
@@ -1084,172 +987,52 @@ listTables(const char *infotype, const char *name, bool desc)
 	PGresult   *res;
 	printQueryOpt myopt = pset.popt;
 
-	if (showSystem && !(showSeq || showIndices || showViews || showTables))
+	if (showSystem && !(showSeq || showIndexes || showViews || showTables))
 		showTables = showViews = showSeq = true;
 
 
 	buf[0] = '\0';
 
-	/* tables */
-	if (showTables)
-	{
-		strcat(buf, "SELECT c.relname as \"Name\", 'table'::text as \"Type\", u.usename as \"Owner\"");
-		if (desc)
-			strcat(buf, ", obj_description(c.oid) as \"Description\"");
-		strcat(buf, "\nFROM pg_class c, pg_user u\n"
-			   "WHERE c.relowner = u.usesysid AND c.relkind = 'r'\n");
-		strcat(buf, showSystem ? "  AND c.relname ~ '^pg_'\n" : "  AND c.relname !~ '^pg_'\n");
-		if (name)
-		{
-			strcat(buf, "  AND c.relname ~ '^");
-			strncat(buf, name, REGEXP_CUTOFF);
-			strcat(buf, "'\n");
-		}
+	snprintf(buf, sizeof(buf),
+			 "SELECT c.relname as \"%s\",\n"
+			 "  CASE c.relkind WHEN 'r' THEN '%s' WHEN 'v' THEN '%s' WHEN 'i' THEN '%s' WHEN 'S' THEN '%s' WHEN 's' THEN '%s' END as \"%s\",\n"
+			 "  u.usename as \"%s\"",
+			 _("Name"), _("table"), _("view"), _("index"), _("sequence"),
+			 _("special"), _("Type"), _("Owner"));
 
-		strcat(buf, "UNION\n");
-		strcat(buf, "SELECT c.relname as \"Name\", 'table'::text as \"Type\", NULL as \"Owner\"");
-		if (desc)
-			strcat(buf, ", obj_description(c.oid) as \"Description\"");
-		strcat(buf, "\nFROM pg_class c\n"
-			   "WHERE c.relkind = 'r'\n"
-			   "  AND not exists (select 1 from pg_user where usesysid = c.relowner)\n");
-		strcat(buf, showSystem ? "  AND c.relname ~ '^pg_'\n" : "  AND c.relname !~ '^pg_'\n");
-		if (name)
-		{
-			strcat(buf, "  AND c.relname ~ '^");
-			strncat(buf, name, REGEXP_CUTOFF);
-			strcat(buf, "'\n");
-		}
-	}
-
-	/* views */
+	if (desc)
+		snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
+				 ",\n  obj_description(c.oid) as \"%s\"",
+				 _("Description"));
+	strcat(buf,
+		   "\nFROM pg_class c LEFT JOIN pg_user u ON c.relowner = u.usesysid\n"
+		   "WHERE c.relkind IN (");
+	if (showTables)
+		strcat(buf, "'r',");
 	if (showViews)
-	{
-		if (buf[0])
-			strcat(buf, "\nUNION\n\n");
-
-		strcat(buf, "SELECT c.relname as \"Name\", 'view'::text as \"Type\", u.usename as \"Owner\"");
-		if (desc)
-			strcat(buf, ", obj_description(c.oid) as \"Description\"");
-		strcat(buf, "\nFROM pg_class c, pg_user u\n"
-			   "WHERE c.relowner = u.usesysid AND c.relkind = 'v'\n");
-		strcat(buf, showSystem ? "  AND c.relname ~ '^pg_'\n" : "  AND c.relname !~ '^pg_'\n");
-		if (name)
-		{
-			strcat(buf, "  AND c.relname ~ '^");
-			strncat(buf, name, REGEXP_CUTOFF);
-			strcat(buf, "'\n");
-		}
-
-		strcat(buf, "UNION\n");
-		strcat(buf, "SELECT c.relname as \"Name\", 'view'::text as \"Type\", NULL as \"Owner\"");
-		if (desc)
-			strcat(buf, ", obj_description(c.oid) as \"Description\"");
-		strcat(buf, "\nFROM pg_class c\n"
-			   "WHERE c.relkind = 'v'\n"
-			   "  AND not exists (select 1 from pg_user where usesysid = c.relowner)\n");
-		strcat(buf, showSystem ? "  AND c.relname ~ '^pg_'\n" : "  AND c.relname !~ '^pg_'\n");
-		if (name)
-		{
-			strcat(buf, "  AND c.relname ~ '^");
-			strncat(buf, name, REGEXP_CUTOFF);
-			strcat(buf, "'\n");
-		}
-	}
-
-	/* indices, sequences */
-	if (showIndices || showSeq)
-	{
-		if (buf[0])
-			strcat(buf, "\nUNION\n\n");
-
-		strcat(buf,
-			   "SELECT c.relname as \"Name\",\n"
-			   "  (CASE WHEN relkind = 'S' THEN 'sequence'::text ELSE 'index'::text END) as \"Type\",\n"
-			   "  u.usename as \"Owner\""
-			);
-		if (desc)
-			strcat(buf, ", obj_description(c.oid) as \"Description\"");
-		strcat(buf, "\nFROM pg_class c, pg_user u\n"
-			   "WHERE c.relowner = u.usesysid AND relkind in (");
-		if (showIndices && showSeq)
-			strcat(buf, "'i', 'S'");
-		else if (showIndices)
-			strcat(buf, "'i'");
-		else
-			strcat(buf, "'S'");
-		strcat(buf, ")\n");
-
-		strcat(buf, showSystem ? "  AND c.relname ~ '^pg_'\n" : "  AND c.relname !~ '^pg_'\n");
-		if (name)
-		{
-			strcat(buf, "  AND c.relname ~ '^");
-			strncat(buf, name, REGEXP_CUTOFF);
-			strcat(buf, "'\n");
-		}
-
-		strcat(buf, "UNION\n");
-		strcat(buf,
-			   "SELECT c.relname as \"Name\",\n"
-			   "  (CASE WHEN relkind = 'S' THEN 'sequence'::text ELSE 'index'::text END) as \"Type\",\n"
-			   "  NULL as \"Owner\""
-			);
-		if (desc)
-			strcat(buf, ", obj_description(c.oid) as \"Description\"");
-		strcat(buf, "\nFROM pg_class c\n"
-			   "WHERE not exists (select 1 from pg_user where usesysid = c.relowner) AND relkind in (");
-		if (showIndices && showSeq)
-			strcat(buf, "'i', 'S'");
-		else if (showIndices)
-			strcat(buf, "'i'");
-		else
-			strcat(buf, "'S'");
-		strcat(buf, ")\n");
-
-		strcat(buf, showSystem ? "  AND c.relname ~ '^pg_'\n" : "  AND c.relname !~ '^pg_'\n");
-		if (name)
-		{
-			strcat(buf, "  AND c.relname ~ '^");
-			strncat(buf, name, REGEXP_CUTOFF);
-			strcat(buf, "'\n");
-		}
-	}
-
-	/* special system tables */
+		strcat(buf, "'v',");
+	if (showIndexes)
+		strcat(buf, "'i',");
+	if (showSeq)
+		strcat(buf, "'S',");
 	if (showSystem && showTables)
-	{
-		if (buf[0])
-			strcat(buf, "\nUNION\n\n");
+		strcat(buf, "'s',");
+	strcat(buf, "''");				/* dummy */
+	strcat(buf, ")\n");
 
-		strcat(buf, "SELECT c.relname as \"Name\", 'special'::text as \"Type\", u.usename as \"Owner\"");
-		if (desc)
-			strcat(buf, ", obj_description(c.oid) as \"Description\"");
-		strcat(buf, "\nFROM pg_class c, pg_user u\n"
-			   "WHERE c.relowner = u.usesysid AND c.relkind = 's'\n");
-		if (name)
-		{
-			strcat(buf, "  AND c.relname ~ '^");
-			strncat(buf, name, REGEXP_CUTOFF);
-			strcat(buf, "'\n");
-		}
+	if (showSystem)
+		strcat(buf, "  AND c.relname ~ '^pg_'\n");
+	else
+		strcat(buf, "  AND c.relname !~ '^pg_'\n");
 
-		strcat(buf, "UNION\n");
-		strcat(buf, "SELECT c.relname as \"Name\", 'special'::text as \"Type\", NULL as \"Owner\"");
-		if (desc)
-			strcat(buf, ", obj_description(c.oid) as \"Description\"");
-		strcat(buf, "\nFROM pg_class c\n"
-			   "WHERE c.relkind = 's'\n"
-			   "  AND not exists (select 1 from pg_user where usesysid = c.relowner)");
-		if (name)
-		{
-			strcat(buf, "  AND c.relname ~ '^");
-			strncat(buf, name, REGEXP_CUTOFF);
-			strcat(buf, "'\n");
-		}
+	if (name)
+	{
+		strcat(buf, "  AND c.relname ~ '^");
+		strncat(buf, name, REGEXP_CUTOFF);
+		strcat(buf, "'\n");
 	}
 
-	strcat(buf, "\nORDER BY \"Name\"");
-
+	strcat(buf, "ORDER BY 1;");
 
 	res = PSQLexec(buf);
 	if (!res)
@@ -1258,14 +1041,14 @@ listTables(const char *infotype, const char *name, bool desc)
 	if (PQntuples(res) == 0 && !QUIET())
 	{
 		if (name)
-			fprintf(pset.queryFout, "No matching relations found.\n");
+			fprintf(pset.queryFout, _("No matching relations found.\n"));
 		else
-			fprintf(pset.queryFout, "No relations found.\n");
+			fprintf(pset.queryFout, _("No relations found.\n"));
 	}
 	else
 	{
 		myopt.nullPrint = NULL;
-		myopt.title = "List of relations";
+		myopt.title = _("List of relations");
 
 		printQuery(res, &myopt, pset.queryFout);
 	}
diff --git a/src/bin/psql/nls.mk b/src/bin/psql/nls.mk
index 545a6ecca0f..9d183d011ff 100644
--- a/src/bin/psql/nls.mk
+++ b/src/bin/psql/nls.mk
@@ -1,7 +1,6 @@
-# $Header: /cvsroot/pgsql/src/bin/psql/nls.mk,v 1.3 2001/06/20 18:25:26 petere Exp $
+# $Header: /cvsroot/pgsql/src/bin/psql/nls.mk,v 1.4 2001/06/30 17:26:12 petere Exp $
 CATALOG_NAME	:= psql
 AVAIL_LANGUAGES	:= de fr sv
 GETTEXT_FILES	:= command.c common.c copy.c help.c input.c large_obj.c \
-                   mainloop.c print.c startup.c
-                   # describe.c needs work
+                   mainloop.c print.c startup.c describe.c
 GETTEXT_TRIGGERS:= _ psql_error simple_prompt
diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c
index 49e239a4fe1..bd0dddcb365 100644
--- a/src/bin/psql/startup.c
+++ b/src/bin/psql/startup.c
@@ -3,7 +3,7 @@
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/startup.c,v 1.50 2001/06/02 18:25:18 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/startup.c,v 1.51 2001/06/30 17:26:12 petere Exp $
  */
 #include "postgres_fe.h"
 
@@ -174,7 +174,7 @@ main(int argc, char *argv[])
 		 * by the name on the command line.
 		 */
 		if (strcmp(options.username, "\001") == 0)
-			username = simple_prompt("Username: ", 100, true);
+			username = simple_prompt("User name: ", 100, true);
 		else
 			username = strdup(options.username);
 	}
-- 
GitLab