88 *
99 * Copyright (c) 2000-2009, PostgreSQL Global Development Group
1010 *
11- * $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.208 2009/04/08 22:29:30 tgl Exp $
11+ * $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.209 2009/04/21 15:49:06 momjian Exp $
1212 */
1313#include "postgres_fe.h"
1414
@@ -183,15 +183,43 @@ describeTablespaces(const char *pattern, bool verbose)
183183
184184
185185/* \df
186- * Takes an optional regexp to select particular functions
186+ * Takes an optional regexp to select particular functions.
187+ *
188+ * As with \d, you can specify the kinds of functions you want:
189+ *
190+ * a for aggregates
191+ * n for normal
192+ * t for trigger
193+ * w for window
194+ *
195+ * and you can mix and match these in any order.
187196 */
188197bool
189- describeFunctions (const char * pattern , bool verbose , bool showSystem )
198+ describeFunctions (const char * functypes , const char * pattern , bool verbose , bool showSystem )
190199{
200+ bool showAggregate = strchr (functypes , 'a' ) != NULL ;
201+ bool showNormal = strchr (functypes , 'n' ) != NULL ;
202+ bool showTrigger = strchr (functypes , 't' ) != NULL ;
203+ bool showWindow = strchr (functypes , 'w' ) != NULL ;
204+
191205 PQExpBufferData buf ;
192206 PGresult * res ;
193207 printQueryOpt myopt = pset .popt ;
194208
209+ if (showWindow && pset .sversion < 80400 )
210+ {
211+ fprintf (stderr , _ ("\\df does not take a \"w\" decorator in %d.%d.\n" ),
212+ pset .sversion / 10000 , (pset .sversion / 100 ) % 100 );
213+ return true;
214+ }
215+
216+ if (!showAggregate && !showNormal && !showTrigger && !showWindow )
217+ {
218+ showAggregate = showNormal = showTrigger = true;
219+ if (pset .sversion >= 80400 )
220+ showWindow = true;
221+ }
222+
195223 initPQExpBuffer (& buf );
196224
197225 printfPQExpBuffer (& buf ,
@@ -203,9 +231,21 @@ describeFunctions(const char *pattern, bool verbose, bool showSystem)
203231 if (pset .sversion >= 80400 )
204232 appendPQExpBuffer (& buf ,
205233 " pg_catalog.pg_get_function_result(p.oid) as \"%s\",\n"
206- " pg_catalog.pg_get_function_arguments(p.oid) as \"%s\"" ,
234+ " pg_catalog.pg_get_function_arguments(p.oid) as \"%s\",\n"
235+ " CASE\n"
236+ " WHEN p.proisagg THEN '%s'\n"
237+ " WHEN p.proiswindow THEN '%s'\n"
238+ " WHEN pg_catalog.pg_get_function_result(p.oid) = 'trigger' THEN '%s'\n"
239+ " ELSE '%s'\n"
240+ "END as \"%s\"" ,
207241 gettext_noop ("Result data type" ),
208- gettext_noop ("Argument data types" ));
242+ gettext_noop ("Argument data types" ),
243+ /* translator: "agg" is short for "aggregate" */
244+ gettext_noop ("agg" ),
245+ gettext_noop ("window" ),
246+ gettext_noop ("trigger" ),
247+ gettext_noop ("normal" ),
248+ gettext_noop ("Type" ));
209249 else if (pset .sversion >= 80100 )
210250 appendPQExpBuffer (& buf ,
211251 " CASE WHEN p.proretset THEN 'SETOF ' ELSE '' END ||\n"
@@ -238,16 +278,36 @@ describeFunctions(const char *pattern, bool verbose, bool showSystem)
238278 " FROM\n"
239279 " pg_catalog.generate_series(0, pg_catalog.array_upper(p.proargtypes, 1)) AS s(i)\n"
240280 " ), ', ')\n"
281+ " END AS \"%s\",\n"
282+ " CASE\n"
283+ " WHEN p.proisagg THEN '%s'\n"
284+ " WHEN 'trigger' = pg_catalog.format_type(p.prorettype, NULL) THEN '%s'\n"
285+ " ELSE '%s'\n"
241286 " END AS \"%s\"" ,
242287 gettext_noop ("Result data type" ),
243- gettext_noop ("Argument data types" ));
288+ gettext_noop ("Argument data types" ),
289+ /* translator: "agg" is short for "aggregate" */
290+ gettext_noop ("agg" ),
291+ gettext_noop ("trigger" ),
292+ gettext_noop ("normal" ),
293+ gettext_noop ("Type" ));
244294 else
245295 appendPQExpBuffer (& buf ,
246296 " CASE WHEN p.proretset THEN 'SETOF ' ELSE '' END ||\n"
247297 " pg_catalog.format_type(p.prorettype, NULL) as \"%s\",\n"
248- " pg_catalog.oidvectortypes(p.proargtypes) as \"%s\"" ,
298+ " pg_catalog.oidvectortypes(p.proargtypes) as \"%s\",\n"
299+ " CASE\n"
300+ " WHEN p.proisagg THEN '%s'\n"
301+ " WHEN 'trigger' = pg_catalog.format_type(p.prorettype, NULL) THEN '%s'\n"
302+ " ELSE '%s'\n"
303+ " END AS \"%s\"" ,
249304 gettext_noop ("Result data type" ),
250- gettext_noop ("Argument data types" ));
305+ gettext_noop ("Argument data types" ),
306+ /* translator: "agg" is short for "aggregate" */
307+ gettext_noop ("agg" ),
308+ gettext_noop ("trigger" ),
309+ gettext_noop ("normal" ),
310+ gettext_noop ("Type" ));
251311
252312 if (verbose )
253313 appendPQExpBuffer (& buf ,
@@ -274,16 +334,63 @@ describeFunctions(const char *pattern, bool verbose, bool showSystem)
274334 appendPQExpBuffer (& buf ,
275335 " LEFT JOIN pg_catalog.pg_language l ON l.oid = p.prolang\n" );
276336
277- appendPQExpBuffer (& buf , "WHERE NOT p.proisagg\n" );
337+ processSQLNamePattern (pset .db , & buf , pattern , false, true,
338+ "n.nspname" , "p.proname" , NULL ,
339+ "pg_catalog.pg_function_is_visible(p.oid)" );
340+
341+ if (showNormal && showAggregate && showTrigger && showWindow )
342+ /* Do nothing */ ;
343+ else if (showNormal )
344+ {
345+ if (!showWindow && pset .sversion >= 80400 )
346+ appendPQExpBuffer (& buf , " AND NOT p.proiswindow\n" );
347+ if (!showAggregate )
348+ appendPQExpBuffer (& buf , " AND NOT p.proisagg\n" );
349+ if (!showTrigger )
350+ {
351+ if (pset .sversion >= 80400 )
352+ appendPQExpBuffer (& buf ,
353+ " AND pg_catalog.pg_get_function_result(p.oid) <> 'trigger'\n" );
354+ else
355+ appendPQExpBuffer (& buf ,
356+ " AND pg_catalog.format_type(p.prorettype, NULL) <> 'trigger'\n" );
357+ }
358+ }
359+ else
360+ {
361+ bool needs_or = false;
362+
363+ appendPQExpBuffer (& buf , " AND (\n " );
364+ if (showAggregate )
365+ {
366+ appendPQExpBuffer (& buf ,"p.proisagg\n" );
367+ needs_or = true;
368+ }
369+ if (showTrigger )
370+ {
371+ if (needs_or )
372+ appendPQExpBuffer (& buf , " OR " );
373+ if (pset .sversion >= 80400 )
374+ appendPQExpBuffer (& buf ,
375+ "pg_catalog.pg_get_function_result(p.oid) = 'trigger'\n" );
376+ else
377+ appendPQExpBuffer (& buf ,
378+ "'trigger' <> pg_catalog.format_type(p.prorettype, NULL)\n" );
379+ needs_or = true;
380+ }
381+ if (showWindow )
382+ {
383+ if (needs_or )
384+ appendPQExpBuffer (& buf , " OR " );
385+ appendPQExpBuffer (& buf , "p.proiswindow\n" );
386+ }
387+ appendPQExpBuffer (& buf , " )\n" );
388+ }
278389
279390 if (!showSystem && !pattern )
280391 appendPQExpBuffer (& buf , " AND n.nspname <> 'pg_catalog'\n"
281392 " AND n.nspname <> 'information_schema'\n" );
282393
283- processSQLNamePattern (pset .db , & buf , pattern , true, false,
284- "n.nspname" , "p.proname" , NULL ,
285- "pg_catalog.pg_function_is_visible(p.oid)" );
286-
287394 appendPQExpBuffer (& buf , "ORDER BY 1, 2, 4;" );
288395
289396 res = PSQLexec (buf .data , false);
0 commit comments