Hello

attached updated \sf implementation. It is little bit simplyfied with
support a pager and output forwarding. Formating was updated per Tom's
request.

Regards

Pavel Stehule

>
> BTW, the last I looked, \sf+ was using what I thought to be a quite ugly
> and poorly-considered formatting for the line number.  I would suggest
> eight blanks for a header line and "%-7d " as the prefix format for a
> numbered line.  The reason for making sure the prefix is 8 columns rather
> than some other width is to not mess up tab-based formatting of the
> function body.  I would also prefer a lot more visual separation between
> the line number and the code than "%4d " will offer; and as for the
> stars, they're just useless and distracting.
>
>                        regards, tom lane
>
*** ./doc/src/sgml/ref/psql-ref.sgml.orig	2010-08-12 02:40:59.000000000 +0200
--- ./doc/src/sgml/ref/psql-ref.sgml	2010-08-12 15:01:04.339404200 +0200
***************
*** 2100,2105 ****
--- 2100,2131 ----
  
  
        <varlistentry>
+         <term><literal>\sf[+] <optional> <replaceable class="parameter">function_description</> <optional>  <replaceable class="parameter">line_number</> </optional> </optional> </literal></term>
+ 
+         <listitem>
+         <para>
+          This command fetches and shows the definition of the named function,
+          in the form of a <command>CREATE OR REPLACE FUNCTION</> command.
+          If <literal>+</literal> is appended to the command name, then output
+          lines has a line number.
+         </para>
+ 
+         <para>
+          The target function can be specified by name alone, or by name
+          and arguments, for example <literal>foo(integer, text)</>.
+          The argument types must be given if there is more
+          than one function of the same name.
+         </para>
+ 
+         <para>
+         If a line number is specified, <application>psql</application> will
+         show the specified line as first line. Previous lines are skiped.
+         </para>
+         </listitem>
+       </varlistentry>
+ 
+ 
+       <varlistentry>
          <term><literal>\set [ <replaceable class="parameter">name</replaceable> [ <replaceable class="parameter">value</replaceable> [ ... ] ] ]</literal></term>
  
          <listitem>
*** ./src/bin/psql/command.c.orig	2010-08-12 02:40:59.000000000 +0200
--- ./src/bin/psql/command.c	2010-08-12 14:39:22.334403954 +0200
***************
*** 32,37 ****
--- 32,38 ----
  #ifdef USE_SSL
  #include <openssl/ssl.h>
  #endif
+ #include <signal.h>
  
  #include "portability/instr_time.h"
  
***************
*** 46,51 ****
--- 47,53 ----
  #include "input.h"
  #include "large_obj.h"
  #include "mainloop.h"
+ #include "pqsignal.h"
  #include "print.h"
  #include "psqlscan.h"
  #include "settings.h"
***************
*** 1083,1088 ****
--- 1085,1232 ----
  		free(opt0);
  	}
  
