diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index b39466d..626eadc 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -396,6 +396,9 @@ exec_command(const char *cmd, case 'u': success = describeRoles(pattern, show_verbose); break; + case 'w': + success = describeWindowingFunctions(pattern, show_system); + break; case 'F': /* text search subsystem */ switch (cmd[2]) { diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index cc88984..c718267 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -286,6 +286,9 @@ describeFunctions(const char *pattern, bool verbose, bool showSystem) appendPQExpBuffer(&buf, " AND n.nspname <> 'pg_catalog'\n" " AND n.nspname <> 'information_schema'\n"); + if (pset.sversion >= 80400) + appendPQExpBuffer(&buf, " AND NOT p.proiswindow\n"); + processSQLNamePattern(pset.db, &buf, pattern, true, false, "n.nspname", "p.proname", NULL, "pg_catalog.pg_function_is_visible(p.oid)"); @@ -3069,6 +3072,60 @@ listUserMappings(const char *pattern, bool verbose) return true; } +bool +describeWindowingFunctions(const char *pattern, bool showSystem) +{ + PQExpBufferData buf; + PGresult *res; + printQueryOpt myopt = pset.popt; + + if (pset.sversion < 80400) + { + fprintf(stderr, _("The server (version %d.%d) does not support windowing functions.\n"), + pset.sversion / 10000, (pset.sversion / 100) % 100); + return true; + } + + initPQExpBuffer(&buf); + + printfPQExpBuffer(&buf, + "SELECT n.nspname as \"%s\",\n" + " p.proname as \"%s\",\n" + " pg_catalog.pg_get_function_result(p.oid) as \"%s\",\n" + " pg_catalog.pg_get_function_arguments(p.oid) as \"%s\"" + "\nFROM pg_catalog.pg_proc p" + "\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n" + "WHERE p.proiswindow\n", + gettext_noop("Schema"), + gettext_noop("Name"), + gettext_noop("Result data type"), + gettext_noop("Argument data types")); + + 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); + termPQExpBuffer(&buf); + if (!res) + return false; + + myopt.nullPrint = NULL; + myopt.title = _("List of windowing functions"); + myopt.translate_header = true; + + printQuery(res, &myopt, pset.queryFout, pset.logfile); + + PQclear(res); + return true; +} + /* * printACLColumn * diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h index 57e5c7b..3c6f2b1 100644 --- a/src/bin/psql/describe.h +++ b/src/bin/psql/describe.h @@ -75,5 +75,8 @@ extern bool listForeignServers(const char *pattern, bool verbose); /* \deu */ extern bool listUserMappings(const char *pattern, bool verbose); +/* \dw */ +extern bool describeWindowingFunctions(const char *pattern, bool showSystem); + #endif /* DESCRIBE_H */ diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c index 389feb0..d647069 100644 --- a/src/bin/psql/help.c +++ b/src/bin/psql/help.c @@ -221,6 +221,7 @@ slashUsage(unsigned short int pager) fprintf(output, _(" \\dT[S+] [PATTERN] list data types\n")); fprintf(output, _(" \\du [PATTERN] list roles (users)\n")); fprintf(output, _(" \\dv[S+] [PATTERN] list views\n")); + fprintf(output, _(" \\dw[S] [PATTERN] list windowing functions\n")); fprintf(output, _(" \\l[+] list all databases\n")); fprintf(output, _(" \\z [PATTERN] same as \\dp\n")); fprintf(output, "\n"); diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index 5602007..9f489c7 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -347,6 +347,21 @@ static const SchemaQuery Query_for_list_of_views = { }; +static const SchemaQuery Query_for_list_of_windowing_functions = { + /* catname */ + "pg_catalog.pg_proc p", + /* selcondition */ + "p.proiswindow", + /* viscondition */ + "pg_catalog.pg_function_is_visible(p.oid)", + /* namespace */ + "p.pronamespace", + /* result */ + "pg_catalog.quote_ident(p.proname)", + /* qualresult */ + NULL +}; + /* * Queries to get lists of names of various kinds of things, possibly * restricted to names matching a partially entered name. In these queries, @@ -629,7 +644,7 @@ psql_completion(char *text, int start, int end) "\\a", "\\connect", "\\C", "\\cd", "\\copy", "\\copyright", "\\d", "\\da", "\\db", "\\dc", "\\dC", "\\dd", "\\dD", "\\des", "\\deu", "\\dew", "\\df", "\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl", - "\\dn", "\\do", "\\dp", "\\ds", "\\dS", "\\dt", "\\dT", "\\dv", "\\du", + "\\dn", "\\do", "\\dp", "\\ds", "\\dS", "\\dt", "\\dT", "\\dv", "\\du", "\\dw", "\\e", "\\echo", "\\encoding", "\\f", "\\g", "\\h", "\\help", "\\H", "\\i", "\\l", "\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink", @@ -2213,6 +2228,8 @@ psql_completion(char *text, int start, int end) COMPLETE_WITH_QUERY(Query_for_list_of_roles); else if (strncmp(prev_wd, "\\dv", strlen("\\dv")) == 0) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL); + else if (strncmp(prev_wd, "\\dw", strlen("\\dw")) == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_windowing_functions, NULL); /* must be at end of \d list */ else if (strncmp(prev_wd, "\\d", strlen("\\d")) == 0)