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

Reply via email to