Hello

2010/8/8 Tom Lane <t...@sss.pgh.pa.us>:
> Pavel Stehule <pavel.steh...@gmail.com> writes:
>> updated patch attached
>
> What exactly is the point of the \sf command?  It seems like quite a lot
> of added code for a feature that nobody has requested, and whose
> definition is about as ad-hoc as could be.  Personally I'd much sooner
> use \ef for looking at a function definition.  I think if \sf had been
> submitted as a separate patch, rather than being snuck in with a feature
> people do want, it wouldn't be accepted.
>
> The current patch doesn't even compile warning-free :-(
>
> command.c: In function `exec_command':
> command.c:559: warning: `lineno' might be used uninitialized in this function
> command.c: In function `editFile':
> command.c:1729: warning: `editor_lineno_switch' might be used uninitialized 
> in this function
>

This warnings depends on gcc version, probably :(. On new fedora I see
nothing. So updated patch attached - these variables are initialised
in declaration now.

Regards

Pavel Stehule

>
>                        regards, tom lane
>
*** ./doc/src/sgml/ref/psql-ref.sgml.orig	2010-08-03 09:00:48.384710383 +0200
--- ./doc/src/sgml/ref/psql-ref.sgml	2010-08-03 10:44:57.312835131 +0200
***************
*** 1339,1345 ****
  
  
        <varlistentry>
!         <term><literal>\edit</literal> (or <literal>\e</literal>) <literal><optional> <replaceable class="parameter">filename</replaceable> </optional></literal></term>
  
          <listitem>
          <para>
--- 1339,1345 ----
  
  
        <varlistentry>
!         <term><literal>\edit</literal> (or <literal>\e</literal>) <literal><optional> <replaceable class="parameter">filename</replaceable> </optional> <optional> linenumber </optional></literal></term>
  
          <listitem>
          <para>
***************
*** 1369,1380 ****
          systems, <filename>notepad.exe</filename> on Windows systems.
          </para>
          </tip>
          </listitem>
        </varlistentry>
  
  
        <varlistentry>
!         <term><literal>\ef <optional> <replaceable class="parameter">function_description</replaceable> </optional></literal></term>
  
          <listitem>
          <para>
--- 1369,1387 ----
          systems, <filename>notepad.exe</filename> on Windows systems.
          </para>
          </tip>
+ 
+         <para>
+         If <replaceable class="parameter">linenumber</replaceable> is
+         specified, then cursor is moved on this line after start of 
+         editor (The psql's variable <varname>EDITOR_LINENUMBER_SWITCH</varname>
+         have to be filled).
+         </para>
          </listitem>
        </varlistentry>
  
  
        <varlistentry>
!         <term><literal>\ef <optional> <replaceable class="parameter">function_description</replaceable> </optional> <optional> linenumber </optional> </literal></term>
  
          <listitem>
          <para>
***************
*** 1397,1402 ****
--- 1404,1417 ----
           If no function is specified, a blank <command>CREATE FUNCTION</>
           template is presented for editing.
          </para>
+ 
+         <para>
+         If <replaceable class="parameter">linenumber</replaceable> is
+         specified, then cursor is moved on this line after start of 
+         editor. It count lines from start of function body, not from
+         start of text (The psql's variable <varname>EDITOR_LINENUMBER_SWITCH</varname>
+         have to be filled).
+         </para>
          </listitem>
        </varlistentry>
  
***************
*** 2116,2121 ****
--- 2131,2148 ----
  
  
        <varlistentry>
+         <term><literal>\sf[+] <replaceable class="parameter">function_description</replaceable> <optional> linenumber </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 the form <literal>\sf+</literal> is used, then lines are numbered.
+         </para>
+         </listitem>
+       </varlistentry>
+ 
+       <varlistentry>
          <term><literal>\t</literal></term>
          <listitem>
          <para>
***************
*** 2123,2128 ****
--- 2150,2161 ----
          footer. This command is equivalent to <literal>\pset
          tuples_only</literal> and is provided for convenience.
          </para>
+ 
+         <para>
+         If <replaceable class="parameter">linenumber</replaceable> is
+         specified, then cursor is moved on this line after start of 
+         editor.
+         </para>
          </listitem>
        </varlistentry>
  
***************
*** 2459,2464 ****
--- 2492,2511 ----
        </varlistentry>
  
        <varlistentry>
+         <term><varname>EDITOR_LINENUMBER_SWITCH</varname></term>
+         <listitem>
+         <para>
+         Option used for navigation (go to line command) in external
+         editor. When it isn't defined, then you cannot to specify
+         line numbers for <command>\edit</command> and <command>\ef</command>
+         commands. On unix platforms are possible to use a '<option>+</option>'
+         or '<option>--line </option>'. The space after <literal>line</literal> 
+         is required.
+         </para>
+         </listitem>
+       </varlistentry>
+ 
+       <varlistentry>
          <term><varname>ENCODING</varname></term>
          <listitem>
          <para>
***************
*** 3065,3070 ****
--- 3112,3118 ----
      </listitem>
     </varlistentry>
  
+ 
     <varlistentry>
      <term><envar>SHELL</envar></term>
  
*** ./src/bin/psql/command.c.orig	2010-08-03 09:00:48.386710435 +0200
--- ./src/bin/psql/command.c	2010-08-09 08:54:00.466222215 +0200
***************
*** 46,54 ****
--- 46,56 ----
  #include "input.h"
  #include "large_obj.h"
  #include "mainloop.h"
+ #include "pqsignal.h"
  #include "print.h"
  #include "psqlscan.h"
  #include "settings.h"
+ #include <signal.h>
  #include "variables.h"
  
  
***************
*** 57,63 ****
  			 PsqlScanState scan_state,
  			 PQExpBuffer query_buf);
  static bool do_edit(const char *filename_arg, PQExpBuffer query_buf,
! 		bool *edited);
  static bool do_connect(char *dbname, char *user, char *host, char *port);
  static bool do_shell(const char *command);
  static bool lookup_function_oid(PGconn *conn, const char *desc, Oid *foid);
--- 59,65 ----
  			 PsqlScanState scan_state,
  			 PQExpBuffer query_buf);
  static bool do_edit(const char *filename_arg, PQExpBuffer query_buf,
! 			 int lineno, bool *edited);
  static bool do_connect(char *dbname, char *user, char *host, char *port);
  static bool do_shell(const char *command);
  static bool lookup_function_oid(PGconn *conn, const char *desc, Oid *foid);
***************
*** 66,71 ****
--- 68,76 ----
  
  static void printSSLInfo(void);
  
+ static int extract_lineno_from_funcdesc(char *func, backslashResult *status);
+ static char *get_functiondef_dollarquote_tag(char *row);
+ 
  #ifdef WIN32
  static void checkWin32Codepage(void);
  #endif
***************
*** 513,528 ****
  		else
  		{
  			char	   *fname;
! 
  			fname = psql_scan_slash_option(scan_state,
! 										   OT_NORMAL, NULL, true);
! 			expand_tilde(&fname);
  			if (fname)
! 				canonicalize_path(fname);
! 			if (do_edit(fname, query_buf, NULL))
! 				status = PSQL_CMD_NEWEDIT;
! 			else
! 				status = PSQL_CMD_ERROR;
  			free(fname);
  		}
  	}
--- 518,554 ----
  		else
  		{
  			char	   *fname;
! 			char		*ln;
! 			int  lineno = -1;
! 			
  			fname = psql_scan_slash_option(scan_state,
! 								   OT_NORMAL, NULL, true);
! 			
! 			/* try to get lineno */
  			if (fname)
! 			{
! 				ln = psql_scan_slash_option(scan_state,
! 									   OT_NORMAL, NULL, true);
! 				if (ln)
! 				{
! 					lineno = atoi(ln);
! 					if (lineno < 1)
! 					{
! 						psql_error("invalid line number\n");
! 						status = PSQL_CMD_ERROR;
! 					}
! 				}
! 			}
! 			if (status != PSQL_CMD_ERROR)
! 			{
! 				expand_tilde(&fname);
! 				if (fname)
! 					canonicalize_path(fname);
! 				if (do_edit(fname, query_buf, lineno, NULL))
! 					status = PSQL_CMD_NEWEDIT;
! 				else
! 					status = PSQL_CMD_ERROR;
! 			}
  			free(fname);
  		}
  	}
***************
*** 533,538 ****
--- 559,566 ----
  	 */
  	else if (strcmp(cmd, "ef") == 0)
  	{
+ 		int	lineno = -1;		/* be compiler quiet */
+ 	
  		if (!query_buf)
  		{
  			psql_error("no query buffer\n");
***************
*** 545,580 ****
  
  			func = psql_scan_slash_option(scan_state,
  										  OT_WHOLE_LINE, NULL, true);
! 			if (!func)
! 			{
! 				/* set up an empty command to fill in */
! 				printfPQExpBuffer(query_buf,
! 								  "CREATE FUNCTION ( )\n"
! 								  " RETURNS \n"
! 								  " LANGUAGE \n"
! 								  " -- common options:  IMMUTABLE  STABLE  STRICT  SECURITY DEFINER\n"
! 								  "AS $function$\n"
! 								  "\n$function$\n");
! 			}
! 			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)
  		{
  			bool		edited = false;
  
! 			if (!do_edit(0, query_buf, &edited))
  				status = PSQL_CMD_ERROR;
  			else if (!edited)
  				puts(_("No changes"));
--- 573,615 ----
  
  			func = psql_scan_slash_option(scan_state,
  										  OT_WHOLE_LINE, NULL, true);
! 			lineno = extract_lineno_from_funcdesc(func, &status);
! 			
! 			if (status != PSQL_CMD_ERROR)
  			{
! 				if (!func)
! 				{
! 					/* set up an empty command to fill in */
! 					printfPQExpBuffer(query_buf,
! 									  "CREATE FUNCTION ( )\n"
! 									  " RETURNS \n"
! 									  " LANGUAGE \n"
! 									  " -- common options:  IMMUTABLE  STABLE  STRICT  SECURITY DEFINER\n"
! 									  "AS $function$\n"
! 									  "\n$function$\n");
! 				}
! 				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)
  		{
  			bool		edited = false;
  
! 			if (!do_edit(0, query_buf, lineno, &edited))
  				status = PSQL_CMD_ERROR;
  			else if (!edited)
  				puts(_("No changes"));
***************
*** 969,974 ****
--- 1004,1152 ----
  		free(fname);
  	}
  
+ 	/*
+ 	 * \sf -- show the named function
+ 	 */
+ 	else if (strcmp(cmd, "sf") == 0 || strcmp(cmd, "sf+") == 0)
+ 	{
+ 		int	first_visible_row = -1;
+ 		bool	with_lno;
+ 		
+ 		with_lno = (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_row = extract_lineno_from_funcdesc(func, &status);
+ 			
+ 			if (status != PSQL_CMD_ERROR)
+ 			{
+ 				if (!func)
+ 				{
+ 					/* show error for empty command */
+ 					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)
+ 		{
+ 			int	lineno = 0;
+ 			char	*row;
+ 			char	   *dqtag = NULL;
+ 			bool	is_header = true;
+ 			bool	is_body = false;
+ 			bool	is_footer = false;
+ 			char	  *end_of_line;
+ 			int	lines;
+ 			FILE	   *output;
+ 			
+ 			
+ 			/* get number of lines of functiondef - used for possible using a pager */
+ 			row = query_buf->data;
+ 			lines = 0;
+ 			while (*row)
+ 			{
+ 				lines++;
+ 				end_of_line = strchr(row, '\n');
+ 				if (end_of_line)
+ 					row = end_of_line + 1;
+ 				else
+ 					break;
+ 			}
+ 			
+ 			output = PageOutput(lines, pset.popt.topt.pager);
+ 
+ 			row = query_buf->data;
+ 			while (*row)
+ 			{
+ 				/* find next end of line */
+ 				end_of_line = strchr(row, '\n');
+ 				if (end_of_line)
+ 					*end_of_line = '\0';
+ 				
+ 				if (is_header)
+ 				{
+ 					/* detect end of header */
+ 					dqtag = get_functiondef_dollarquote_tag(row);
+ 					if (dqtag)
+ 					{
+ 						is_header = false;
+ 						is_body = true;
+ 						lineno = 1;
+ 					}
+ 				}
+ 				else if (is_body)
+ 				{
+ 					lineno++;
+ 					if (strcmp(row, dqtag) == 0)
+ 					{
+ 						is_body = false;
+ 						is_footer = true;
+ 					}
+ 				}
+ 				
+ 				/* can we show rows? */
+ 				if (first_visible_row < 0 || (first_visible_row <= lineno))
+ 				{
+ 					if (with_lno)
+ 					{
+ 						if (is_header || is_footer)
+ 							fprintf(output, "**** %s", row);
+ 						else 
+ 							fprintf(output, "%4d %s", lineno, row);
+ 					}
+ 					else
+ 						fprintf(output, "%s", row);
+ 					
+ 					/* return back replaced "\n" */
+ 					if (end_of_line)
+ 						fprintf(output, "\n");
+ 				}
+ 				
+ 				if (end_of_line)
+ 					row = end_of_line + 1;
+ 				else
+ 					break;
+ 			}
+ 			
+ 			/* function pg_get_functiondef uses dollar quoted strings always */
+ 			psql_assert(dqtag != NULL);
+ 			free(dqtag);
+ 			
+ 			if (output != stdout)
+ 			{
+ 				pclose(output);
+ #ifndef WIN32
+ 				pqsignal(SIGPIPE, SIG_DFL);
+ #endif
+ 			}
+ 		}
+ 	}
+ 
  	/* \set -- generalized set variable/option command */
  	else if (strcmp(cmd, "set") == 0)
  	{
***************
*** 1548,1558 ****
   * If you do not specify a filename, the current query buffer will be copied
   * into a temporary one.
   */
- 
  static bool
! editFile(const char *fname)
  {
  	const char *editorName;
  	char	   *sys;
  	int			result;
  
--- 1726,1736 ----
   * If you do not specify a filename, the current query buffer will be copied
   * into a temporary one.
   */
  static bool
! editFile(const char *fname, int lineno)
  {
  	const char *editorName;
+ 	const char *editor_lineno_switch = NULL;	/* be compiler quiet */
  	char	   *sys;
  	int			result;
  
***************
*** 1566,1572 ****
  		editorName = getenv("VISUAL");
  	if (!editorName)
  		editorName = DEFAULT_EDITOR;
! 
  	/*
  	 * On Unix the EDITOR value should *not* be quoted, since it might include
  	 * switches, eg, EDITOR="pico -t"; it's up to the user to put quotes in it
--- 1744,1761 ----
  		editorName = getenv("VISUAL");
  	if (!editorName)
  		editorName = DEFAULT_EDITOR;
! 	
! 	/* Find a EDITOR_LINENUMBER_SWITCH when lineno is used */
! 	if (lineno >= 1)
! 	{
! 		editor_lineno_switch = GetVariable(pset.vars, "EDITOR_LINENUMBER_SWITCH");
! 		if (!editor_lineno_switch)
! 		{
! 			psql_error("EDITOR_LINENUMBER_SWITCH variable is not set\n");
! 			return false;
! 		}
! 	}
! 	
  	/*
  	 * On Unix the EDITOR value should *not* be quoted, since it might include
  	 * switches, eg, EDITOR="pico -t"; it's up to the user to put quotes in it
***************
*** 1574,1584 ****
  	 * severe brain damage in their command shell plus the fact that standard
  	 * program paths include spaces.
  	 */
! 	sys = pg_malloc(strlen(editorName) + strlen(fname) + 10 + 1);
  #ifndef WIN32
! 	sprintf(sys, "exec %s '%s'", editorName, fname);
  #else
! 	sprintf(sys, SYSTEMQUOTE "\"%s\" \"%s\"" SYSTEMQUOTE, editorName, fname);
  #endif
  	result = system(sys);
  	if (result == -1)
--- 1763,1795 ----
  	 * severe brain damage in their command shell plus the fact that standard
  	 * program paths include spaces.
  	 */
! 	if (lineno >= 1)
! 		/*
! 		 * allocate sufficient memory for command line content and
! 		 * increase it about space for editor_lineno_switch and lineno 
! 		 * (signed int ~ 10 digits) and one space more.
! 		 */
! 		sys = pg_malloc(strlen(editorName) + strlen(fname) + 10 
! 				    + strlen(editor_lineno_switch) + 10 + 1 + 1);
! 	
! 	else
! 		/* allocate sufficient memory for command line content */
! 		sys = pg_malloc(strlen(editorName) + strlen(fname) + 10 + 1);
! 	
  #ifndef WIN32
! 	if (lineno > 0)
! 		sprintf(sys, "exec %s %s%d '%s'", editorName, editor_lineno_switch, lineno, fname);
! 	else
! 		sprintf(sys, "exec %s '%s'", editorName, fname);
  #else
! 	if (lineno > 0)
! 		sprintf(sys, SYSTEMQUOTE "\"%s\" %s%d \"%s\"" SYSTEMQUOTE, 
! 									    editorName, 
! 									    editor_lineno_switch,
! 									    lineno, 
! 									    fname);
! 	else
! 		sprintf(sys, SYSTEMQUOTE "\"%s\" \"%s\"" SYSTEMQUOTE, editorName, fname);
  #endif
  	result = system(sys);
  	if (result == -1)
***************
*** 1593,1599 ****
  
  /* call this one */
  static bool
! do_edit(const char *filename_arg, PQExpBuffer query_buf, bool *edited)
  {
  	char		fnametmp[MAXPGPATH];
  	FILE	   *stream = NULL;
--- 1804,1810 ----
  
  /* call this one */
  static bool
! do_edit(const char *filename_arg, PQExpBuffer query_buf, int lineno, bool *edited)
  {
  	char		fnametmp[MAXPGPATH];
  	FILE	   *stream = NULL;
***************
*** 1685,1691 ****
  
  	/* call editor */
  	if (!error)
! 		error = !editFile(fname);
  
  	if (!error && stat(fname, &after) != 0)
  	{
--- 1896,1935 ----
  
  	/* call editor */
  	if (!error)
! 	{
! 		/* skip header lines */
! 		if (lineno != -1)
! 		{
! 			char   *lines = query_buf->data;
! 			char	*dqtag;
! 			
! 			/* we have to detect number of header lines */
! 			while (*lines)
! 			{
! 				char    *end_of_line = strchr(lines, '\n');
! 			
! 				if (end_of_line)
! 					*end_of_line = '\0';
! 			
! 				dqtag = get_functiondef_dollarquote_tag(lines);
! 				if (dqtag)
! 				{
! 					free(dqtag);
! 					break;
! 				}
! 				
! 				lineno++;
! 				
! 				/* leave when there are not next row */
! 				if (!end_of_line)
! 					break;
! 					
! 				lines = end_of_line + 1;
! 			}
! 		}
! 	
! 		error = !editFile(fname, lineno);
! 	}
  
  	if (!error && stat(fname, &after) != 0)
  	{
***************
*** 2241,2243 ****
--- 2485,2582 ----
  
  	destroyPQExpBuffer(msg);
  }
+ 
+ 
+ /*
+  * Returns lineno used in \sf and \ef commands. 
+  *
+  * These commands can be completed with number used as line
+  * number for navigation in showed lines / open file. The most 
+  * simple method for parsing is reading isolated digits from 
+  * right - \ef foo nn, \ef foo(..)nn. Returns -1 when
+  * lineno isn't used in function's descriptor.
+ */
+ static int
+ extract_lineno_from_funcdesc(char *func, backslashResult *status)
+ {
+ 	char *endfunc;
+ 	char *c;
+ 	int lineno = -1;
+ 	
+ 	if (!func)
+ 		return lineno;
+ 	
+ 	endfunc = func + strlen(func) - 1;
+ 	c = endfunc;
+ 	
+ 	/* skip useles whitespaces */
+ 	while (c >= func && isblank(*c))
+ 		c--;
+ 	
+ 	/* search the most left digit of continuously number */
+ 	while (c >= func && isdigit(*c))
+ 		c--;
+ 	
+ 	/* 
+ 	 * when left char isn't blank and isn't a right parenthesis
+ 	 * then command hasn't a lineno.
+ 	 */
+ 	if (c < endfunc && c > func)
+ 	{
+ 		/* 
+ 		 * digits have to be a separated from identifier by right 
+ 		 * parenthesis or by space, and there have to be entered
+ 		 * minimal one digit.
+ 		 */
+ 		if (isdigit(c[1]) && ( isblank(*c) || *c == ')' ))
+ 		{
+ 			c++;
+ 			
+ 			lineno = atoi(c);
+ 			if (lineno < 1)
+ 			{
+ 				psql_error("invalid line number\n");
+ 				*status = PSQL_CMD_ERROR;
+ 			}
+ 			else
+ 			{
+ 				/* remove lineno from function descriptor */
+ 				*c = '\0';
+ 			}
+ 		}
+ 	}
+ 	
+ 	return lineno;
+ }
+ 
+ /*
+  * Returns tag of dollar quoted string used as function body, It parses
+  * only result of pg_get_functiondef function, so there are not possibility
+  * use just "'" char. When row doesn't contain a AS part of CREATE FUNCTION
+  * command, then it returns NULL.
+  */
+ static char *
+ get_functiondef_dollarquote_tag(char *row)
+ {
+ 	char *starttag;
+ 	char *endtag;
+ 	int	len;
+ 	char	*result;
+ 
+ 	/* leave when line doesn't contain a body separator */
+ 	if (strncmp(row, "AS $function", 12) != 0)
+ 		return NULL;
+ 		
+ 	/* detect body's tag */
+ 	starttag = row + strlen("AS ");
+ 	endtag = strchr(row + strlen("AS $function"), '$');
+ 	
+ 	psql_assert(endtag);
+ 	
+ 	len = endtag - starttag + 1;
+ 	result = pg_malloc(len + 1);
+ 	memcpy(result, starttag, len);
+ 	result[len] = '\0';
+ 		
+ 	return result;
+ }
*** ./src/bin/psql/help.c.orig	2010-08-03 09:00:48.387710077 +0200
--- ./src/bin/psql/help.c	2010-08-03 13:16:22.264713224 +0200
***************
*** 162,168 ****
  {
  	FILE	   *output;
  
! 	output = PageOutput(87, 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 */
  
***************
*** 174,186 ****
  	fprintf(output, "\n");
  
  	fprintf(output, _("Query Buffer\n"));
! 	fprintf(output, _("  \\e [FILE]              edit the query buffer (or file) with external editor\n"));
! 	fprintf(output, _("  \\ef [FUNCNAME]         edit function definition with external editor\n"));
  	fprintf(output, _("  \\p                     show the contents of the query buffer\n"));
  	fprintf(output, _("  \\r                     reset (clear) the query buffer\n"));
  #ifdef USE_READLINE
  	fprintf(output, _("  \\s [FILE]              display history or save it to file\n"));
  #endif
  	fprintf(output, _("  \\w FILE                write query buffer to file\n"));
  	fprintf(output, "\n");
  
--- 174,187 ----
  	fprintf(output, "\n");
  
  	fprintf(output, _("Query Buffer\n"));
! 	fprintf(output, _("  \\e [FILE] [lno]        edit the query buffer (or file) with external editor\n"));
! 	fprintf(output, _("  \\ef [FUNCNAME] [lno]   edit function definition with external editor\n"));
  	fprintf(output, _("  \\p                     show the contents of the query buffer\n"));
  	fprintf(output, _("  \\r                     reset (clear) the query buffer\n"));
  #ifdef USE_READLINE
  	fprintf(output, _("  \\s [FILE]              display history or save it to file\n"));
  #endif
+ 	fprintf(output, _("  \\sf[+] FUNCNAME [lno]  show finction definition\n"));
  	fprintf(output, _("  \\w FILE                write query buffer to file\n"));
  	fprintf(output, "\n");
  
*** ./src/bin/psql/tab-complete.c.orig	2010-08-03 09:00:48.390710399 +0200
--- ./src/bin/psql/tab-complete.c	2010-08-03 09:01:05.996710353 +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,2509 ----
  
  	else if (strcmp(prev_wd, "\\ef") == 0)
  		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
+ 	
+ 		else if (strncmp(prev_wd, "\\sf", 2) == 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