On Tue, Apr 14, 2009 at 02:52:32PM -0400, Alvaro Herrera wrote:
> Tom Lane wrote:
> 
> > I had a second thought about that: presumably we should make the
> > function type names translatable.  If we do that, it might be better
> > to make the aggregate case be "aggregate" and take the width hit.
> > Otherwise translators are going to be puzzled when they come across
> > "agg" as a translatable phrase.
> 
> I think it's good to have them translatable.  As for using "aggregate"
> instead of "agg" I don't think it's that great an idea.  If you need to
> notify translators that "agg" stands for "aggregate", add a
> /* translator: */ comment.

Here's the next revision :)

Cheers,
David.
-- 
David Fetter <da...@fetter.org> http://fetter.org/
Phone: +1 415 235 3778  AIM: dfetter666  Yahoo!: dfetter
Skype: davidfetter      XMPP: david.fet...@gmail.com

Remember to vote!
Consider donating to Postgres: http://www.postgresql.org/about/donate
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index 10d42ca..5224440 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -1043,14 +1043,19 @@ testdb=&gt;
         <listitem>
         <para>
         Lists available functions, together with their argument and
-        return types. If <replaceable
-        class="parameter">pattern</replaceable>
-        is specified, only functions whose names match the pattern are shown.
-        If the form <literal>\df+</literal> is used, additional information 
about
-        each function, including volatility, language, source code and 
description, is shown.
-        By default, only user-created objects are shown;  supply a
-        pattern or the <literal>S</literal> modifier to include system
-        objects.
+        return types and their function type: 'normal', 'agg',
+        'trigger', and 'window'.  If <replaceable
+        class="parameter">pattern</replaceable> is specified, only
+        functions whose names match the pattern are shown.  If the
+        form <literal>\df+</literal> is used, additional information
+        about each function, including volatility, language, source
+        code and description, is shown.  By default, only user-created
+        objects are shown;  supply a pattern or the
+        <literal>S</literal> modifier to include system objects.  To
+        include aggregates in the result set, use \dfa, normal
+        functions, \dfn, trigger functions, \dft, windowing functions,
+        \dfw.  You may freely mix and match the +, S, a, n, t and w
+        options.
         </para>
 
         <note>
@@ -1064,7 +1069,6 @@ testdb=&gt;
         </listitem>
       </varlistentry>
 
-
       <varlistentry>
         <term><literal>\dF[+] [ <replaceable 
class="parameter">pattern</replaceable> ]</literal></term>
         <listitem>
diff --git a/doc/src/sgml/release.sgml b/doc/src/sgml/release.sgml
index fc56c3d..09ba686 100644
--- a/doc/src/sgml/release.sgml
+++ b/doc/src/sgml/release.sgml
@@ -183,6 +183,15 @@ do it for earlier branch release files.
      </para>
     </listitem>
 
+    <listitem>
+     <para>
+      In psql, \df now shows which type of function (normal,
+      aggregate, trigger, or window) it is.  You can also specify
+      mix-and-match options.  To get aggregates and windowing
+      functions, including system ones, for example, invoke \dfwaS+
+     </para>
+    </listitem>
+
    </itemizedlist>
 
    <para>
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index b39466d..1dc3cc3 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -365,8 +365,22 @@ exec_command(const char *cmd,
                        case 'D':
                                success = listDomains(pattern, show_system);
                                break;
-                       case 'f':
-                               success = describeFunctions(pattern, 
show_verbose, show_system);
+                       case 'f':                       /* function subsystem */
+                               switch (cmd[2])
+                               {
+                                       case '\0':
+                                       case '+':
+                                       case 'S':
+                                       case 'a':
+                                       case 'n':
+                                       case 't':
+                                       case 'w':
+                                               success =  
describeFunctions(&cmd[2], pattern, show_verbose, show_system);
+                                               break;
+                                       default:
+                                               status = PSQL_CMD_UNKNOWN;
+                                               break;
+                               }
                                break;
                        case 'g':
                                /* no longer distinct from \du */
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 731baf8..ad5dcbe 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -183,15 +183,43 @@ describeTablespaces(const char *pattern, bool verbose)
 
 
 /* \df
- * Takes an optional regexp to select particular functions
+ * Takes an optional regexp to select particular functions.
+ *
+ * As with \d, you can specify the kinds of functions you want:
+ *
+ * a for aggregates
+ * n for normal
+ * t for trigger
+ * w for window
+ *
+ * and you can mix and match these in any order.
  */
 bool
-describeFunctions(const char *pattern, bool verbose, bool showSystem)
+describeFunctions(const char *functypes, const char *pattern, bool verbose, 
bool showSystem)
 {
+       bool                    showAggregate = strchr(functypes, 'a') != NULL;
+       bool                    showNormal = strchr(functypes, 'n') != NULL;
+       bool                    showTrigger = strchr(functypes, 't') != NULL;
+       bool                    showWindow = strchr(functypes, 'w') != NULL;
+
        PQExpBufferData buf;
        PGresult   *res;
        printQueryOpt myopt = pset.popt;
 
+       if (showWindow && pset.sversion < 80400)
+       {
+               fprintf(stderr, _("\\df does not take a \"w\" decorator in 
%d.%d.\n"),
+                               pset.sversion / 10000, (pset.sversion / 100) % 
100);
+               return true;
+       }
+
+       if (!(showAggregate || showNormal || showTrigger || showWindow))
+       {
+               showAggregate = showNormal = showTrigger = true;
+               if (pset.sversion >= 80400)
+                       showWindow = true;
+       }
+
        initPQExpBuffer(&buf);
 
        printfPQExpBuffer(&buf,
@@ -203,9 +231,20 @@ describeFunctions(const char *pattern, bool verbose, bool 
showSystem)
     if (pset.sversion >= 80400)
                appendPQExpBuffer(&buf,
                                                  "  
pg_catalog.pg_get_function_result(p.oid) as \"%s\",\n"
-                                                 "  
pg_catalog.pg_get_function_arguments(p.oid) as \"%s\"",
+                                                 "  
pg_catalog.pg_get_function_arguments(p.oid) as \"%s\",\n"
+                                                 " CASE\n"
+                                                 "  WHEN p.proisagg THEN 
'%s'\n"
+                                                 "  WHEN p.proiswindow THEN 
'%s'\n"
+                                                 "  WHEN 
pg_catalog.pg_get_function_result(p.oid) = 'trigger' THEN '%s'\n"
+                                                 "  ELSE '%s'\n"
+                                                 "END as \"%s\"",
                                                  gettext_noop("Result data 
type"),
-                                                 gettext_noop("Argument data 
types"));
+                                                 gettext_noop("Argument data 
types"),
+                                                 gettext_noop("agg"), /* 
translator: "agg" is short for "aggregate" */
+                                                 gettext_noop("window"),
+                                                 gettext_noop("trigger"),
+                                                 gettext_noop("normal"),
+                                                 gettext_noop("Type"));
     else if (pset.sversion >= 80100)
                appendPQExpBuffer(&buf,
                                          "  CASE WHEN p.proretset THEN 'SETOF 
' ELSE '' END ||\n"
@@ -238,16 +277,34 @@ describeFunctions(const char *pattern, bool verbose, bool 
showSystem)
                                          "      FROM\n"
                                          "        
pg_catalog.generate_series(0, pg_catalog.array_upper(p.proargtypes, 1)) AS 
s(i)\n"
                                          "    ), ', ')\n"
+                                         "  END AS \"%s\",\n"
+                                         "  CASE\n"
+                                         "    WHEN p.proisagg THEN '%s'\n"
+                                         "    WHEN 'trigger' = 
pg_catalog.format_type(p.prorettype, NULL) THEN '%s'\n"
+                                         "    ELSE '%s'\n"
                                          "  END AS \"%s\"",
-                                                 gettext_noop("Result data 
type"),
-                                                 gettext_noop("Argument data 
types"));
+                                         gettext_noop("Result data type"),
+                                         gettext_noop("Argument data types"),
+                                         gettext_noop("agg"), /* translator: 
"agg" is short for "aggregate" */
+                                         gettext_noop("trigger"),
+                                         gettext_noop("normal"),
+                                         gettext_noop("Type"));
        else
                appendPQExpBuffer(&buf,
                                          "  CASE WHEN p.proretset THEN 'SETOF 
' ELSE '' END ||\n"
                                  "  pg_catalog.format_type(p.prorettype, NULL) 
as \"%s\",\n"
-                                         "  
pg_catalog.oidvectortypes(p.proargtypes) as \"%s\"",
-                                                 gettext_noop("Result data 
type"),
-                                                 gettext_noop("Argument data 
types"));
+                                         "  
pg_catalog.oidvectortypes(p.proargtypes) as \"%s\",\n"
+                                         "  CASE\n"
+                                         "    WHEN p.proisagg THEN '%s'\n"
+                                         "    WHEN 'trigger' = 
pg_catalog.format_type(p.prorettype, NULL) THEN '%s'\n"
+                                         "    ELSE '%s'\n"
+                                         "  END AS \"%s\"",
+                                         gettext_noop("Result data type"),
+                                         gettext_noop("Argument data types"),
+                                         gettext_noop("agg"), /* translator: 
"agg" is short for "aggregate" */
+                                         gettext_noop("trigger"),
+                                         gettext_noop("normal"),
+                                         gettext_noop("Type"));
 
        if (verbose)
                appendPQExpBuffer(&buf,
@@ -274,16 +331,68 @@ describeFunctions(const char *pattern, bool verbose, bool 
showSystem)
                appendPQExpBuffer(&buf,
                                                  "     LEFT JOIN 
pg_catalog.pg_language l ON l.oid = p.prolang\n");
 
-       appendPQExpBuffer(&buf, "WHERE NOT p.proisagg\n");
+       processSQLNamePattern(pset.db, &buf, pattern, false, true,
+                                                 "n.nspname", "p.proname", 
NULL,
+                                                 
"pg_catalog.pg_function_is_visible(p.oid)");
+
+       if (showNormal && showAggregate && showTrigger && showWindow)
+               /* Do nothing */;
+       else if (showNormal)
+       {
+               if (!showWindow && pset.sversion >= 80400)
+                               appendPQExpBuffer(&buf, "      AND NOT 
p.proiswindow\n");
+               if (!showAggregate)
+                       appendPQExpBuffer(&buf, "      AND NOT p.proisagg\n");
+               if (!showTrigger)
+               {
+                       if (pset.sversion >= 80400)
+                               appendPQExpBuffer(&buf,
+                                                                 "      AND 
pg_catalog.pg_get_function_result(p.oid) <> 'trigger'\n");
+                       else
+                               appendPQExpBuffer(&buf,
+                                                                 "      AND 
pg_catalog.format_type(p.prorettype, NULL) <> 'trigger'\n");
+               }
+       }
+       else
+       {
+               bool needs_or = false;
+               bool needs_paren = showAggregate ? 1 : 0 +
+                                                  showTrigger ? 1 : 0 +
+                                                  showWindow ? 1 : 0
+                                                  > 1;
+               if (needs_paren)
+                       appendPQExpBuffer(&buf, "      AND (\n");
+               if (showAggregate)
+               {
+                       appendPQExpBuffer(&buf,"          p.proisagg\n");
+                       needs_or = true;
+               }
+               if (showTrigger)
+               {
+                       if (pset.sversion >= 80400)
+                               appendPQExpBuffer(&buf,
+                                                                 "%s          
pg_catalog.pg_get_function_result(p.oid) = 'trigger'\n",
+                                                                 needs_or ? 
"OR" : "  ");
+                       else
+                               appendPQExpBuffer(&buf,
+                                                                 "%s          
'trigger' <> pg_catalog.format_type(p.prorettype, NULL)\n",
+                                                                 needs_or ? 
"OR" : "  ");
+                       needs_or = true;
+               }
+               if (showWindow)
+               {
+                       appendPQExpBuffer(&buf,
+                                                         "%s          
p.proiswindow\n",
+                                                         needs_or ? "OR" : "  
");
+               }
+               if (needs_paren)
+                       appendPQExpBuffer(&buf, "      )\n");
+       }
 
        if (!showSystem && !pattern)
                appendPQExpBuffer(&buf, "      AND n.nspname <> 'pg_catalog'\n"
                                                                "      AND 
n.nspname <> 'information_schema'\n");
 
-       processSQLNamePattern(pset.db, &buf, pattern, true, false,
-                                                 "n.nspname", "p.proname", 
NULL,
-                                                 
"pg_catalog.pg_function_is_visible(p.oid)");
-
        appendPQExpBuffer(&buf, "ORDER BY 1, 2, 4;");
 
        res = PSQLexec(buf.data, false);
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index 57e5c7b..0b32ddf 100644
--- a/src/bin/psql/describe.h
+++ b/src/bin/psql/describe.h
@@ -15,8 +15,8 @@ extern bool describeAggregates(const char *pattern, bool 
verbose, bool showSyste
 /* \db */
 extern bool describeTablespaces(const char *pattern, bool verbose);
 
-/* \df */
-extern bool describeFunctions(const char *pattern, bool verbose, bool 
showSystem);
+/* \df, \dfa, \dfn, \dft, \dfw, etc. */
+extern bool describeFunctions(const char *functypes, const char *pattern, bool 
verbose, bool showSystem);
 
 /* \dT */
 extern bool describeTypes(const char *pattern, bool verbose, bool showSystem);
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index 93ff5d0..504d55c 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -174,29 +174,29 @@ slashUsage(unsigned short int pager)
        fprintf(output, "\n");
 
        fprintf(output, _("Query Buffer\n"));
-       fprintf(output, _("  \\e [FILE]              edit the query buffer (or 
file) with external editor\n"));
+       fprintf(output, _("  \\e  [FILE]             edit the query buffer (or 
file) with external editor\n"));
        fprintf(output, _("  \\ef [FUNCNAME]         edit function definition 
with external editor\n"));
        fprintf(output, _("  \\p                     show the contents of the 
query buffer\n"));
        fprintf(output, _("  \\r                     reset (clear) the query 
buffer\n"));
 #ifdef USE_READLINE
-       fprintf(output, _("  \\s [FILE]              display history or save it 
to file\n"));
+       fprintf(output, _("  \\s  [FILE]             display history or save it 
to file\n"));
 #endif
-       fprintf(output, _("  \\w FILE                write query buffer to 
file\n"));
+       fprintf(output, _("  \\w  FILE               write query buffer to 
file\n"));
        fprintf(output, "\n");
 
        fprintf(output, _("Input/Output\n"));
        fprintf(output, _("  \\copy ...              perform SQL COPY with data 
stream to the client host\n"));
-       fprintf(output, _("  \\echo [STRING]         write string to standard 
output\n"));
-       fprintf(output, _("  \\i FILE                execute commands from 
file\n"));
-       fprintf(output, _("  \\o [FILE]              send all query results to 
file or |pipe\n"));
-       fprintf(output, _("  \\qecho [STRING]        write string to query 
output stream (see \\o)\n"));
+       fprintf(output, _("  \\echo  [STRING]        write string to standard 
output\n"));
+       fprintf(output, _("  \\i  FILE               execute commands from 
file\n"));
+       fprintf(output, _("  \\o  [FILE]             send all query results to 
file or |pipe\n"));
+       fprintf(output, _("  \\qecho  [STRING]       write string to query 
output stream (see \\o)\n"));
        fprintf(output, "\n");
 
        fprintf(output, _("Informational\n"));
        fprintf(output, _("  (options: S = show system objects, + = additional 
detail)\n"));
        fprintf(output, _("  \\d[S+]                 list tables, views, and 
sequences\n"));
        fprintf(output, _("  \\d[S+]  NAME           describe table, view, 
sequence, or index\n"));
-       fprintf(output, _("  \\da[S]  [PATTERN]      list aggregate 
functions\n"));
+       fprintf(output, _("  \\da[+]  [PATTERN]      list aggregates\n"));
        fprintf(output, _("  \\db[+]  [PATTERN]      list tablespaces\n"));
        fprintf(output, _("  \\dc[S]  [PATTERN]      list conversions\n"));
        fprintf(output, _("  \\dC     [PATTERN]      list casts\n"));
@@ -205,7 +205,7 @@ slashUsage(unsigned short int pager)
        fprintf(output, _("  \\des[+] [PATTERN]      list foreign servers\n"));
        fprintf(output, _("  \\deu[+] [PATTERN]      list user mappings\n"));
        fprintf(output, _("  \\dew[+] [PATTERN]      list foreign-data 
wrappers\n"));
-       fprintf(output, _("  \\df[S+] [PATTERN]      list functions\n"));
+       fprintf(output, _("  \\df[S+] [PATTERN]      list functions.  Add a, n, 
t, w for aggregate, normal, trigger, window\n"));
        fprintf(output, _("  \\dF[+]  [PATTERN]      list text search 
configurations\n"));
        fprintf(output, _("  \\dFd[+] [PATTERN]      list text search 
dictionaries\n"));
        fprintf(output, _("  \\dFp[+] [PATTERN]      list text search 
parsers\n"));
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to