Peter Eisentraut <[email protected]> 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 ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers