Improve the method of localizing column names and other fixed strings in

psql's \d commands and other uses of printQuery().  Previously we would pass
these strings through gettext() and then send them to the server as literals
in the SQL query.  But the code was not set up to handle doubling of quotes in
the strings, causing failure if a translation attempted to use the wrong kind
of quote marks, as indeed is now the case for (at least) the French
translation of \dFp.  Another hazard was that gettext() would translate to
whatever encoding was implied by the client's LC_CTYPE setting, which might be
different from the client_encoding setting, which would probably cause the
server to reject the query as mis-encoded.  The new arrangement is to send the
untranslated ASCII strings to the server, and do the translations inside
printQuery() after the query results come back.  Per report from Guillaume
Lelarge and subsequent discussion.
This commit is contained in:
Tom Lane 2007-12-12 21:41:47 +00:00
parent 286049dbe4
commit df4271fedd
7 changed files with 241 additions and 125 deletions

View File

@ -3,7 +3,7 @@
* *
* Copyright (c) 2000-2007, PostgreSQL Global Development Group * Copyright (c) 2000-2007, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.162 2007/11/15 21:14:42 momjian Exp $ * $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.163 2007/12/12 21:41:47 tgl Exp $
*/ */
#include "postgres_fe.h" #include "postgres_fe.h"
#include "describe.h" #include "describe.h"
@ -85,8 +85,11 @@ describeAggregates(const char *pattern, bool verbose)
"FROM pg_catalog.pg_proc p\n" "FROM pg_catalog.pg_proc p\n"
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n" " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n"
"WHERE p.proisagg\n", "WHERE p.proisagg\n",
_("Schema"), _("Name"), _("Result data type"), gettext_noop("Schema"),
_("Argument data types"), _("Description")); gettext_noop("Name"),
gettext_noop("Result data type"),
gettext_noop("Argument data types"),
gettext_noop("Description"));
processSQLNamePattern(pset.db, &buf, pattern, true, false, processSQLNamePattern(pset.db, &buf, pattern, true, false,
"n.nspname", "p.proname", NULL, "n.nspname", "p.proname", NULL,
@ -101,6 +104,7 @@ describeAggregates(const char *pattern, bool verbose)
myopt.nullPrint = NULL; myopt.nullPrint = NULL;
myopt.title = _("List of aggregate functions"); myopt.title = _("List of aggregate functions");
myopt.trans_headers = true;
printQuery(res, &myopt, pset.queryFout, pset.logfile); printQuery(res, &myopt, pset.queryFout, pset.logfile);
@ -131,13 +135,16 @@ describeTablespaces(const char *pattern, bool verbose)
"SELECT spcname AS \"%s\",\n" "SELECT spcname AS \"%s\",\n"
" pg_catalog.pg_get_userbyid(spcowner) AS \"%s\",\n" " pg_catalog.pg_get_userbyid(spcowner) AS \"%s\",\n"
" spclocation AS \"%s\"", " spclocation AS \"%s\"",
_("Name"), _("Owner"), _("Location")); gettext_noop("Name"),
gettext_noop("Owner"),
gettext_noop("Location"));
if (verbose) if (verbose)
appendPQExpBuffer(&buf, appendPQExpBuffer(&buf,
",\n spcacl as \"%s\"" ",\n spcacl AS \"%s\""
",\n pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"", ",\n pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"",
_("Access privileges"), _("Description")); gettext_noop("Access privileges"),
gettext_noop("Description"));
appendPQExpBuffer(&buf, appendPQExpBuffer(&buf,
"\nFROM pg_catalog.pg_tablespace\n"); "\nFROM pg_catalog.pg_tablespace\n");
@ -155,6 +162,7 @@ describeTablespaces(const char *pattern, bool verbose)
myopt.nullPrint = NULL; myopt.nullPrint = NULL;
myopt.title = _("List of tablespaces"); myopt.title = _("List of tablespaces");
myopt.trans_headers = true;
printQuery(res, &myopt, pset.queryFout, pset.logfile); printQuery(res, &myopt, pset.queryFout, pset.logfile);
@ -208,8 +216,10 @@ describeFunctions(const char *pattern, bool verbose)
" pg_catalog.generate_series(0, pg_catalog.array_upper(p.proargtypes, 1)) AS s(i)\n" " pg_catalog.generate_series(0, pg_catalog.array_upper(p.proargtypes, 1)) AS s(i)\n"
" ), ', ')\n" " ), ', ')\n"
" END AS \"%s\"", " END AS \"%s\"",
_("Schema"), _("Name"), _("Result data type"), gettext_noop("Schema"),
_("Argument data types")); gettext_noop("Name"),
gettext_noop("Result data type"),
gettext_noop("Argument data types"));
if (verbose) if (verbose)
appendPQExpBuffer(&buf, appendPQExpBuffer(&buf,
@ -222,8 +232,11 @@ describeFunctions(const char *pattern, bool verbose)
" l.lanname as \"%s\",\n" " l.lanname as \"%s\",\n"
" p.prosrc as \"%s\",\n" " p.prosrc as \"%s\",\n"
" pg_catalog.obj_description(p.oid, 'pg_proc') as \"%s\"", " pg_catalog.obj_description(p.oid, 'pg_proc') as \"%s\"",
_("Volatility"), _("Owner"), _("Language"), gettext_noop("Volatility"),
_("Source code"), _("Description")); gettext_noop("Owner"),
gettext_noop("Language"),
gettext_noop("Source code"),
gettext_noop("Description"));
if (!verbose) if (!verbose)
appendPQExpBuffer(&buf, appendPQExpBuffer(&buf,
@ -258,6 +271,7 @@ describeFunctions(const char *pattern, bool verbose)
myopt.nullPrint = NULL; myopt.nullPrint = NULL;
myopt.title = _("List of functions"); myopt.title = _("List of functions");
myopt.trans_headers = true;
printQuery(res, &myopt, pset.queryFout, pset.logfile); printQuery(res, &myopt, pset.queryFout, pset.logfile);
@ -283,7 +297,8 @@ describeTypes(const char *pattern, bool verbose)
printfPQExpBuffer(&buf, printfPQExpBuffer(&buf,
"SELECT n.nspname as \"%s\",\n" "SELECT n.nspname as \"%s\",\n"
" pg_catalog.format_type(t.oid, NULL) AS \"%s\",\n", " pg_catalog.format_type(t.oid, NULL) AS \"%s\",\n",
_("Schema"), _("Name")); gettext_noop("Schema"),
gettext_noop("Name"));
if (verbose) if (verbose)
appendPQExpBuffer(&buf, appendPQExpBuffer(&buf,
" t.typname AS \"%s\",\n" " t.typname AS \"%s\",\n"
@ -293,10 +308,11 @@ describeTypes(const char *pattern, bool verbose)
" THEN CAST('var' AS pg_catalog.text)\n" " THEN CAST('var' AS pg_catalog.text)\n"
" ELSE CAST(t.typlen AS pg_catalog.text)\n" " ELSE CAST(t.typlen AS pg_catalog.text)\n"
" END AS \"%s\",\n", " END AS \"%s\",\n",
_("Internal name"), _("Size")); gettext_noop("Internal name"),
gettext_noop("Size"));
appendPQExpBuffer(&buf, appendPQExpBuffer(&buf,
" pg_catalog.obj_description(t.oid, 'pg_type') as \"%s\"\n", " pg_catalog.obj_description(t.oid, 'pg_type') as \"%s\"\n",
_("Description")); gettext_noop("Description"));
appendPQExpBuffer(&buf, "FROM pg_catalog.pg_type t\n" appendPQExpBuffer(&buf, "FROM pg_catalog.pg_type t\n"
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n"); " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n");
@ -325,6 +341,7 @@ describeTypes(const char *pattern, bool verbose)
myopt.nullPrint = NULL; myopt.nullPrint = NULL;
myopt.title = _("List of data types"); myopt.title = _("List of data types");
myopt.trans_headers = true;
printQuery(res, &myopt, pset.queryFout, pset.logfile); printQuery(res, &myopt, pset.queryFout, pset.logfile);
@ -354,9 +371,12 @@ describeOperators(const char *pattern)
" pg_catalog.obj_description(o.oprcode, 'pg_proc')) AS \"%s\"\n" " pg_catalog.obj_description(o.oprcode, 'pg_proc')) AS \"%s\"\n"
"FROM pg_catalog.pg_operator o\n" "FROM pg_catalog.pg_operator o\n"
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = o.oprnamespace\n", " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = o.oprnamespace\n",
_("Schema"), _("Name"), gettext_noop("Schema"),
_("Left arg type"), _("Right arg type"), gettext_noop("Name"),
_("Result type"), _("Description")); gettext_noop("Left arg type"),
gettext_noop("Right arg type"),
gettext_noop("Result type"),
gettext_noop("Description"));
processSQLNamePattern(pset.db, &buf, pattern, false, true, processSQLNamePattern(pset.db, &buf, pattern, false, true,
"n.nspname", "o.oprname", NULL, "n.nspname", "o.oprname", NULL,
@ -371,6 +391,7 @@ describeOperators(const char *pattern)
myopt.nullPrint = NULL; myopt.nullPrint = NULL;
myopt.title = _("List of operators"); myopt.title = _("List of operators");
myopt.trans_headers = true;
printQuery(res, &myopt, pset.queryFout, pset.logfile); printQuery(res, &myopt, pset.queryFout, pset.logfile);
@ -395,19 +416,19 @@ listAllDbs(bool verbose)
printfPQExpBuffer(&buf, printfPQExpBuffer(&buf,
"SELECT d.datname as \"%s\",\n" "SELECT d.datname as \"%s\",\n"
" r.rolname as \"%s\"", " r.rolname as \"%s\",\n"
_("Name"), _("Owner")); " pg_catalog.pg_encoding_to_char(d.encoding) as \"%s\"",
appendPQExpBuffer(&buf, gettext_noop("Name"),
",\n pg_catalog.pg_encoding_to_char(d.encoding) as \"%s\"", gettext_noop("Owner"),
_("Encoding")); gettext_noop("Encoding"));
if (verbose) if (verbose)
{ {
appendPQExpBuffer(&buf, appendPQExpBuffer(&buf,
",\n t.spcname as \"%s\"", ",\n t.spcname as \"%s\"",
_("Tablespace")); gettext_noop("Tablespace"));
appendPQExpBuffer(&buf, appendPQExpBuffer(&buf,
",\n pg_catalog.shobj_description(d.oid, 'pg_database') as \"%s\"", ",\n pg_catalog.shobj_description(d.oid, 'pg_database') as \"%s\"",
_("Description")); gettext_noop("Description"));
} }
appendPQExpBuffer(&buf, appendPQExpBuffer(&buf,
"\nFROM pg_catalog.pg_database d" "\nFROM pg_catalog.pg_database d"
@ -423,6 +444,7 @@ listAllDbs(bool verbose)
myopt.nullPrint = NULL; myopt.nullPrint = NULL;
myopt.title = _("List of databases"); myopt.title = _("List of databases");
myopt.trans_headers = true;
printQuery(res, &myopt, pset.queryFout, pset.logfile); printQuery(res, &myopt, pset.queryFout, pset.logfile);
@ -441,6 +463,7 @@ permissionsList(const char *pattern)
PQExpBufferData buf; PQExpBufferData buf;
PGresult *res; PGresult *res;
printQueryOpt myopt = pset.popt; printQueryOpt myopt = pset.popt;
static const bool trans_columns[] = {false, false, true, false};
initPQExpBuffer(&buf); initPQExpBuffer(&buf);
@ -455,7 +478,11 @@ permissionsList(const char *pattern)
"FROM pg_catalog.pg_class c\n" "FROM pg_catalog.pg_class c\n"
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n" " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n"
"WHERE c.relkind IN ('r', 'v', 'S')\n", "WHERE c.relkind IN ('r', 'v', 'S')\n",
_("Schema"), _("Name"), _("table"), _("view"), _("sequence"), _("Type"), _("Access privileges")); gettext_noop("Schema"),
gettext_noop("Name"),
gettext_noop("table"), gettext_noop("view"), gettext_noop("sequence"),
gettext_noop("Type"),
gettext_noop("Access privileges"));
/* /*
* Unless a schema pattern is specified, we suppress system and temp * Unless a schema pattern is specified, we suppress system and temp
@ -477,8 +504,11 @@ permissionsList(const char *pattern)
} }
myopt.nullPrint = NULL; myopt.nullPrint = NULL;
printfPQExpBuffer(&buf, _("Access privileges for database \"%s\""), PQdb(pset.db)); printfPQExpBuffer(&buf, _("Access privileges for database \"%s\""),
PQdb(pset.db));
myopt.title = buf.data; myopt.title = buf.data;
myopt.trans_headers = true;
myopt.trans_columns = trans_columns;
printQuery(res, &myopt, pset.queryFout, pset.logfile); printQuery(res, &myopt, pset.queryFout, pset.logfile);
@ -503,13 +533,17 @@ objectDescription(const char *pattern)
PQExpBufferData buf; PQExpBufferData buf;
PGresult *res; PGresult *res;
printQueryOpt myopt = pset.popt; printQueryOpt myopt = pset.popt;
static const bool trans_columns[] = {false, false, true, false};
initPQExpBuffer(&buf); initPQExpBuffer(&buf);
appendPQExpBuffer(&buf, appendPQExpBuffer(&buf,
"SELECT DISTINCT tt.nspname AS \"%s\", tt.name AS \"%s\", tt.object AS \"%s\", d.description AS \"%s\"\n" "SELECT DISTINCT tt.nspname AS \"%s\", tt.name AS \"%s\", tt.object AS \"%s\", d.description AS \"%s\"\n"
"FROM (\n", "FROM (\n",
_("Schema"), _("Name"), _("Object"), _("Description")); gettext_noop("Schema"),
gettext_noop("Name"),
gettext_noop("Object"),
gettext_noop("Description"));
/* Aggregate descriptions */ /* Aggregate descriptions */
appendPQExpBuffer(&buf, appendPQExpBuffer(&buf,
@ -520,7 +554,7 @@ objectDescription(const char *pattern)
" FROM pg_catalog.pg_proc p\n" " FROM pg_catalog.pg_proc p\n"
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n" " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n"
" WHERE p.proisagg\n", " WHERE p.proisagg\n",
_("aggregate")); gettext_noop("aggregate"));
processSQLNamePattern(pset.db, &buf, pattern, true, false, processSQLNamePattern(pset.db, &buf, pattern, true, false,
"n.nspname", "p.proname", NULL, "n.nspname", "p.proname", NULL,
"pg_catalog.pg_function_is_visible(p.oid)"); "pg_catalog.pg_function_is_visible(p.oid)");
@ -539,7 +573,7 @@ objectDescription(const char *pattern)
" AND (p.proargtypes[0] IS NULL\n" " AND (p.proargtypes[0] IS NULL\n"
" OR p.proargtypes[0] <> 'pg_catalog.cstring'::pg_catalog.regtype)\n" " OR p.proargtypes[0] <> 'pg_catalog.cstring'::pg_catalog.regtype)\n"
" AND NOT p.proisagg\n", " AND NOT p.proisagg\n",
_("function")); gettext_noop("function"));
processSQLNamePattern(pset.db, &buf, pattern, true, false, processSQLNamePattern(pset.db, &buf, pattern, true, false,
"n.nspname", "p.proname", NULL, "n.nspname", "p.proname", NULL,
"pg_catalog.pg_function_is_visible(p.oid)"); "pg_catalog.pg_function_is_visible(p.oid)");
@ -553,7 +587,7 @@ objectDescription(const char *pattern)
" CAST('%s' AS pg_catalog.text) as object\n" " CAST('%s' AS pg_catalog.text) as object\n"
" FROM pg_catalog.pg_operator o\n" " FROM pg_catalog.pg_operator o\n"
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = o.oprnamespace\n", " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = o.oprnamespace\n",
_("operator")); gettext_noop("operator"));
processSQLNamePattern(pset.db, &buf, pattern, false, false, processSQLNamePattern(pset.db, &buf, pattern, false, false,
"n.nspname", "o.oprname", NULL, "n.nspname", "o.oprname", NULL,
"pg_catalog.pg_operator_is_visible(o.oid)"); "pg_catalog.pg_operator_is_visible(o.oid)");
@ -567,7 +601,7 @@ objectDescription(const char *pattern)
" CAST('%s' AS pg_catalog.text) as object\n" " CAST('%s' AS pg_catalog.text) as object\n"
" FROM pg_catalog.pg_type t\n" " FROM pg_catalog.pg_type t\n"
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n", " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n",
_("data type")); gettext_noop("data type"));
processSQLNamePattern(pset.db, &buf, pattern, false, false, processSQLNamePattern(pset.db, &buf, pattern, false, false,
"n.nspname", "pg_catalog.format_type(t.oid, NULL)", "n.nspname", "pg_catalog.format_type(t.oid, NULL)",
NULL, NULL,
@ -585,7 +619,10 @@ objectDescription(const char *pattern)
" FROM pg_catalog.pg_class c\n" " FROM pg_catalog.pg_class c\n"
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n" " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n"
" WHERE c.relkind IN ('r', 'v', 'i', 'S')\n", " WHERE c.relkind IN ('r', 'v', 'i', 'S')\n",
_("table"), _("view"), _("index"), _("sequence")); gettext_noop("table"),
gettext_noop("view"),
gettext_noop("index"),
gettext_noop("sequence"));
processSQLNamePattern(pset.db, &buf, pattern, true, false, processSQLNamePattern(pset.db, &buf, pattern, true, false,
"n.nspname", "c.relname", NULL, "n.nspname", "c.relname", NULL,
"pg_catalog.pg_table_is_visible(c.oid)"); "pg_catalog.pg_table_is_visible(c.oid)");
@ -601,7 +638,7 @@ objectDescription(const char *pattern)
" JOIN pg_catalog.pg_class c ON c.oid = r.ev_class\n" " JOIN pg_catalog.pg_class c ON c.oid = r.ev_class\n"
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n" " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n"
" WHERE r.rulename != '_RETURN'\n", " WHERE r.rulename != '_RETURN'\n",
_("rule")); gettext_noop("rule"));
/* XXX not sure what to do about visibility rule here? */ /* XXX not sure what to do about visibility rule here? */
processSQLNamePattern(pset.db, &buf, pattern, true, false, processSQLNamePattern(pset.db, &buf, pattern, true, false,
"n.nspname", "r.rulename", NULL, "n.nspname", "r.rulename", NULL,
@ -617,7 +654,7 @@ objectDescription(const char *pattern)
" FROM pg_catalog.pg_trigger t\n" " FROM pg_catalog.pg_trigger t\n"
" JOIN pg_catalog.pg_class c ON c.oid = t.tgrelid\n" " JOIN pg_catalog.pg_class c ON c.oid = t.tgrelid\n"
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n", " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n",
_("trigger")); gettext_noop("trigger"));
/* XXX not sure what to do about visibility rule here? */ /* XXX not sure what to do about visibility rule here? */
processSQLNamePattern(pset.db, &buf, pattern, false, false, processSQLNamePattern(pset.db, &buf, pattern, false, false,
"n.nspname", "t.tgname", NULL, "n.nspname", "t.tgname", NULL,
@ -636,6 +673,8 @@ objectDescription(const char *pattern)
myopt.nullPrint = NULL; myopt.nullPrint = NULL;
myopt.title = _("Object descriptions"); myopt.title = _("Object descriptions");
myopt.trans_headers = true;
myopt.trans_columns = trans_columns;
printQuery(res, &myopt, pset.queryFout, pset.logfile); printQuery(res, &myopt, pset.queryFout, pset.logfile);
@ -1572,6 +1611,7 @@ describeRoles(const char *pattern, bool verbose)
PQExpBufferData buf; PQExpBufferData buf;
PGresult *res; PGresult *res;
printQueryOpt myopt = pset.popt; printQueryOpt myopt = pset.popt;
static const bool trans_columns[] = {false, true, true, true, true, false, false};
initPQExpBuffer(&buf); initPQExpBuffer(&buf);
@ -1584,16 +1624,20 @@ describeRoles(const char *pattern, bool verbose)
" ELSE CAST(r.rolconnlimit AS pg_catalog.text)\n" " ELSE CAST(r.rolconnlimit AS pg_catalog.text)\n"
" END AS \"%s\", \n" " END AS \"%s\", \n"
" ARRAY(SELECT b.rolname FROM pg_catalog.pg_auth_members m JOIN pg_catalog.pg_roles b ON (m.roleid = b.oid) WHERE m.member = r.oid) as \"%s\"", " ARRAY(SELECT b.rolname FROM pg_catalog.pg_auth_members m JOIN pg_catalog.pg_roles b ON (m.roleid = b.oid) WHERE m.member = r.oid) as \"%s\"",
_("Role name"), gettext_noop("Role name"),
_("yes"), _("no"), _("Superuser"), gettext_noop("yes"), gettext_noop("no"),
_("yes"), _("no"), _("Create role"), gettext_noop("Superuser"),
_("yes"), _("no"), _("Create DB"), gettext_noop("yes"), gettext_noop("no"),
_("no limit"), _("Connections"), gettext_noop("Create role"),
_("Member of")); gettext_noop("yes"), gettext_noop("no"),
gettext_noop("Create DB"),
gettext_noop("no limit"),
gettext_noop("Connections"),
gettext_noop("Member of"));
if (verbose) if (verbose)
appendPQExpBuffer(&buf, "\n, pg_catalog.shobj_description(r.oid, 'pg_authid') AS \"%s\"", appendPQExpBuffer(&buf, "\n, pg_catalog.shobj_description(r.oid, 'pg_authid') AS \"%s\"",
_("Description")); gettext_noop("Description"));
appendPQExpBuffer(&buf, "\nFROM pg_catalog.pg_roles r\n"); appendPQExpBuffer(&buf, "\nFROM pg_catalog.pg_roles r\n");
@ -1609,6 +1653,8 @@ describeRoles(const char *pattern, bool verbose)
myopt.nullPrint = NULL; myopt.nullPrint = NULL;
myopt.title = _("List of roles"); myopt.title = _("List of roles");
myopt.trans_headers = true;
myopt.trans_columns = trans_columns;
printQuery(res, &myopt, pset.queryFout, pset.logfile); printQuery(res, &myopt, pset.queryFout, pset.logfile);
@ -1642,6 +1688,7 @@ listTables(const char *tabtypes, const char *pattern, bool verbose)
PQExpBufferData buf; PQExpBufferData buf;
PGresult *res; PGresult *res;
printQueryOpt myopt = pset.popt; printQueryOpt myopt = pset.popt;
static const bool trans_columns[] = {false, false, true, false, false, false};
if (!(showTables || showIndexes || showViews || showSeq)) if (!(showTables || showIndexes || showViews || showSeq))
showTables = showViews = showSeq = true; showTables = showViews = showSeq = true;
@ -1657,19 +1704,21 @@ listTables(const char *tabtypes, const char *pattern, bool verbose)
" c.relname as \"%s\",\n" " 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" " 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"
" r.rolname as \"%s\"", " r.rolname as \"%s\"",
_("Schema"), _("Name"), gettext_noop("Schema"),
_("table"), _("view"), _("index"), _("sequence"), gettext_noop("Name"),
_("special"), _("Type"), _("Owner")); gettext_noop("table"), gettext_noop("view"), gettext_noop("index"), gettext_noop("sequence"), gettext_noop("special"),
gettext_noop("Type"),
gettext_noop("Owner"));
if (showIndexes) if (showIndexes)
appendPQExpBuffer(&buf, appendPQExpBuffer(&buf,
",\n c2.relname as \"%s\"", ",\n c2.relname as \"%s\"",
_("Table")); gettext_noop("Table"));
if (verbose) if (verbose)
appendPQExpBuffer(&buf, appendPQExpBuffer(&buf,
",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"", ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"",
_("Description")); gettext_noop("Description"));
appendPQExpBuffer(&buf, appendPQExpBuffer(&buf,
"\nFROM pg_catalog.pg_class c" "\nFROM pg_catalog.pg_class c"
@ -1729,6 +1778,8 @@ listTables(const char *tabtypes, const char *pattern, bool verbose)
{ {
myopt.nullPrint = NULL; myopt.nullPrint = NULL;
myopt.title = _("List of relations"); myopt.title = _("List of relations");
myopt.trans_headers = true;
myopt.trans_columns = trans_columns;
printQuery(res, &myopt, pset.queryFout, pset.logfile); printQuery(res, &myopt, pset.queryFout, pset.logfile);
} }
@ -1766,11 +1817,11 @@ listDomains(const char *pattern)
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n" " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n"
" LEFT JOIN pg_catalog.pg_constraint r ON t.oid = r.contypid\n" " LEFT JOIN pg_catalog.pg_constraint r ON t.oid = r.contypid\n"
"WHERE t.typtype = 'd'\n", "WHERE t.typtype = 'd'\n",
_("Schema"), gettext_noop("Schema"),
_("Name"), gettext_noop("Name"),
_("Type"), gettext_noop("Type"),
_("Modifier"), gettext_noop("Modifier"),
_("Check")); gettext_noop("Check"));
processSQLNamePattern(pset.db, &buf, pattern, true, false, processSQLNamePattern(pset.db, &buf, pattern, true, false,
"n.nspname", "t.typname", NULL, "n.nspname", "t.typname", NULL,
@ -1785,6 +1836,7 @@ listDomains(const char *pattern)
myopt.nullPrint = NULL; myopt.nullPrint = NULL;
myopt.title = _("List of domains"); myopt.title = _("List of domains");
myopt.trans_headers = true;
printQuery(res, &myopt, pset.queryFout, pset.logfile); printQuery(res, &myopt, pset.queryFout, pset.logfile);
@ -1803,6 +1855,7 @@ listConversions(const char *pattern)
PQExpBufferData buf; PQExpBufferData buf;
PGresult *res; PGresult *res;
printQueryOpt myopt = pset.popt; printQueryOpt myopt = pset.popt;
static const bool trans_columns[] = {false, false, false, false, true};
initPQExpBuffer(&buf); initPQExpBuffer(&buf);
@ -1815,13 +1868,12 @@ listConversions(const char *pattern)
" ELSE '%s' END AS \"%s\"\n" " ELSE '%s' END AS \"%s\"\n"
"FROM pg_catalog.pg_conversion c, pg_catalog.pg_namespace n\n" "FROM pg_catalog.pg_conversion c, pg_catalog.pg_namespace n\n"
"WHERE n.oid = c.connamespace\n", "WHERE n.oid = c.connamespace\n",
_("Schema"), gettext_noop("Schema"),
_("Name"), gettext_noop("Name"),
_("Source"), gettext_noop("Source"),
_("Destination"), gettext_noop("Destination"),
_("yes"), gettext_noop("yes"), gettext_noop("no"),
_("no"), gettext_noop("Default?"));
_("Default?"));
processSQLNamePattern(pset.db, &buf, pattern, true, false, processSQLNamePattern(pset.db, &buf, pattern, true, false,
"n.nspname", "c.conname", NULL, "n.nspname", "c.conname", NULL,
@ -1836,6 +1888,8 @@ listConversions(const char *pattern)
myopt.nullPrint = NULL; myopt.nullPrint = NULL;
myopt.title = _("List of conversions"); myopt.title = _("List of conversions");
myopt.trans_headers = true;
myopt.trans_columns = trans_columns;
printQuery(res, &myopt, pset.queryFout, pset.logfile); printQuery(res, &myopt, pset.queryFout, pset.logfile);
@ -1854,13 +1908,19 @@ listCasts(const char *pattern)
PQExpBufferData buf; PQExpBufferData buf;
PGresult *res; PGresult *res;
printQueryOpt myopt = pset.popt; printQueryOpt myopt = pset.popt;
static const bool trans_columns[] = {false, false, false, true};
initPQExpBuffer(&buf); initPQExpBuffer(&buf);
/* NEED LEFT JOIN FOR BINARY CASTS */ /*
* We need left join here for binary casts. Also note that we don't
* attempt to localize '(binary compatible)', because there's too much
* risk of gettext translating a function name that happens to match
* some string in the PO database.
*/
printfPQExpBuffer(&buf, printfPQExpBuffer(&buf,
"SELECT pg_catalog.format_type(castsource, NULL) AS \"%s\",\n" "SELECT pg_catalog.format_type(castsource, NULL) AS \"%s\",\n"
" pg_catalog.format_type(casttarget, NULL) AS \"%s\",\n" " pg_catalog.format_type(casttarget, NULL) AS \"%s\",\n"
" CASE WHEN castfunc = 0 THEN '%s'\n" " CASE WHEN castfunc = 0 THEN '(binary compatible)'\n"
" ELSE p.proname\n" " ELSE p.proname\n"
" END as \"%s\",\n" " END as \"%s\",\n"
" CASE WHEN c.castcontext = 'e' THEN '%s'\n" " CASE WHEN c.castcontext = 'e' THEN '%s'\n"
@ -1870,14 +1930,11 @@ listCasts(const char *pattern)
"FROM pg_catalog.pg_cast c LEFT JOIN pg_catalog.pg_proc p\n" "FROM pg_catalog.pg_cast c LEFT JOIN pg_catalog.pg_proc p\n"
" ON c.castfunc = p.oid\n" " ON c.castfunc = p.oid\n"
"ORDER BY 1, 2", "ORDER BY 1, 2",
_("Source type"), gettext_noop("Source type"),
_("Target type"), gettext_noop("Target type"),
_("(binary compatible)"), gettext_noop("Function"),
_("Function"), gettext_noop("no"), gettext_noop("in assignment"), gettext_noop("yes"),
_("no"), gettext_noop("Implicit?"));
_("in assignment"),
_("yes"),
_("Implicit?"));
res = PSQLexec(buf.data, false); res = PSQLexec(buf.data, false);
termPQExpBuffer(&buf); termPQExpBuffer(&buf);
@ -1886,6 +1943,8 @@ listCasts(const char *pattern)
myopt.nullPrint = NULL; myopt.nullPrint = NULL;
myopt.title = _("List of casts"); myopt.title = _("List of casts");
myopt.trans_headers = true;
myopt.trans_columns = trans_columns;
printQuery(res, &myopt, pset.queryFout, pset.logfile); printQuery(res, &myopt, pset.queryFout, pset.logfile);
@ -1909,13 +1968,15 @@ listSchemas(const char *pattern, bool verbose)
printfPQExpBuffer(&buf, printfPQExpBuffer(&buf,
"SELECT n.nspname AS \"%s\",\n" "SELECT n.nspname AS \"%s\",\n"
" r.rolname AS \"%s\"", " r.rolname AS \"%s\"",
_("Name"), _("Owner")); gettext_noop("Name"),
gettext_noop("Owner"));
if (verbose) if (verbose)
appendPQExpBuffer(&buf, appendPQExpBuffer(&buf,
",\n n.nspacl as \"%s\"," ",\n n.nspacl as \"%s\","
" pg_catalog.obj_description(n.oid, 'pg_namespace') as \"%s\"", " pg_catalog.obj_description(n.oid, 'pg_namespace') as \"%s\"",
_("Access privileges"), _("Description")); gettext_noop("Access privileges"),
gettext_noop("Description"));
appendPQExpBuffer(&buf, appendPQExpBuffer(&buf,
"\nFROM pg_catalog.pg_namespace n JOIN pg_catalog.pg_roles r\n" "\nFROM pg_catalog.pg_namespace n JOIN pg_catalog.pg_roles r\n"
@ -1936,6 +1997,7 @@ listSchemas(const char *pattern, bool verbose)
myopt.nullPrint = NULL; myopt.nullPrint = NULL;
myopt.title = _("List of schemas"); myopt.title = _("List of schemas");
myopt.trans_headers = true;
printQuery(res, &myopt, pset.queryFout, pset.logfile); printQuery(res, &myopt, pset.queryFout, pset.logfile);
@ -1967,9 +2029,9 @@ listTSParsers(const char *pattern, bool verbose)
" pg_catalog.obj_description(p.oid, 'pg_ts_parser') as \"%s\"\n" " pg_catalog.obj_description(p.oid, 'pg_ts_parser') as \"%s\"\n"
"FROM pg_catalog.pg_ts_parser p \n" "FROM pg_catalog.pg_ts_parser p \n"
"LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.prsnamespace\n", "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.prsnamespace\n",
_("Schema"), gettext_noop("Schema"),
_("Name"), gettext_noop("Name"),
_("Description") gettext_noop("Description")
); );
processSQLNamePattern(pset.db, &buf, pattern, false, false, processSQLNamePattern(pset.db, &buf, pattern, false, false,
@ -1985,6 +2047,7 @@ listTSParsers(const char *pattern, bool verbose)
myopt.nullPrint = NULL; myopt.nullPrint = NULL;
myopt.title = _("List of text search parsers"); myopt.title = _("List of text search parsers");
myopt.trans_headers = true;
printQuery(res, &myopt, pset.queryFout, pset.logfile); printQuery(res, &myopt, pset.queryFout, pset.logfile);
@ -2067,6 +2130,7 @@ describeOneTSParser(const char *oid, const char *nspname, const char *prsname)
PGresult *res; PGresult *res;
char title[1024]; char title[1024];
printQueryOpt myopt = pset.popt; printQueryOpt myopt = pset.popt;
static const bool trans_columns[] = {true, false, false};
initPQExpBuffer(&buf); initPQExpBuffer(&buf);
@ -2100,14 +2164,19 @@ describeOneTSParser(const char *oid, const char *nspname, const char *prsname)
" pg_catalog.obj_description(p.prslextype, 'pg_proc') \n" " pg_catalog.obj_description(p.prslextype, 'pg_proc') \n"
" FROM pg_catalog.pg_ts_parser p \n" " FROM pg_catalog.pg_ts_parser p \n"
" WHERE p.oid = '%s' \n", " WHERE p.oid = '%s' \n",
_("Start parse"), gettext_noop("Start parse"),
_("Method"), _("Function"), _("Description"), gettext_noop("Method"),
gettext_noop("Function"),
gettext_noop("Description"),
oid, oid,
_("Get next token"), oid, gettext_noop("Get next token"),
_("End parse"), oid, oid,
_("Get headline"), oid, gettext_noop("End parse"),
_("Get token types"), oid oid,
); gettext_noop("Get headline"),
oid,
gettext_noop("Get token types"),
oid);
res = PSQLexec(buf.data, false); res = PSQLexec(buf.data, false);
termPQExpBuffer(&buf); termPQExpBuffer(&buf);
@ -2122,6 +2191,8 @@ describeOneTSParser(const char *oid, const char *nspname, const char *prsname)
myopt.title = title; myopt.title = title;
myopt.footers = NULL; myopt.footers = NULL;
myopt.default_footer = false; myopt.default_footer = false;
myopt.trans_headers = true;
myopt.trans_columns = trans_columns;
printQuery(res, &myopt, pset.queryFout, pset.logfile); printQuery(res, &myopt, pset.queryFout, pset.logfile);
@ -2134,8 +2205,8 @@ describeOneTSParser(const char *oid, const char *nspname, const char *prsname)
" t.description as \"%s\" \n" " t.description as \"%s\" \n"
"FROM pg_catalog.ts_token_type( '%s'::pg_catalog.oid ) as t \n" "FROM pg_catalog.ts_token_type( '%s'::pg_catalog.oid ) as t \n"
"ORDER BY 1;", "ORDER BY 1;",
_("Token name"), gettext_noop("Token name"),
_("Description"), gettext_noop("Description"),
oid); oid);
res = PSQLexec(buf.data, false); res = PSQLexec(buf.data, false);
@ -2151,6 +2222,8 @@ describeOneTSParser(const char *oid, const char *nspname, const char *prsname)
myopt.title = title; myopt.title = title;
myopt.footers = NULL; myopt.footers = NULL;
myopt.default_footer = true; myopt.default_footer = true;
myopt.trans_headers = true;
myopt.trans_columns = NULL;
printQuery(res, &myopt, pset.queryFout, pset.logfile); printQuery(res, &myopt, pset.queryFout, pset.logfile);
@ -2176,8 +2249,8 @@ listTSDictionaries(const char *pattern, bool verbose)
"SELECT \n" "SELECT \n"
" n.nspname as \"%s\",\n" " n.nspname as \"%s\",\n"
" d.dictname as \"%s\",\n", " d.dictname as \"%s\",\n",
_("Schema"), gettext_noop("Schema"),
_("Name")); gettext_noop("Name"));
if (verbose) if (verbose)
{ {
@ -2187,13 +2260,13 @@ listTSDictionaries(const char *pattern, bool verbose)
" LEFT JOIN pg_catalog.pg_namespace nt ON nt.oid = t.tmplnamespace \n" " LEFT JOIN pg_catalog.pg_namespace nt ON nt.oid = t.tmplnamespace \n"
" WHERE d.dicttemplate = t.oid ) AS \"%s\", \n" " WHERE d.dicttemplate = t.oid ) AS \"%s\", \n"
" d.dictinitoption as \"%s\", \n", " d.dictinitoption as \"%s\", \n",
_("Template"), gettext_noop("Template"),
_("Init options")); gettext_noop("Init options"));
} }
appendPQExpBuffer(&buf, appendPQExpBuffer(&buf,
" pg_catalog.obj_description(d.oid, 'pg_ts_dict') as \"%s\"\n", " pg_catalog.obj_description(d.oid, 'pg_ts_dict') as \"%s\"\n",
_("Description")); gettext_noop("Description"));
appendPQExpBuffer(&buf, "FROM pg_catalog.pg_ts_dict d\n" appendPQExpBuffer(&buf, "FROM pg_catalog.pg_ts_dict d\n"
"LEFT JOIN pg_catalog.pg_namespace n ON n.oid = d.dictnamespace\n"); "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = d.dictnamespace\n");
@ -2211,6 +2284,7 @@ listTSDictionaries(const char *pattern, bool verbose)
myopt.nullPrint = NULL; myopt.nullPrint = NULL;
myopt.title = _("List of text search dictionaries"); myopt.title = _("List of text search dictionaries");
myopt.trans_headers = true;
printQuery(res, &myopt, pset.queryFout, pset.logfile); printQuery(res, &myopt, pset.queryFout, pset.logfile);
@ -2240,20 +2314,20 @@ listTSTemplates(const char *pattern, bool verbose)
" t.tmplinit::pg_catalog.regproc AS \"%s\",\n" " t.tmplinit::pg_catalog.regproc AS \"%s\",\n"
" t.tmpllexize::pg_catalog.regproc AS \"%s\",\n" " t.tmpllexize::pg_catalog.regproc AS \"%s\",\n"
" pg_catalog.obj_description(t.oid, 'pg_ts_template') AS \"%s\"\n", " pg_catalog.obj_description(t.oid, 'pg_ts_template') AS \"%s\"\n",
_("Schema"), gettext_noop("Schema"),
_("Name"), gettext_noop("Name"),
_("Init"), gettext_noop("Init"),
_("Lexize"), gettext_noop("Lexize"),
_("Description")); gettext_noop("Description"));
else else
printfPQExpBuffer(&buf, printfPQExpBuffer(&buf,
"SELECT \n" "SELECT \n"
" n.nspname AS \"%s\",\n" " n.nspname AS \"%s\",\n"
" t.tmplname AS \"%s\",\n" " t.tmplname AS \"%s\",\n"
" pg_catalog.obj_description(t.oid, 'pg_ts_template') AS \"%s\"\n", " pg_catalog.obj_description(t.oid, 'pg_ts_template') AS \"%s\"\n",
_("Schema"), gettext_noop("Schema"),
_("Name"), gettext_noop("Name"),
_("Description")); gettext_noop("Description"));
appendPQExpBuffer(&buf, "FROM pg_catalog.pg_ts_template t\n" appendPQExpBuffer(&buf, "FROM pg_catalog.pg_ts_template t\n"
"LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.tmplnamespace\n"); "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.tmplnamespace\n");
@ -2271,6 +2345,7 @@ listTSTemplates(const char *pattern, bool verbose)
myopt.nullPrint = NULL; myopt.nullPrint = NULL;
myopt.title = _("List of text search templates"); myopt.title = _("List of text search templates");
myopt.trans_headers = true;
printQuery(res, &myopt, pset.queryFout, pset.logfile); printQuery(res, &myopt, pset.queryFout, pset.logfile);
@ -2302,9 +2377,9 @@ listTSConfigs(const char *pattern, bool verbose)
" pg_catalog.obj_description(c.oid, 'pg_ts_config') as \"%s\"\n" " pg_catalog.obj_description(c.oid, 'pg_ts_config') as \"%s\"\n"
"FROM pg_catalog.pg_ts_config c\n" "FROM pg_catalog.pg_ts_config c\n"
"LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.cfgnamespace \n", "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.cfgnamespace \n",
_("Schema"), gettext_noop("Schema"),
_("Name"), gettext_noop("Name"),
_("Description") gettext_noop("Description")
); );
processSQLNamePattern(pset.db, &buf, pattern, false, false, processSQLNamePattern(pset.db, &buf, pattern, false, false,
@ -2320,6 +2395,7 @@ listTSConfigs(const char *pattern, bool verbose)
myopt.nullPrint = NULL; myopt.nullPrint = NULL;
myopt.title = _("List of text search configurations"); myopt.title = _("List of text search configurations");
myopt.trans_headers = true;
printQuery(res, &myopt, pset.queryFout, pset.logfile); printQuery(res, &myopt, pset.queryFout, pset.logfile);
@ -2428,8 +2504,8 @@ describeOneTSConfig(const char *oid, const char *nspname, const char *cfgname,
"WHERE c.oid = '%s' AND m.mapcfg = c.oid \n" "WHERE c.oid = '%s' AND m.mapcfg = c.oid \n"
"GROUP BY m.mapcfg, m.maptokentype, c.cfgparser \n" "GROUP BY m.mapcfg, m.maptokentype, c.cfgparser \n"
"ORDER BY 1", "ORDER BY 1",
_("Token"), gettext_noop("Token"),
_("Dictionaries"), gettext_noop("Dictionaries"),
oid); oid);
res = PSQLexec(buf.data, false); res = PSQLexec(buf.data, false);
@ -2440,19 +2516,24 @@ describeOneTSConfig(const char *oid, const char *nspname, const char *cfgname,
initPQExpBuffer(&title); initPQExpBuffer(&title);
if (nspname) if (nspname)
appendPQExpBuffer(&title, _("Text search configuration \"%s.%s\""), nspname, cfgname); appendPQExpBuffer(&title, _("Text search configuration \"%s.%s\""),
nspname, cfgname);
else else
appendPQExpBuffer(&title, _("Text search configuration \"%s\""), cfgname); appendPQExpBuffer(&title, _("Text search configuration \"%s\""),
cfgname);
if (pnspname) if (pnspname)
appendPQExpBuffer(&title, _("\nParser: \"%s.%s\""), pnspname, prsname); appendPQExpBuffer(&title, _("\nParser: \"%s.%s\""),
pnspname, prsname);
else else
appendPQExpBuffer(&title, _("\nParser: \"%s\""), prsname); appendPQExpBuffer(&title, _("\nParser: \"%s\""),
prsname);
myopt.nullPrint = NULL; myopt.nullPrint = NULL;
myopt.title = title.data; myopt.title = title.data;
myopt.footers = NULL; myopt.footers = NULL;
myopt.default_footer = false; myopt.default_footer = false;
myopt.trans_headers = true;
printQuery(res, &myopt, pset.queryFout, pset.logfile); printQuery(res, &myopt, pset.queryFout, pset.logfile);

View File

@ -3,7 +3,7 @@
* *
* Copyright (c) 2000-2007, PostgreSQL Global Development Group * Copyright (c) 2000-2007, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/bin/psql/large_obj.c,v 1.48 2007/01/20 16:57:31 neilc Exp $ * $PostgreSQL: pgsql/src/bin/psql/large_obj.c,v 1.49 2007/12/12 21:41:47 tgl Exp $
*/ */
#include "postgres_fe.h" #include "postgres_fe.h"
#include "large_obj.h" #include "large_obj.h"
@ -279,11 +279,12 @@ do_lo_list(void)
printQueryOpt myopt = pset.popt; printQueryOpt myopt = pset.popt;
snprintf(buf, sizeof(buf), snprintf(buf, sizeof(buf),
"SELECT loid as \"ID\",\n" "SELECT loid as \"%s\",\n"
" pg_catalog.obj_description(loid, 'pg_largeobject') as \"%s\"\n" " pg_catalog.obj_description(loid, 'pg_largeobject') as \"%s\"\n"
"FROM (SELECT DISTINCT loid FROM pg_catalog.pg_largeobject) x\n" "FROM (SELECT DISTINCT loid FROM pg_catalog.pg_largeobject) x\n"
"ORDER BY 1", "ORDER BY 1",
_("Description")); gettext_noop("ID"),
gettext_noop("Description"));
res = PSQLexec(buf, false); res = PSQLexec(buf, false);
if (!res) if (!res)
@ -292,6 +293,7 @@ do_lo_list(void)
myopt.topt.tuples_only = false; myopt.topt.tuples_only = false;
myopt.nullPrint = NULL; myopt.nullPrint = NULL;
myopt.title = _("Large objects"); myopt.title = _("Large objects");
myopt.trans_headers = true;
printQuery(res, &myopt, pset.queryFout, pset.logfile); printQuery(res, &myopt, pset.queryFout, pset.logfile);

View File

@ -3,7 +3,7 @@
* *
* Copyright (c) 2000-2007, PostgreSQL Global Development Group * Copyright (c) 2000-2007, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.94 2007/11/22 17:51:39 momjian Exp $ * $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.95 2007/12/12 21:41:47 tgl Exp $
* *
* Note: we include postgres.h not postgres_fe.h so that we can include * Note: we include postgres.h not postgres_fe.h so that we can include
* catalog/pg_type.h, and thereby have access to INT4OID and similar macros. * catalog/pg_type.h, and thereby have access to INT4OID and similar macros.
@ -1926,38 +1926,59 @@ printTable(const char *title,
void void
printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *flog) printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *flog)
{ {
int ntuples;
int nfields; int nfields;
int ncells; int ncells;
const char **headers; const char **headers;
const char **cells; const char **cells;
char **footers; char **footers;
char *align; char *align;
int i; int i,
r,
c;
if (cancel_pressed) if (cancel_pressed)
return; return;
/* extract headers */ /* extract headers */
ntuples = PQntuples(result);
nfields = PQnfields(result); nfields = PQnfields(result);
headers = pg_local_calloc(nfields + 1, sizeof(*headers)); headers = pg_local_calloc(nfields + 1, sizeof(*headers));
for (i = 0; i < nfields; i++) for (i = 0; i < nfields; i++)
{
headers[i] = (char *) mbvalidate((unsigned char *) PQfname(result, i), headers[i] = (char *) mbvalidate((unsigned char *) PQfname(result, i),
opt->topt.encoding); opt->topt.encoding);
#ifdef ENABLE_NLS
if (opt->trans_headers)
headers[i] = _(headers[i]);
#endif
}
/* set cells */ /* set cells */
ncells = PQntuples(result) * nfields; ncells = ntuples * nfields;
cells = pg_local_calloc(ncells + 1, sizeof(*cells)); cells = pg_local_calloc(ncells + 1, sizeof(*cells));
for (i = 0; i < ncells; i++) i = 0;
for (r = 0; r < ntuples; r++)
{ {
if (PQgetisnull(result, i / nfields, i % nfields)) for (c = 0; c < nfields; c++)
cells[i] = opt->nullPrint ? opt->nullPrint : ""; {
else if (PQgetisnull(result, r, c))
cells[i] = (char *) cells[i] = opt->nullPrint ? opt->nullPrint : "";
mbvalidate((unsigned char *) PQgetvalue(result, i / nfields, i % nfields), else
opt->topt.encoding); {
cells[i] = (char *)
mbvalidate((unsigned char *) PQgetvalue(result, r, c),
opt->topt.encoding);
#ifdef ENABLE_NLS
if (opt->trans_columns && opt->trans_columns[c])
cells[i] = _(cells[i]);
#endif
}
i++;
}
} }
/* set footers */ /* set footers */
@ -1970,7 +1991,7 @@ printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *f
footers = pg_local_calloc(2, sizeof(*footers)); footers = pg_local_calloc(2, sizeof(*footers));
footers[0] = pg_local_malloc(100); footers[0] = pg_local_malloc(100);
total_records = opt->topt.prior_records + PQntuples(result); total_records = opt->topt.prior_records + ntuples;
if (total_records == 1) if (total_records == 1)
snprintf(footers[0], 100, _("(1 row)")); snprintf(footers[0], 100, _("(1 row)"));
else else
@ -2013,7 +2034,7 @@ printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *f
free(headers); free(headers);
free(cells); free(cells);
if (footers) if (footers && !opt->footers)
{ {
free(footers[0]); free(footers[0]);
free(footers); free(footers);

View File

@ -3,7 +3,7 @@
* *
* Copyright (c) 2000-2007, PostgreSQL Global Development Group * Copyright (c) 2000-2007, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/bin/psql/print.h,v 1.33 2007/01/05 22:19:49 momjian Exp $ * $PostgreSQL: pgsql/src/bin/psql/print.h,v 1.34 2007/12/12 21:41:47 tgl Exp $
*/ */
#ifndef PRINT_H #ifndef PRINT_H
#define PRINT_H #define PRINT_H
@ -67,7 +67,6 @@ void printTable(const char *title, const char *const * headers,
const printTableOpt *opt, FILE *fout, FILE *flog); const printTableOpt *opt, FILE *fout, FILE *flog);
typedef struct _printQueryOpt typedef struct _printQueryOpt
{ {
printTableOpt topt; /* the options above */ printTableOpt topt; /* the options above */
@ -76,6 +75,8 @@ typedef struct _printQueryOpt
char *title; /* override title */ char *title; /* override title */
char **footers; /* override footer (default is "(xx rows)") */ char **footers; /* override footer (default is "(xx rows)") */
bool default_footer; /* print default footer if footers==NULL */ bool default_footer; /* print default footer if footers==NULL */
bool trans_headers; /* do gettext on column headers */
const bool *trans_columns; /* trans_columns[i-1] => do gettext on col i */
} printQueryOpt; } printQueryOpt;
/* /*

View File

@ -3,7 +3,7 @@
* *
* Copyright (c) 2000-2007, PostgreSQL Global Development Group * Copyright (c) 2000-2007, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/bin/psql/startup.c,v 1.144 2007/12/11 19:01:06 tgl Exp $ * $PostgreSQL: pgsql/src/bin/psql/startup.c,v 1.145 2007/12/12 21:41:47 tgl Exp $
*/ */
#include "postgres_fe.h" #include "postgres_fe.h"
@ -140,6 +140,7 @@ main(int argc, char *argv[])
pset.cur_cmd_source = stdin; pset.cur_cmd_source = stdin;
pset.cur_cmd_interactive = false; pset.cur_cmd_interactive = false;
/* We rely on unmentioned fields of pset.popt to start out 0/false/NULL */
pset.popt.topt.format = PRINT_ALIGNED; pset.popt.topt.format = PRINT_ALIGNED;
pset.popt.topt.border = 1; pset.popt.topt.border = 1;
pset.popt.topt.pager = 1; pset.popt.topt.pager = 1;

View File

@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/bin/scripts/createlang.c,v 1.27 2007/12/11 19:57:32 tgl Exp $ * $PostgreSQL: pgsql/src/bin/scripts/createlang.c,v 1.28 2007/12/12 21:41:47 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -125,6 +125,7 @@ main(int argc, char *argv[])
if (listlangs) if (listlangs)
{ {
printQueryOpt popt; printQueryOpt popt;
static const bool trans_columns[] = {false, true};
conn = connectDatabase(dbname, host, port, username, password, conn = connectDatabase(dbname, host, port, username, password,
progname); progname);
@ -132,7 +133,9 @@ main(int argc, char *argv[])
printfPQExpBuffer(&sql, "SELECT lanname as \"%s\", " printfPQExpBuffer(&sql, "SELECT lanname as \"%s\", "
"(CASE WHEN lanpltrusted THEN '%s' ELSE '%s' END) as \"%s\" " "(CASE WHEN lanpltrusted THEN '%s' ELSE '%s' END) as \"%s\" "
"FROM pg_catalog.pg_language WHERE lanispl;", "FROM pg_catalog.pg_language WHERE lanispl;",
_("Name"), _("yes"), _("no"), _("Trusted?")); gettext_noop("Name"),
gettext_noop("yes"), gettext_noop("no"),
gettext_noop("Trusted?"));
result = executeQuery(conn, sql.data, progname, echo); result = executeQuery(conn, sql.data, progname, echo);
memset(&popt, 0, sizeof(popt)); memset(&popt, 0, sizeof(popt));
@ -142,6 +145,8 @@ main(int argc, char *argv[])
popt.topt.stop_table = true; popt.topt.stop_table = true;
popt.topt.encoding = PQclientEncoding(conn); popt.topt.encoding = PQclientEncoding(conn);
popt.title = _("Procedural Languages"); popt.title = _("Procedural Languages");
popt.trans_headers = true;
popt.trans_columns = trans_columns;
printQuery(result, &popt, stdout, NULL); printQuery(result, &popt, stdout, NULL);
PQfinish(conn); PQfinish(conn);

View File

@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/bin/scripts/droplang.c,v 1.24 2007/12/11 19:57:32 tgl Exp $ * $PostgreSQL: pgsql/src/bin/scripts/droplang.c,v 1.25 2007/12/12 21:41:47 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -136,6 +136,7 @@ main(int argc, char *argv[])
if (listlangs) if (listlangs)
{ {
printQueryOpt popt; printQueryOpt popt;
static const bool trans_columns[] = {false, true};
conn = connectDatabase(dbname, host, port, username, password, conn = connectDatabase(dbname, host, port, username, password,
progname); progname);
@ -143,7 +144,9 @@ main(int argc, char *argv[])
printfPQExpBuffer(&sql, "SELECT lanname as \"%s\", " printfPQExpBuffer(&sql, "SELECT lanname as \"%s\", "
"(CASE WHEN lanpltrusted THEN '%s' ELSE '%s' END) as \"%s\" " "(CASE WHEN lanpltrusted THEN '%s' ELSE '%s' END) as \"%s\" "
"FROM pg_catalog.pg_language WHERE lanispl;", "FROM pg_catalog.pg_language WHERE lanispl;",
_("Name"), _("yes"), _("no"), _("Trusted?")); gettext_noop("Name"),
gettext_noop("yes"), gettext_noop("no"),
gettext_noop("Trusted?"));
result = executeQuery(conn, sql.data, progname, echo); result = executeQuery(conn, sql.data, progname, echo);
memset(&popt, 0, sizeof(popt)); memset(&popt, 0, sizeof(popt));
@ -153,6 +156,8 @@ main(int argc, char *argv[])
popt.topt.stop_table = true; popt.topt.stop_table = true;
popt.topt.encoding = PQclientEncoding(conn); popt.topt.encoding = PQclientEncoding(conn);
popt.title = _("Procedural Languages"); popt.title = _("Procedural Languages");
popt.trans_headers = true;
popt.trans_columns = trans_columns;
printQuery(result, &popt, stdout, NULL); printQuery(result, &popt, stdout, NULL);
PQfinish(conn); PQfinish(conn);