Peter Eisentraut <peter.eisentr...@2ndquadrant.com> writes: > On 7/12/16 7:11 PM, Stephen Frost wrote: >> I'm curious how it's useful and in what way \sf does not accomplish what >> you use \df+ for.
> One main use is to see multiple related functions next to each other and > compare their source code. But also because one is used to \df and > wants to see everything there and not in a different format like \sf. Well, how about my suggestion of moving source code to a footer? I had just been experimenting to see how painful that would be, and it doesn't seem awful --- see attached. regards, tom lane
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 27be102..f5dfd83 100644 *** a/src/bin/psql/describe.c --- b/src/bin/psql/describe.c *************** describeFunctions(const char *functypes, *** 294,308 **** bool showNormal = strchr(functypes, 'n') != NULL; bool showTrigger = strchr(functypes, 't') != NULL; bool showWindow = strchr(functypes, 'w') != NULL; bool have_where; PQExpBufferData buf; PGresult *res; printQueryOpt myopt = pset.popt; static const bool translate_columns[] = {false, false, false, false, true, true, true, false, true, false, false, false, false}; - /* No "Parallel" column before 9.6 */ - static const bool translate_columns_pre_96[] = {false, false, false, false, true, true, false, true, false, false, false, false}; - if (strlen(functypes) != strspn(functypes, "antwS+")) { psql_error("\\df only takes [antwS+] as options\n"); --- 294,316 ---- bool showNormal = strchr(functypes, 'n') != NULL; bool showTrigger = strchr(functypes, 't') != NULL; bool showWindow = strchr(functypes, 'w') != NULL; + bool have_parallel; bool have_where; PQExpBufferData buf; PGresult *res; + printTableContent cont; printQueryOpt myopt = pset.popt; + int nfields, + r, + c; + const int schema_col = 0; + const int proname_col = 1; + const int proargs_col = 3; + const int parallel_col = 6; + const int lanname_col = 10; + const int prosrc_col = 11; static const bool translate_columns[] = {false, false, false, false, true, true, true, false, true, false, false, false, false}; if (strlen(functypes) != strspn(functypes, "antwS+")) { psql_error("\\df only takes [antwS+] as options\n"); *************** describeFunctions(const char *functypes, *** 323,328 **** --- 331,344 ---- showWindow = true; } + /* + * proparallel only exists in server versions >= 9.6. Before that, we + * retrieve a null "parallel" column so as to keep column numbering + * consistent in the query result, and then skip adding that column to the + * printed table. + */ + have_parallel = (pset.sversion >= 90600); + initPQExpBuffer(&buf); printfPQExpBuffer(&buf, *************** describeFunctions(const char *functypes, *** 424,430 **** gettext_noop("stable"), gettext_noop("volatile"), gettext_noop("Volatility")); ! if (pset.sversion >= 90600) appendPQExpBuffer(&buf, ",\n CASE\n" " WHEN p.proparallel = 'r' THEN '%s'\n" --- 440,446 ---- gettext_noop("stable"), gettext_noop("volatile"), gettext_noop("Volatility")); ! if (have_parallel) appendPQExpBuffer(&buf, ",\n CASE\n" " WHEN p.proparallel = 'r' THEN '%s'\n" *************** describeFunctions(const char *functypes, *** 435,440 **** --- 451,459 ---- gettext_noop("safe"), gettext_noop("unsafe"), gettext_noop("Parallel")); + else + appendPQExpBufferStr(&buf, + ",\n NULL as \"Parallel\""); appendPQExpBuffer(&buf, ",\n pg_catalog.pg_get_userbyid(p.proowner) as \"%s\"" ",\n CASE WHEN prosecdef THEN '%s' ELSE '%s' END AS \"%s\"", *************** describeFunctions(const char *functypes, *** 449,455 **** ",\n p.prosrc as \"%s\"" ",\n pg_catalog.obj_description(p.oid, 'pg_proc') as \"%s\"", gettext_noop("Language"), ! gettext_noop("Source code"), gettext_noop("Description")); } --- 468,474 ---- ",\n p.prosrc as \"%s\"" ",\n pg_catalog.obj_description(p.oid, 'pg_proc') as \"%s\"", gettext_noop("Language"), ! gettext_noop("Internal name"), gettext_noop("Description")); } *************** describeFunctions(const char *functypes, *** 543,569 **** appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;"); res = PSQLexec(buf.data); - termPQExpBuffer(&buf); if (!res) return false; ! myopt.nullPrint = NULL; ! myopt.title = _("List of functions"); ! myopt.translate_header = true; ! if (pset.sversion >= 90600) { ! myopt.translate_columns = translate_columns; ! myopt.n_translate_columns = lengthof(translate_columns); } ! else { ! myopt.translate_columns = translate_columns_pre_96; ! myopt.n_translate_columns = lengthof(translate_columns_pre_96); } ! printQuery(res, &myopt, pset.queryFout, false, pset.logfile); PQclear(res); return true; } --- 562,634 ---- appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;"); res = PSQLexec(buf.data); if (!res) + { + termPQExpBuffer(&buf); return false; + } ! nfields = PQnfields(res); ! Assert(lengthof(translate_columns) >= nfields); ! ! printTableInit(&cont, &myopt.topt, _("List of functions"), ! (have_parallel || !verbose) ? nfields : nfields - 1, ! PQntuples(res)); ! ! for (c = 0; c < nfields; c++) { ! if (c == parallel_col && !have_parallel) ! continue; ! printTableAddHeader(&cont, PQfname(res, c), true, ! column_type_alignment(PQftype(res, c))); } ! ! /* set cells */ ! for (r = 0; r < cont.nrows; r++) { ! for (c = 0; c < nfields; c++) ! { ! char *cell; ! ! if (c == parallel_col && !have_parallel) ! continue; ! ! if (PQgetisnull(res, r, c)) ! cell = ""; ! else ! cell = PQgetvalue(res, r, c); ! ! if (c == prosrc_col) ! { ! const char *lanname = PQgetvalue(res, r, lanname_col); ! ! if (strcmp(lanname, "internal") == 0 || ! strcmp(lanname, "c") == 0) ! /* keep prosrc in the "Internal name" column */ ; ! else ! { ! /* put prosrc in a footer, instead */ ! printfPQExpBuffer(&buf, ! _("Source code of function %s.%s(%s):"), ! PQgetvalue(res, r, schema_col), ! PQgetvalue(res, r, proname_col), ! PQgetvalue(res, r, proargs_col)); ! printTableAddFooter(&cont, buf.data); ! printTableAddFooter(&cont, cell); ! cell = ""; ! } ! } ! ! printTableAddCell(&cont, cell, translate_columns[c], false); ! } } ! printTable(&cont, pset.queryFout, false, pset.logfile); ! printTableCleanup(&cont); PQclear(res); + termPQExpBuffer(&buf); + return true; }
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers