NLS for the psql \d family of commands. (E.g., the column headers will
authorPeter Eisentraut <peter_e@gmx.net>
Sat, 30 Jun 2001 17:26:12 +0000 (17:26 +0000)
committerPeter Eisentraut <peter_e@gmx.net>
Sat, 30 Jun 2001 17:26:12 +0000 (17:26 +0000)
have localized strings.)  Also, modernize the system catalog queries where
appropriate, e.g., with outer joins.

src/bin/psql/describe.c
src/bin/psql/nls.mk
src/bin/psql/startup.c

index f9b599f941b23eeba94065dd5672ad077564f527..9e88a8f7c570c614855e3a2fbc10e3a8089c62b1 100644 (file)
@@ -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);
    }
index 545a6ecca0f8ced05846c9420a22446e5363012a..9d183d011ff8653389584469c739617315fb7e56 100644 (file)
@@ -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
index 49e239a4fe19cee1f081ee553fadea3f2af94b26..bd0dddcb3651065a68aa46645f86424747f2e89f 100644 (file)
@@ -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);
    }