+ 	/* \sf = show a function source code */
+ 	else if (strcmp(cmd, "sf") == 0 || strcmp(cmd, "sf+") == 0)
+ 	{
+ 		bool show_lineno;
+ 		int	first_visible_line = -1;
+ 		
+ 		show_lineno = (strcmp(cmd, "sf+") == 0);
+ 		
+ 		if (!query_buf)
+ 		{
+ 			psql_error("no query buffer\n");
+ 			status = PSQL_CMD_ERROR;
+ 		}
+ 		else
+ 		{
+ 			char	*func;
+ 			Oid		foid = InvalidOid;
+ 			
+ 			func = psql_scan_slash_option(scan_state,
+ 									OT_WHOLE_LINE, NULL, true);
+ 			first_visible_line = strip_lineno_from_funcdesc(func);
+ 			if (first_visible_line == 0)
+ 			{
+ 				/* error already reported */
+ 				status = PSQL_CMD_ERROR;
+ 			}
+ 			else if (!func)
+ 			{
+ 				psql_error("missing a function name\n");
+ 				status = PSQL_CMD_ERROR;
+ 			}
+ 			else if (!lookup_function_oid(pset.db, func, &foid))
+ 			{
+ 				/* error already reported */
+ 				status = PSQL_CMD_ERROR;
+ 			}
+ 			else if (!get_create_function_cmd(pset.db, foid, query_buf))
+ 			{
+ 				/* error already reported */
+ 				status = PSQL_CMD_ERROR;
+ 			}
+ 			
+ 			if (func)
+ 				free(func);
+ 			
+ 			if (status != PSQL_CMD_ERROR)
+ 			{
+ 				FILE *output;
+ 				bool	is_pager = false;
+ 				
+ 				/*
+ 				 * Count a lines in function definition - it's used for opening
+ 				 * a pager. Get a output stream - stdout, pager or forwarded output.
+ 				 */
+ 				if (pset.queryFout == stdout)
+ 				{
+ 					int	lc = 0;
+ 					const char *lines = query_buf->data;
+ 					
+ 					while (*lines != '\0')
+ 					{
+ 						lc++;
+ 						/* find start of next line */
+ 						lines = strchr(lines, '\n');
+ 						if (!lines)
+ 							break;
+ 						lines++;
+ 					}
+ 					
+ 					output = PageOutput(lc, pset.popt.topt.pager);
+ 					is_pager = output != stdout;
+ 				}
+ 				else
+ 				{
+ 					/* use a prepared query output, pager isn't activated */
+ 					output = pset.queryFout;
+ 					is_pager = false;
+ 				}
+ 				
+ 				if (first_visible_line > 0 || show_lineno)
+ 				{
+ 					bool	is_header = true;		/* true, when header lines is processed */
+ 					int	lineno = 0;
+ 					char *lines = query_buf->data;
+ 					
+ 					/*
+ 					 * lineno "1" should correspond to the first line of the function
+ 					 * body. We expect that pg_get_functiondef() will emit that on a line
+ 					 * beginning with "AS $function" is real start of the function body.
+ 					 */
+ 					while (*lines != '\0')
+ 					{
+ 						char *eol;
+ 						
+ 						if (is_header && strncmp(lines, "AS $function", 12) == 0)
+ 							is_header = false;
+ 						
+ 						/* increment lineno only for body's lines */
+ 						if (!is_header)
+ 							lineno++;
+ 						/* find a end of current line */
+ 						eol = strchr(lines, '\n');
+ 						/* show a current line, when it is desirable */
+ 						if (first_visible_line == -1 || lineno >= first_visible_line)
+ 						{
+ 							/* disjoin a current line from a next line */
+ 							if (eol != NULL)
+ 								*eol = '\0';
+ 							if (!show_lineno)
+ 								fprintf(output, "%s", lines);
+ 							else if (is_header)
+ 								fprintf(output, "        %s", lines);
+ 							else
+ 								fprintf(output, "%-7d %s", lineno, lines);
+ 							/* print a replaced \n char */
+ 							if (eol)
+ 								fprintf(output, "\n");
+ 						}
+ 						/* leave when there are not a next line */
+ 						if (!eol)
+ 							break;
+ 						/* move to next line */
+ 						lines = ++eol;
+ 					}
+ 				}
+ 				else
+ 				{
+ 					/* just send a function definition to output */
+ 					fprintf(output, "%s", query_buf->data);
+ 				}
+ 				
+ 				if (is_pager)
+ 				{
+ 					pclose(output);
+ #ifndef WIN32
+ 					pqsignal(SIGPIPE, SIG_DFL);
+ #endif
+ 				}
+ 			}
+ 		}
+ 	}
+ 
  	/* \t -- turn off headers and row count */
  	else if (strcmp(cmd, "t") == 0)
  	{
*** ./src/bin/psql/help.c.orig	2010-08-12 02:40:59.000000000 +0200
--- ./src/bin/psql/help.c	2010-08-12 14:53:25.491278641 +0200
***************
*** 162,168 ****
  {
  	FILE	   *output;
  
! 	output = PageOutput(89, pager);
  
  	/* if you add/remove a line here, change the row count above */
  
--- 162,168 ----
  {
  	FILE	   *output;
  
! 	output = PageOutput(90, pager);
  
  	/* if you add/remove a line here, change the row count above */
  
***************
*** 223,228 ****
--- 223,229 ----
  	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, _("  \\sf[+] FUNCNAME [LINE]] show the function definition\n"));
  	fprintf(output, _("  \\l[+]                  list all databases\n"));
  	fprintf(output, _("  \\z      [PATTERN]      same as \\dp\n"));
  	fprintf(output, "\n");
*** ./src/bin/psql/tab-complete.c.orig	2010-07-20 05:54:19.000000000 +0200
--- ./src/bin/psql/tab-complete.c	2010-08-12 14:49:19.490403596 +0200
***************
*** 644,650 ****
  		"\\f", "\\g", "\\h", "\\help", "\\H", "\\i", "\\l",
  		"\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
  		"\\o", "\\p", "\\password", "\\prompt", "\\pset", "\\q", "\\qecho", "\\r",
! 		"\\set", "\\t", "\\T",
  		"\\timing", "\\unset", "\\x", "\\w", "\\z", "\\!", NULL
  	};
  
--- 644,650 ----
  		"\\f", "\\g", "\\h", "\\help", "\\H", "\\i", "\\l",
  		"\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
  		"\\o", "\\p", "\\password", "\\prompt", "\\pset", "\\q", "\\qecho", "\\r",
! 		"\\set", "\\sf", "\\t", "\\T",
  		"\\timing", "\\unset", "\\x", "\\w", "\\z", "\\!", NULL
  	};
  
***************
*** 2501,2506 ****
--- 2501,2508 ----
  
  	else if (strcmp(prev_wd, "\\ef") == 0)
  		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
+ 	else if (strcmp(prev_wd, "\\sf") == 0 || strcmp(prev_wd, "\\sf+") == 0)
+ 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
  
  	else if (strcmp(prev_wd, "\\encoding") == 0)
  		COMPLETE_WITH_QUERY(Query_for_list_of_encodings);
-- 
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