psql slash# command

Started by Sibte Abbasover 18 years ago7 messages
#1Sibte Abbas
sibtay@gmail.com
1 attachment(s)

Attached is the patch for the TODO item mentioned at
http://archives.postgresql.org/pgsql-hackers/2007-09/msg00352.php

The command has the following synopsis:

\#: displays the command history. Like \s but prefixes the lines with line
numbers

\# <line_no>: executes the command(if any) executed at the line specified by
line_no

regards,
--
Sibte Abbas

Attachments:

psql_slash#.patchtext/x-patch; name=psql_slash#.patchDownload
? GNUmakefile
? config.log
? config.status
? mydiff.diff
? psql_slash#.patch
? src/Makefile.global
? src/backend/postgres
? src/backend/catalog/postgres.bki
? src/backend/catalog/postgres.description
? src/backend/catalog/postgres.shdescription
? src/backend/snowball/libdict_snowball.so.0.0
? src/backend/snowball/snowball_create.sql
? src/backend/utils/mb/conversion_procs/conversion_create.sql
? src/backend/utils/mb/conversion_procs/ascii_and_mic/libascii_and_mic.so.0.0
? src/backend/utils/mb/conversion_procs/cyrillic_and_mic/libcyrillic_and_mic.so.0.0
? src/backend/utils/mb/conversion_procs/euc_cn_and_mic/libeuc_cn_and_mic.so.0.0
? src/backend/utils/mb/conversion_procs/euc_jis_2004_and_shift_jis_2004/libeuc_jis_2004_and_shift_jis_2004.so.0.0
? src/backend/utils/mb/conversion_procs/euc_jp_and_sjis/libeuc_jp_and_sjis.so.0.0
? src/backend/utils/mb/conversion_procs/euc_kr_and_mic/libeuc_kr_and_mic.so.0.0
? src/backend/utils/mb/conversion_procs/euc_tw_and_big5/libeuc_tw_and_big5.so.0.0
? src/backend/utils/mb/conversion_procs/latin2_and_win1250/liblatin2_and_win1250.so.0.0
? src/backend/utils/mb/conversion_procs/latin_and_mic/liblatin_and_mic.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_ascii/libutf8_and_ascii.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_big5/libutf8_and_big5.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_cyrillic/libutf8_and_cyrillic.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_euc_cn/libutf8_and_euc_cn.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_euc_jis_2004/libutf8_and_euc_jis_2004.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_euc_jp/libutf8_and_euc_jp.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_euc_kr/libutf8_and_euc_kr.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_euc_tw/libutf8_and_euc_tw.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_gb18030/libutf8_and_gb18030.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_gbk/libutf8_and_gbk.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_iso8859/libutf8_and_iso8859.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_iso8859_1/libutf8_and_iso8859_1.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_johab/libutf8_and_johab.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_shift_jis_2004/libutf8_and_shift_jis_2004.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_sjis/libutf8_and_sjis.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_uhc/libutf8_and_uhc.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_win/libutf8_and_win.so.0.0
? src/bin/initdb/initdb
? src/bin/ipcclean/ipcclean
? src/bin/pg_config/pg_config
? src/bin/pg_controldata/pg_controldata
? src/bin/pg_ctl/pg_ctl
? src/bin/pg_dump/pg_dump
? src/bin/pg_dump/pg_dumpall
? src/bin/pg_dump/pg_restore
? src/bin/pg_resetxlog/pg_resetxlog
? src/bin/psql/.command.c.swp
? src/bin/psql/cscope.out
? src/bin/psql/psql
? src/bin/scripts/clusterdb
? src/bin/scripts/createdb
? src/bin/scripts/createlang
? src/bin/scripts/createuser
? src/bin/scripts/dropdb
? src/bin/scripts/droplang
? src/bin/scripts/dropuser
? src/bin/scripts/reindexdb
? src/bin/scripts/vacuumdb
? src/include/pg_config.h
? src/include/stamp-h
? src/interfaces/ecpg/compatlib/libecpg_compat.so.2.3
? src/interfaces/ecpg/ecpglib/libecpg.so.6.0
? src/interfaces/ecpg/include/ecpg_config.h
? src/interfaces/ecpg/pgtypeslib/libpgtypes.so.2.3
? src/interfaces/ecpg/preproc/ecpg
? src/interfaces/libpq/exports.list
? src/interfaces/libpq/libpq.so.5.1
? src/pl/plpgsql/src/libplpgsql.so.1.0
? src/port/pg_config_paths.h
? src/test/regress/libregress.so.0.0
? src/test/regress/pg_regress
? src/test/regress/results
? src/test/regress/testtablespace
? src/test/regress/expected/constraints.out
? src/test/regress/expected/copy.out
? src/test/regress/expected/create_function_1.out
? src/test/regress/expected/create_function_2.out
? src/test/regress/expected/largeobject.out
? src/test/regress/expected/largeobject_1.out
? src/test/regress/expected/misc.out
? src/test/regress/expected/tablespace.out
? src/test/regress/sql/constraints.sql
? src/test/regress/sql/copy.sql
? src/test/regress/sql/create_function_1.sql
? src/test/regress/sql/create_function_2.sql
? src/test/regress/sql/largeobject.sql
? src/test/regress/sql/misc.sql
? src/test/regress/sql/tablespace.sql
? src/timezone/zic
Index: src/bin/psql/command.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/command.c,v
retrieving revision 1.181
diff -c -r1.181 command.c
*** src/bin/psql/command.c	21 Aug 2007 01:11:22 -0000	1.181
--- src/bin/psql/command.c	9 Sep 2007 15:23:41 -0000
***************
*** 55,61 ****
  static bool do_edit(const char *filename_arg, PQExpBuffer query_buf);
  static bool do_connect(char *dbname, char *user, char *host, char *port);
  static bool do_shell(const char *command);
! 
  
  /*----------
   * HandleSlashCmds:
--- 55,62 ----
  static bool do_edit(const char *filename_arg, PQExpBuffer query_buf);
  static bool do_connect(char *dbname, char *user, char *host, char *port);
  static bool do_shell(const char *command);
! static bool get_hist_entry(const char *lno_s, HIST_ENTRY *hist_ent);
! static int str_to_pint(const char *str);
  
  /*----------
   * HandleSlashCmds:
***************
*** 834,839 ****
--- 835,878 ----
  		free(fname);
  	}
  
+ 	/* \# show history on screen with all lines prefixed with incrementing line numbers 
+ 	 * OR execute a history command at a specific line number
+ 	 */
+ 	else if (strcmp(cmd, "#") == 0)
+ 	{
+ 		char	   *next = psql_scan_slash_option(scan_state,
+ 												   OT_NORMAL, NULL, true);
+ 		if (next) 
+ 		{
+ 			/* something follows after \#, hence consider it a \# <lineno> case */
+ 			HIST_ENTRY	he;
+ 			success = get_hist_entry(next, &he);
+ 
+ 			if (success)
+ 			{
+ 				resetPQExpBuffer(query_buf);
+ 				psql_scan_reset(scan_state);
+ 
+ 				appendPQExpBuffer(query_buf, he.line);
+ 				status = PSQL_CMD_SEND;
+ 			}
+ 			free(next);
+ 		}
+ 		else
+ 		{
+ 			/* only \#, simply display the history contents on the screen */
+ 			register HIST_ENTRY **the_list;
+ 			register int i;
+ 	
+ 			the_list = history_list();
+ 			if (the_list)
+ 			{
+ 				for (i = 0; the_list[i]; i++)
+ 			    	printf ("%d: %s\n", i + history_base, the_list[i]->line);
+ 			}
+ 		}
+ 	}
+ 
  	/* \set -- generalized set variable/option command */
  	else if (strcmp(cmd, "set") == 0)
  	{
***************
*** 1807,1809 ****
--- 1846,1908 ----
  	}
  	return true;
  }
+ 
+ /*
+  * get_hist_entry
+  *
+  * Returns the history entry corresponding to the line number specificed by 'lno_s' string.
+  * The returned value is copied in 'hist_ent'
+  */
+ static bool get_hist_entry(const char *lno_s, HIST_ENTRY *hist_ent)
+ {
+ 	int 		lno_i = 0;
+ 	HIST_ENTRY	*he;	
+ 
+ 	psql_assert(lno_s);
+ 	psql_assert(hist_ent);
+ 
+ 	/* convert the line no string to integer form */
+ 	if ((lno_i = str_to_pint(lno_s)) == -1)
+ 	{
+ 		fprintf(stderr, _("%s is an invalid value for line number\n"), lno_s);
+ 		return false;
+ 	}
+ 
+ 	/* lookup the history corresponding to the line no */
+ 	if ((he = history_get(lno_i)) != NULL)
+ 	{
+ 		memcpy(hist_ent, he, sizeof(HIST_ENTRY));
+ 		return true;
+ 	}
+ 
+ 	/* else */
+ 	fprintf(stderr, _("Could'nt find any command at line number %d\n"), lno_i);
+ 	return false;
+ }
+ 
+ /*
+  * str_to_pint
+  *
+  * converts the given string into a positive int. Returns an error if "str" 
+  * represents a negative integer.
+  *
+  * Returns, the converted value
+  * On Error, -1 is returned
+  */
+ static int str_to_pint(const char *str)
+ {
+ 	char	*end = NULL;
+ 	int		result = -1;
+ 	int		save_errno = errno;
+ 	psql_assert(str);
+ 
+ 	errno = 0;
+ 	result = strtol(str, &end, 10);
+ 
+ 	if ((errno == ERANGE) || (strlen(end) != 0) || (result < 0))
+ 		result = -1;
+ 	
+ 	errno = save_errno;
+ 	return result;
+ }
+ 
Index: src/bin/psql/help.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/help.c,v
retrieving revision 1.118
diff -c -r1.118 help.c
*** src/bin/psql/help.c	21 Aug 2007 01:11:22 -0000	1.118
--- src/bin/psql/help.c	9 Sep 2007 15:23:41 -0000
***************
*** 196,201 ****
--- 196,202 ----
  	fprintf(output, _("  \\r             reset (clear) the query buffer\n"));
  #ifdef USE_READLINE
  	fprintf(output, _("  \\s [FILE]      display history or save it to file\n"));
+ 	fprintf(output, _("  \\# [LINENO]    display history in lineno:<command> format or execute a line from that history\n"));
  #endif
  	fprintf(output, _("  \\w FILE        write query buffer to file\n"));
  	fprintf(output, "\n");
Index: src/bin/psql/tab-complete.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/tab-complete.c,v
retrieving revision 1.166
diff -c -r1.166 tab-complete.c
*** src/bin/psql/tab-complete.c	3 Jul 2007 01:30:37 -0000	1.166
--- src/bin/psql/tab-complete.c	9 Sep 2007 15:23:42 -0000
***************
*** 544,550 ****
  		"\\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
  	};
  
  	(void) end;					/* not used */
--- 544,550 ----
  		"\\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
  	};
  
  	(void) end;					/* not used */
#2Sibte Abbas
sibtay@gmail.com
In reply to: Sibte Abbas (#1)
1 attachment(s)
Re: psql slash# command

On 9/9/07, Sibte Abbas <sibtay@gmail.com> wrote:

Attached is the patch for the TODO item mentioned at
http://archives.postgresql.org/pgsql-hackers/2007-09/msg00352.php

The command has the following synopsis:

\#: displays the command history. Like \s but prefixes the lines with line
numbers

\# <line_no>: executes the command(if any) executed at the line specified by
line_no

regards,
--
Sibte Abbas

The attached patch adds the following new functionality:

\#e <lineno>: Will open the command at the given lineno in an editor.
\#e with no lineno will behave exactly like \e.

Example:
=====

psql> \#

199: create or replace function foo() returns integer as $$
begin
return 10;
end;
$$language 'plpgsql';

200: select version();

201: select * from foo();

\# 200
<select version() is executed>

psql> \#e 199
<the contents of lineno 199 are opened in the editor>

Definitely not for 8.3, however I hope that it can be queued for 8.4.

thanks,
--
Sibte Abbas

Attachments:

psql_slash#_v2.patchtext/x-patch; name=psql_slash#_v2.patchDownload
? psql_slash#.patch
? psql_slash#_v2.patch
? doc/src/sgml/ref/.psql-ref.sgml.swp
? src/cscope.out
? src/bin/psql/cscope.out
? src/pl/plperl/SPI.c
? src/pl/plperl/libplperl.so.0.0
Index: doc/src/sgml/ref/psql-ref.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/ref/psql-ref.sgml,v
retrieving revision 1.194
diff -c -r1.194 psql-ref.sgml
*** doc/src/sgml/ref/psql-ref.sgml	22 Aug 2007 04:45:20 -0000	1.194
--- doc/src/sgml/ref/psql-ref.sgml	14 Sep 2007 14:07:46 -0000
***************
*** 1923,1928 ****
--- 1922,1956 ----
          </listitem>
        </varlistentry>
  
+       <varlistentry>
+         <term><literal>\# [ <replaceable class="parameter">lineno</replaceable> ]</literal></term>
+         <listitem>
+         <para>
+ 		If <replaceable class="parameter">lineno</replaceable> is specified 
+ 		then the query at the specified lineno from psql's command history is
+ 		executed. Otherwise it behaves like \s (with no commands) with the 
+ 		difference being that it prefixes all lines with their respective
+ 		line numbers like <lineno>:<line>. This option is only available if 
+ 		<application>psql</application> is configured to use the <acronym>GNU</acronym> 
+ 		<application>Readline</application> library.
+         </para>
+         </listitem>
+       </varlistentry>
+ 
+       <varlistentry>
+         <term><literal>\#e [ <replaceable class="parameter">lineno</replaceable> ]</literal></term>
+         <listitem>
+         <para>
+ 		If <replaceable class="parameter">lineno</replaceable> is specified 
+ 		then the query at the specified lineno from the psql's command history is
+ 		opened in an editor. Otherwise whatever query is in the query buffer is 
+ 		opened for edition; just like \e (with no commands). In each case, once 
+ 		the editor is opened the following behaviour is similar to that of \e's.
+ 		This option is only available if <application>psql</application> is configured 
+ 		to use the <acronym>GNU</acronym> <application>Readline</application> library.
+         </para>
+         </listitem>
+       </varlistentry>
  
        <varlistentry>
          <term><literal>\?</literal></term>
Index: src/bin/psql/command.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/command.c,v
retrieving revision 1.181
diff -c -r1.181 command.c
*** src/bin/psql/command.c	21 Aug 2007 01:11:22 -0000	1.181
--- src/bin/psql/command.c	14 Sep 2007 14:07:47 -0000
***************
*** 55,61 ****
  static bool do_edit(const char *filename_arg, PQExpBuffer query_buf);
  static bool do_connect(char *dbname, char *user, char *host, char *port);
  static bool do_shell(const char *command);
! 
  
  /*----------
   * HandleSlashCmds:
--- 55,64 ----
  static bool do_edit(const char *filename_arg, PQExpBuffer query_buf);
  static bool do_connect(char *dbname, char *user, char *host, char *port);
  static bool do_shell(const char *command);
! #ifdef USE_READLINE
! static bool get_hist_entry(const char *lno_s, HIST_ENTRY *hist_ent);
! static int str_to_pint(const char *str);
! #endif
  
  /*----------
   * HandleSlashCmds:
***************
*** 435,441 ****
  			free(pattern);
  	}
  
- 
  	/*
  	 * \e or \edit -- edit the current query buffer (or a file and make it the
  	 * query buffer
--- 438,443 ----
***************
*** 834,839 ****
--- 836,917 ----
  		free(fname);
  	}
  
+ #ifdef USE_READLINE
+ 	/* \# show history on screen with all lines prefixed with incrementing line numbers 
+ 	 * OR execute a history command at a specific line number
+ 	 */
+ 	else if (strcmp(cmd, "#") == 0)
+ 	{
+ 		char	   *next = psql_scan_slash_option(scan_state,
+ 												   OT_NORMAL, NULL, true);
+ 		if (next) 
+ 		{
+ 			/* something follows after \#, hence consider it a \# <lineno> case */
+ 			HIST_ENTRY	he;
+ 			memset(&he, 0, sizeof(he));
+ 			success = get_hist_entry(next, &he);
+ 
+ 			if (success)
+ 			{
+ 				resetPQExpBuffer(query_buf);
+ 				psql_scan_reset(scan_state);
+ 
+ 				appendPQExpBuffer(query_buf, he.line);
+ 				status = PSQL_CMD_SEND;
+ 			}
+ 			free(next);
+ 		}
+ 		else
+ 		{
+ 			/* only \#, simply display the history contents on the screen */
+ 			register HIST_ENTRY **the_list;
+ 			register int i;
+ 	
+ 			the_list = history_list();
+ 			if (the_list)
+ 			{
+ 				for (i = 0; the_list[i]; i++)
+ 			    	printf ("%d: %s\n", i + history_base, the_list[i]->line);
+ 			}
+ 			success = true;
+ 		}
+ 	}
+ 
+ 	/* \#e <lineno> edit the specified history command */
+ 	else if (strcmp(cmd, "#e") == 0)
+ 	{
+ 		char	   *next = psql_scan_slash_option(scan_state,
+ 												   OT_NORMAL, NULL, true);
+ 		success = false;
+ 		if (next) 
+ 		{
+ 			/* something follows after \#e, hence consider it a \#e <lineno> case */
+ 			HIST_ENTRY	he;
+ 			memset(&he, 0, sizeof(he));
+ 
+ 			if ((success = get_hist_entry(next, &he)))
+ 			{
+ 				resetPQExpBuffer(query_buf);
+ 				psql_scan_reset(scan_state);
+ 				appendPQExpBuffer(query_buf, he.line);
+ 			}
+ 			free(next);
+ 		}
+ 		else
+ 		{
+ 			/* only \#e -- just edit current contents of the query_buf */
+ 			if (!query_buf)
+ 			{
+ 				psql_error("no query buffer\n");
+ 				status = PSQL_CMD_ERROR;
+ 			}
+ 			success = true;
+ 		}
+ 		if (success)
+ 			status = do_edit(NULL, query_buf) ? PSQL_CMD_NEWEDIT : PSQL_CMD_ERROR;
+ 	}
+ #endif
+ 
  	/* \set -- generalized set variable/option command */
  	else if (strcmp(cmd, "set") == 0)
  	{
***************
*** 1807,1809 ****
--- 1885,1949 ----
  	}
  	return true;
  }
+ 
+ #ifdef USE_READLINE
+ /*
+  * get_hist_entry
+  *
+  * Returns the history entry corresponding to the line number specificed by 'lno_s' string.
+  * The returned value is copied in 'hist_ent'
+  */
+ static bool get_hist_entry(const char *lno_s, HIST_ENTRY *hist_ent)
+ {
+ 	int 		lno_i = 0;
+ 	HIST_ENTRY	*he;	
+ 
+ 	psql_assert(lno_s);
+ 	psql_assert(hist_ent);
+ 
+ 	/* convert the line no string to integer form */
+ 	if ((lno_i = str_to_pint(lno_s)) == -1)
+ 	{
+ 		fprintf(stderr, _("%s is an invalid value for line number\n"), lno_s);
+ 		return false;
+ 	}
+ 
+ 	/* lookup the history corresponding to the line no */
+ 	if ((he = history_get(lno_i)) != NULL)
+ 	{
+ 		memcpy(hist_ent, he, sizeof(HIST_ENTRY));
+ 		return true;
+ 	}
+ 
+ 	/* else */
+ 	fprintf(stderr, _("Could'nt find any command at line number %d\n"), lno_i);
+ 	return false;
+ }
+ 
+ /*
+  * str_to_pint
+  *
+  * converts the given string into a positive int. Returns an error if "str" 
+  * represents a negative integer.
+  *
+  * Returns, the converted value
+  * On Error, -1 is returned
+  */
+ static int str_to_pint(const char *str)
+ {
+ 	char	*end = NULL;
+ 	int		result = -1;
+ 	int		save_errno = errno;
+ 	psql_assert(str);
+ 
+ 	errno = 0;
+ 	result = strtol(str, &end, 10);
+ 
+ 	if ((errno == ERANGE) || (strlen(end) != 0) || (result < 0))
+ 		result = -1;
+ 	
+ 	errno = save_errno;
+ 	return result;
+ }
+ #endif
+ 
Index: src/bin/psql/help.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/help.c,v
retrieving revision 1.118
diff -c -r1.118 help.c
*** src/bin/psql/help.c	21 Aug 2007 01:11:22 -0000	1.118
--- src/bin/psql/help.c	14 Sep 2007 14:07:48 -0000
***************
*** 196,201 ****
--- 196,203 ----
  	fprintf(output, _("  \\r             reset (clear) the query buffer\n"));
  #ifdef USE_READLINE
  	fprintf(output, _("  \\s [FILE]      display history or save it to file\n"));
+ 	fprintf(output, _("  \\# [LINENO]    display history in lineno:<command> format or execute a line from that history\n"));
+ 	fprintf(output, _("  \\#e [LINENO]   edit the query buffer or the history command at LINENO, with external editor\n"));
  #endif
  	fprintf(output, _("  \\w FILE        write query buffer to file\n"));
  	fprintf(output, "\n");
Index: src/bin/psql/tab-complete.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/tab-complete.c,v
retrieving revision 1.167
diff -c -r1.167 tab-complete.c
*** src/bin/psql/tab-complete.c	14 Sep 2007 04:25:24 -0000	1.167
--- src/bin/psql/tab-complete.c	14 Sep 2007 14:07:49 -0000
***************
*** 570,576 ****
  		"\\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
  	};
  
  	(void) end;					/* not used */
--- 570,576 ----
  		"\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
  		"\\o", "\\p", "\\password", "\\prompt", "\\pset", "\\q", "\\qecho", "\\r",
  		"\\set", "\\t", "\\T",
! 		"\\timing", "\\unset", "\\x", "\\w", "\\z", "\\!", "\\#", "\\#e", NULL
  	};
  
  	(void) end;					/* not used */
#3Bruce Momjian
bruce@momjian.us
In reply to: Sibte Abbas (#2)
Re: psql slash# command

This has been saved for the 8.4 release:

http://momjian.postgresql.org/cgi-bin/pgpatches_hold

---------------------------------------------------------------------------

Sibte Abbas wrote:

On 9/9/07, Sibte Abbas <sibtay@gmail.com> wrote:

Attached is the patch for the TODO item mentioned at
http://archives.postgresql.org/pgsql-hackers/2007-09/msg00352.php

The command has the following synopsis:

\#: displays the command history. Like \s but prefixes the lines with line
numbers

\# <line_no>: executes the command(if any) executed at the line specified by
line_no

regards,
--
Sibte Abbas

The attached patch adds the following new functionality:

\#e <lineno>: Will open the command at the given lineno in an editor.
\#e with no lineno will behave exactly like \e.

Example:
=====

psql> \#

199: create or replace function foo() returns integer as $$
begin
return 10;
end;
$$language 'plpgsql';

200: select version();

201: select * from foo();

\# 200
<select version() is executed>

psql> \#e 199
<the contents of lineno 199 are opened in the editor>

Definitely not for 8.3, however I hope that it can be queued for 8.4.

thanks,
--
Sibte Abbas

[ Attachment, skipping... ]

---------------------------(end of broadcast)---------------------------
TIP 4: Have you searched our list archives?

http://archives.postgresql.org

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://www.enterprisedb.com

+ If your life is a hard drive, Christ can be your backup. +

#4Tom Lane
tgl@sss.pgh.pa.us
In reply to: Sibte Abbas (#2)
Re: [PATCHES] psql slash# command

"Sibte Abbas" <sibtay@gmail.com> writes:

On 9/9/07, Sibte Abbas <sibtay@gmail.com> wrote:

Attached is the patch for the TODO item mentioned at
http://archives.postgresql.org/pgsql-hackers/2007-09/msg00352.php

I looked this over and realized that it has little to do with the
functionality that was so painfully hashed out in the original
discussion thread here:

http://archives.postgresql.org/pgsql-hackers/2006-12/msg00207.php

As I understood it, the consensus was:

1. Invent a switch (probably a variable instead of a dedicated \-command)
that determines whether \s includes command numbers in its output.

2. Add "\# n" to re-execute command number n.

You've twisted this around into

\#: displays the command history. Like \s but prefixes the lines with line
numbers

\# <line_no>: executes the command(if any) executed at the line specified by
line_no

This is a serious regression in functionality from what was agreed to,
because there is no possibility of shoehorning the equivalent of "\s file"
into it --- you've already decided that any argument is a line number.

It also seems to me to be pretty unintuitive and even dangerous that the
same \-command would do *fundamentally* different things depending on
whether it has an argument or not. Especially if one of those things
involves executing an arbitrary SQL-command.

The attached patch adds the following new functionality:
\#e <lineno>: Will open the command at the given lineno in an editor.
\#e with no lineno will behave exactly like \e.

None of that was anywhere in the original discussion; and what pray
tell is the use of the second variant?

I wonder whether it wouldn't be safer and more convenient if we defined
'\# n' as pulling command n into the edit buffer, rather than
immediately executing it. Actual execution is only a <return> away,
but this definition would allow you to edit the command a bit more
before you execute it --- including \e to use an editor. It also
closes the loop in terms of providing some confidence that you typed
the number you should have typed.

BTW, not related to the original discussion, but I fail to understand
how anyone finds \s useful interactively, when it doesn't paginate
its output. Shouldn't we fix that?

regards, tom lane

#5Bruce Momjian
bruce@momjian.us
In reply to: Tom Lane (#4)
Re: [PATCHES] psql slash# command

Based on recent patch feedback from Tom, this has been saved for the
next commit-fest:

http://momjian.postgresql.org/cgi-bin/pgpatches_hold

---------------------------------------------------------------------------

Tom Lane wrote:

"Sibte Abbas" <sibtay@gmail.com> writes:

On 9/9/07, Sibte Abbas <sibtay@gmail.com> wrote:

Attached is the patch for the TODO item mentioned at
http://archives.postgresql.org/pgsql-hackers/2007-09/msg00352.php

I looked this over and realized that it has little to do with the
functionality that was so painfully hashed out in the original
discussion thread here:

http://archives.postgresql.org/pgsql-hackers/2006-12/msg00207.php

As I understood it, the consensus was:

1. Invent a switch (probably a variable instead of a dedicated \-command)
that determines whether \s includes command numbers in its output.

2. Add "\# n" to re-execute command number n.

You've twisted this around into

\#: displays the command history. Like \s but prefixes the lines with line
numbers

\# <line_no>: executes the command(if any) executed at the line specified by
line_no

This is a serious regression in functionality from what was agreed to,
because there is no possibility of shoehorning the equivalent of "\s file"
into it --- you've already decided that any argument is a line number.

It also seems to me to be pretty unintuitive and even dangerous that the
same \-command would do *fundamentally* different things depending on
whether it has an argument or not. Especially if one of those things
involves executing an arbitrary SQL-command.

The attached patch adds the following new functionality:
\#e <lineno>: Will open the command at the given lineno in an editor.
\#e with no lineno will behave exactly like \e.

None of that was anywhere in the original discussion; and what pray
tell is the use of the second variant?

I wonder whether it wouldn't be safer and more convenient if we defined
'\# n' as pulling command n into the edit buffer, rather than
immediately executing it. Actual execution is only a <return> away,
but this definition would allow you to edit the command a bit more
before you execute it --- including \e to use an editor. It also
closes the loop in terms of providing some confidence that you typed
the number you should have typed.

BTW, not related to the original discussion, but I fail to understand
how anyone finds \s useful interactively, when it doesn't paginate
its output. Shouldn't we fix that?

regards, tom lane

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ If your life is a hard drive, Christ can be your backup. +

#6Sibte Abbas
sibtay@gmail.com
In reply to: Tom Lane (#4)
Re: psql slash# command

On Sun, Mar 30, 2008 at 3:09 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

I looked this over and realized that it has little to do with the
functionality that was so painfully hashed out in the original
discussion thread here:

http://archives.postgresql.org/pgsql-hackers/2006-12/msg00207.php

As I understood it, the consensus was:

1. Invent a switch (probably a variable instead of a dedicated \-command)
that determines whether \s includes command numbers in its output.

2. Add "\# n" to re-execute command number n.

You've twisted this around into

\#: displays the command history. Like \s but prefixes the lines with

line

numbers

\# <line_no>: executes the command(if any) executed at the line

specified by

line_no

This patch implements the specification described here:

http://archives.postgresql.org/pgsql-hackers/2006-12/msg00255.php

This is a serious regression in functionality from what was agreed to,
because there is no possibility of shoehorning the equivalent of "\s file"
into it --- you've already decided that any argument is a line number.

It made sense to assume anything following a \# to be a number, since "#"
here denotes a number. However in order to prevent from bad input, there is
a check in the get_hist_entry() function.

The attached patch adds the following new functionality:
\#e <lineno>: Will open the command at the given lineno in an editor.
\#e with no lineno will behave exactly like \e.

None of that was anywhere in the original discussion; and what pray
tell is the use of the second variant?

The above mentioned link contains definitions for both of these. Also the
second variant here is just for completeness sake.

I wonder whether it wouldn't be safer and more convenient if we defined
'\# n' as pulling command n into the edit buffer, rather than
immediately executing it. Actual execution is only a <return> away,
but this definition would allow you to edit the command a bit more
before you execute it --- including \e to use an editor. It also
closes the loop in terms of providing some confidence that you typed
the number you should have typed.

This makes more sense and also appears to be much safer. I will start
modifying the patch as per this approach now.

regards,
-- Sibte Abbas

#7Sibte Abbas
sibtay@gmail.com
In reply to: Sibte Abbas (#6)
1 attachment(s)
Re: psql slash# command

On Thu, Apr 3, 2008 at 7:54 PM, Sibte Abbas <sibtay@gmail.com> wrote:

On Sun, Mar 30, 2008 at 3:09 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:<http://archives.postgresql.org/pgsql-hackers/2006-12/msg00255.php&gt;

I wonder whether it wouldn't be safer and more convenient if we defined
'\# n' as pulling command n into the edit buffer, rather than
immediately executing it. Actual execution is only a <return> away,
but this definition would allow you to edit the command a bit more
before you execute it --- including \e to use an editor. It also
closes the loop in terms of providing some confidence that you typed
the number you should have typed.

This makes more sense and also appears to be much safer. I will start
modifying the patch as per this approach now.

Based on your feedback I have modified the attached patch as follows:

1) \# n opens command n into the edit buffer.

2) A new psql variable; SHOW_LINE_NO is added, which is consulted by the \s
command.
If it is set, \s prefixs each line of its output with an incrementing
line number.

regards,
-- Sibte Abbas

Attachments:

psql_slash#_v3.patchtext/x-patch; name=psql_slash#_v3.patchDownload
? GNUmakefile
? config.log
? config.status
? mydiff.diff
? pgsql.log
? psql_slash#_v2.patch
? psql_slash#_v3.patch
? src/Makefile.global
? src/cscope.out
? src/backend/postgres
? src/backend/access/objfiles.txt
? src/backend/access/common/objfiles.txt
? src/backend/access/gin/objfiles.txt
? src/backend/access/gist/objfiles.txt
? src/backend/access/hash/objfiles.txt
? src/backend/access/heap/objfiles.txt
? src/backend/access/index/objfiles.txt
? src/backend/access/nbtree/objfiles.txt
? src/backend/access/transam/objfiles.txt
? src/backend/bootstrap/objfiles.txt
? src/backend/catalog/objfiles.txt
? src/backend/catalog/postgres.bki
? src/backend/catalog/postgres.description
? src/backend/catalog/postgres.shdescription
? src/backend/commands/objfiles.txt
? src/backend/executor/objfiles.txt
? src/backend/lib/objfiles.txt
? src/backend/libpq/objfiles.txt
? src/backend/main/objfiles.txt
? src/backend/nodes/objfiles.txt
? src/backend/optimizer/objfiles.txt
? src/backend/optimizer/geqo/objfiles.txt
? src/backend/optimizer/path/objfiles.txt
? src/backend/optimizer/plan/objfiles.txt
? src/backend/optimizer/prep/objfiles.txt
? src/backend/optimizer/util/objfiles.txt
? src/backend/parser/objfiles.txt
? src/backend/port/objfiles.txt
? src/backend/postmaster/objfiles.txt
? src/backend/regex/objfiles.txt
? src/backend/rewrite/objfiles.txt
? src/backend/snowball/libdict_snowball.so.0.0
? src/backend/snowball/snowball_create.sql
? src/backend/storage/objfiles.txt
? src/backend/storage/buffer/objfiles.txt
? src/backend/storage/file/objfiles.txt
? src/backend/storage/freespace/objfiles.txt
? src/backend/storage/ipc/objfiles.txt
? src/backend/storage/large_object/objfiles.txt
? src/backend/storage/lmgr/objfiles.txt
? src/backend/storage/page/objfiles.txt
? src/backend/storage/smgr/objfiles.txt
? src/backend/tcop/objfiles.txt
? src/backend/tsearch/objfiles.txt
? src/backend/utils/objfiles.txt
? src/backend/utils/probes.h
? src/backend/utils/adt/objfiles.txt
? src/backend/utils/cache/objfiles.txt
? src/backend/utils/error/objfiles.txt
? src/backend/utils/fmgr/objfiles.txt
? src/backend/utils/hash/objfiles.txt
? src/backend/utils/init/objfiles.txt
? src/backend/utils/mb/objfiles.txt
? src/backend/utils/mb/conversion_procs/conversion_create.sql
? src/backend/utils/mb/conversion_procs/ascii_and_mic/libascii_and_mic.so.0.0
? src/backend/utils/mb/conversion_procs/cyrillic_and_mic/libcyrillic_and_mic.so.0.0
? src/backend/utils/mb/conversion_procs/euc_cn_and_mic/libeuc_cn_and_mic.so.0.0
? src/backend/utils/mb/conversion_procs/euc_jis_2004_and_shift_jis_2004/libeuc_jis_2004_and_shift_jis_2004.so.0.0
? src/backend/utils/mb/conversion_procs/euc_jp_and_sjis/libeuc_jp_and_sjis.so.0.0
? src/backend/utils/mb/conversion_procs/euc_kr_and_mic/libeuc_kr_and_mic.so.0.0
? src/backend/utils/mb/conversion_procs/euc_tw_and_big5/libeuc_tw_and_big5.so.0.0
? src/backend/utils/mb/conversion_procs/latin2_and_win1250/liblatin2_and_win1250.so.0.0
? src/backend/utils/mb/conversion_procs/latin_and_mic/liblatin_and_mic.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_ascii/libutf8_and_ascii.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_big5/libutf8_and_big5.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_cyrillic/libutf8_and_cyrillic.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_euc_cn/libutf8_and_euc_cn.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_euc_jis_2004/libutf8_and_euc_jis_2004.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_euc_jp/libutf8_and_euc_jp.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_euc_kr/libutf8_and_euc_kr.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_euc_tw/libutf8_and_euc_tw.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_gb18030/libutf8_and_gb18030.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_gbk/libutf8_and_gbk.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_iso8859/libutf8_and_iso8859.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_iso8859_1/libutf8_and_iso8859_1.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_johab/libutf8_and_johab.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_shift_jis_2004/libutf8_and_shift_jis_2004.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_sjis/libutf8_and_sjis.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_uhc/libutf8_and_uhc.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_win/libutf8_and_win.so.0.0
? src/backend/utils/misc/objfiles.txt
? src/backend/utils/mmgr/objfiles.txt
? src/backend/utils/resowner/objfiles.txt
? src/backend/utils/sort/objfiles.txt
? src/backend/utils/time/objfiles.txt
? src/bin/initdb/initdb
? src/bin/pg_config/pg_config
? src/bin/pg_controldata/pg_controldata
? src/bin/pg_ctl/pg_ctl
? src/bin/pg_dump/pg_dump
? src/bin/pg_dump/pg_dumpall
? src/bin/pg_dump/pg_restore
? src/bin/pg_resetxlog/pg_resetxlog
? src/bin/psql/how
? src/bin/psql/psql
? src/bin/scripts/clusterdb
? src/bin/scripts/createdb
? src/bin/scripts/createlang
? src/bin/scripts/createuser
? src/bin/scripts/dropdb
? src/bin/scripts/droplang
? src/bin/scripts/dropuser
? src/bin/scripts/reindexdb
? src/bin/scripts/vacuumdb
? src/include/pg_config.h
? src/include/stamp-h
? src/interfaces/ecpg/compatlib/exports.list
? src/interfaces/ecpg/compatlib/libecpg_compat.so.3.1
? src/interfaces/ecpg/ecpglib/exports.list
? src/interfaces/ecpg/ecpglib/libecpg.so.6.1
? src/interfaces/ecpg/include/ecpg_config.h
? src/interfaces/ecpg/pgtypeslib/exports.list
? src/interfaces/ecpg/pgtypeslib/libpgtypes.so.3.1
? src/interfaces/ecpg/preproc/ecpg
? src/interfaces/libpq/exports.list
? src/interfaces/libpq/libpq.so.5.2
? src/pl/plpgsql/src/libplpgsql.so.1.0
? src/port/pg_config_paths.h
? src/test/regress/libregress.so.0.0
? src/test/regress/pg_regress
? src/test/regress/testtablespace
? src/timezone/objfiles.txt
? src/timezone/zic
Index: doc/src/sgml/ref/psql-ref.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/ref/psql-ref.sgml,v
retrieving revision 1.199
diff -c -r1.199 psql-ref.sgml
*** doc/src/sgml/ref/psql-ref.sgml	30 Mar 2008 18:10:20 -0000	1.199
--- doc/src/sgml/ref/psql-ref.sgml	10 Apr 2008 23:55:29 -0000
***************
*** 1768,1777 ****
          <para>
          Print or save the command line history to <replaceable
          class="parameter">filename</replaceable>. If <replaceable
!         class="parameter">filename</replaceable> is omitted, the history
!         is written to the standard output. This option is only available
!         if <application>psql</application> is configured to use the
!         <acronym>GNU</acronym> <application>Readline</application> library.
          </para>
          </listitem>
        </varlistentry>
--- 1768,1781 ----
          <para>
          Print or save the command line history to <replaceable
          class="parameter">filename</replaceable>. If <replaceable
!         class="parameter">filename</replaceable> is omitted, the 
!         history is written to the standard output. In which case 
! 		the output format is determined on the basis of the value 
! 		of <varname>SHOW_LINE_NO</varname>. If it is set, then
! 		the output is prefixed with line numbers. This option  is
! 		only available if <application>psql</application> is configured 
! 		to use the <acronym>GNU</acronym> <application>Readline</application>
! 		library.
          </para>
          </listitem>
        </varlistentry>
***************
*** 1909,1914 ****
--- 1913,1929 ----
          </listitem>
        </varlistentry>
  
+       <varlistentry>
+         <term><literal>\# [ <replaceable class="parameter">lineno</replaceable> ]</literal></term>
+         <listitem>
+         <para>
+ 		Opens the query at <replaceable class="parameter">lineno</replaceable> from 
+ 		the psql's command history in an editor. Once the editor is opened, the following 
+ 		behaviour is similar to that of \e's. This option is only available if <application>psql</application> 
+ 		is configured to use the <acronym>GNU</acronym> <application>Readline</application> library.
+         </para>
+         </listitem>
+       </varlistentry>
  
        <varlistentry>
          <term><literal>\?</literal></term>
***************
*** 2373,2378 ****
--- 2388,2403 ----
        </varlistentry>
  
        <varlistentry>
+         <term><varname>SHOW_LINE_NO</varname></term>
+         <listitem>
+         <para>
+         When set, \s(while printing to standard output) will prefix
+ 		each line of its output with a line number.
+         </para>
+         </listitem>
+       </varlistentry>
+ 
+       <varlistentry>
          <term><varname>SINGLELINE</varname></term>
          <listitem>
          <para>
Index: src/bin/psql/command.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/command.c,v
retrieving revision 1.186
diff -c -r1.186 command.c
*** src/bin/psql/command.c	1 Jan 2008 19:45:55 -0000	1.186
--- src/bin/psql/command.c	10 Apr 2008 23:55:31 -0000
***************
*** 54,60 ****
  static bool do_edit(const char *filename_arg, PQExpBuffer query_buf);
  static bool do_connect(char *dbname, char *user, char *host, char *port);
  static bool do_shell(const char *command);
! 
  
  /*----------
   * HandleSlashCmds:
--- 54,64 ----
  static bool do_edit(const char *filename_arg, PQExpBuffer query_buf);
  static bool do_connect(char *dbname, char *user, char *host, char *port);
  static bool do_shell(const char *command);
! static bool display_history(void);
! #ifdef USE_READLINE
! static bool get_hist_entry(const char *lno_s, HIST_ENTRY *hist_ent);
! static int str_to_pint(const char *str);
! #endif
  
  /*----------
   * HandleSlashCmds:
***************
*** 435,441 ****
  			free(pattern);
  	}
  
- 
  	/*
  	 * \e or \edit -- edit the current query buffer (or a file and make it the
  	 * query buffer
--- 439,444 ----
***************
*** 826,840 ****
  												   OT_NORMAL, NULL, true);
  
  		expand_tilde(&fname);
! 		/* This scrolls off the screen when using /dev/tty */
! 		success = saveHistory(fname ? fname : DEVTTY, false);
! 		if (success && !pset.quiet && fname)
! 			printf(gettext("Wrote history to file \"%s/%s\".\n"),
! 				   pset.dirname ? pset.dirname : ".", fname);
! 		if (!fname)
! 			putchar('\n');
! 		free(fname);
  	}
  
  	/* \set -- generalized set variable/option command */
  	else if (strcmp(cmd, "set") == 0)
--- 829,878 ----
  												   OT_NORMAL, NULL, true);
  
  		expand_tilde(&fname);
! 		if (fname)
! 		{
! 			/* its a \s <filename>, so save history contents in fname */
! 			success = saveHistory(fname, false);
! 			if (success && !pset.quiet)
! 				printf(gettext("Wrote history to file \"%s/%s\".\n"),
! 				   	pset.dirname ? pset.dirname : ".", fname);
! 			free(fname);
! 		}
! 		else /* only \s -- just print the history contents to STDOUT */
! 			success = display_history();
! 	}
! 
! #ifdef USE_READLINE
! 	/* \# <lineno> edit the specified history command */
! 	else if (strcmp(cmd, "#") == 0)
! 	{
! 		char	   *next = psql_scan_slash_option(scan_state,
! 												   OT_NORMAL, NULL, true);
! 		if (next) 
! 		{
! 			/* something follows after \#, hence consider it a \# <lineno> case */
! 			HIST_ENTRY	he;
! 			memset(&he, 0, sizeof(he));
! 
! 			success = get_hist_entry(next, &he);
! 			if (success)
! 			{
! 				resetPQExpBuffer(query_buf);
! 				psql_scan_reset(scan_state);
! 				appendPQExpBuffer(query_buf, he.line);
! 
! 				status = do_edit(NULL, query_buf) ? PSQL_CMD_NEWEDIT : PSQL_CMD_ERROR;
! 			}
! 			free(next);
! 		}
! 		else
! 		{
! 			/* only \# is an error */
! 			psql_error("\\%s: missing required argument\n", cmd);
! 			success = false;
! 		}
  	}
+ #endif
  
  	/* \set -- generalized set variable/option command */
  	else if (strcmp(cmd, "set") == 0)
***************
*** 1810,1812 ****
--- 1848,1938 ----
  	}
  	return true;
  }
+ 
+ static bool display_history(void)
+ {
+ #ifdef USE_READLINE
+ 	/* only \s, simply display the history contents on the screen */
+ 	register HIST_ENTRY **the_list;
+ 	register int i;
+ 	
+ 	the_list = history_list();
+ 	if (the_list)
+ 	{
+ 		if (pset.show_line_no)
+ 		{
+ 			for (i = 0; the_list[i]; i++)
+ 			    printf ("%d: %s\n", i + history_base, the_list[i]->line);
+ 		}
+ 		else
+ 		{
+ 			for (i = 0; the_list[i]; i++)
+ 			    printf ("%s\n", the_list[i]->line);
+ 		}
+ 	}
+ 	return true;
+ #endif
+ 	psql_error("history is not supported by this installation\n");
+ 	return false;
+ }
+ 
+ #ifdef USE_READLINE
+ /*
+  * get_hist_entry
+  *
+  * Returns the history entry corresponding to the line number specificed by 'lno_s' string.
+  * The returned value is copied in 'hist_ent'
+  */
+ static bool get_hist_entry(const char *lno_s, HIST_ENTRY *hist_ent)
+ {
+ 	int 		lno_i = 0;
+ 	HIST_ENTRY	*he;	
+ 
+ 	psql_assert(lno_s);
+ 	psql_assert(hist_ent);
+ 
+ 	/* convert the line no string to integer form */
+ 	if ((lno_i = str_to_pint(lno_s)) == -1)
+ 	{
+ 		fprintf(stderr, _("%s is an invalid value for line number\n"), lno_s);
+ 		return false;
+ 	}
+ 
+ 	/* lookup the history corresponding to the line no */
+ 	if ((he = history_get(lno_i)) != NULL)
+ 	{
+ 		memcpy(hist_ent, he, sizeof(HIST_ENTRY));
+ 		return true;
+ 	}
+ 
+ 	/* else */
+ 	fprintf(stderr, _("Could'nt find any command at line number %d\n"), lno_i);
+ 	return false;
+ }
+ 
+ /*
+  * str_to_pint
+  *
+  * converts the given string into a positive int. Returns an error if "str" 
+  * represents a negative integer.
+  *
+  * Returns, the converted value
+  * On Error, -1 is returned
+  */
+ static int str_to_pint(const char *str)
+ {
+ 	char	*end = NULL;
+ 	int		result = -1;
+ 	int		save_errno = errno;
+ 	psql_assert(str);
+ 
+ 	errno = 0;
+ 	result = strtol(str, &end, 10);
+ 
+ 	if ((errno == ERANGE) || (strlen(end) != 0) || (result < 0))
+ 		result = -1;
+ 	
+ 	errno = save_errno;
+ 	return result;
+ }
+ #endif
Index: src/bin/psql/help.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/help.c,v
retrieving revision 1.126
diff -c -r1.126 help.c
*** src/bin/psql/help.c	4 Apr 2008 18:00:25 -0000	1.126
--- src/bin/psql/help.c	10 Apr 2008 23:55:31 -0000
***************
*** 197,202 ****
--- 197,203 ----
  	fprintf(output, _("  \\r             reset (clear) the query buffer\n"));
  #ifdef USE_READLINE
  	fprintf(output, _("  \\s [FILE]      display history or save it to file\n"));
+ 	fprintf(output, _("  \\# [LINENO]   edit the history command at LINENO, with external editor\n"));
  #endif
  	fprintf(output, _("  \\w FILE        write query buffer to file\n"));
  	fprintf(output, "\n");
Index: src/bin/psql/settings.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/settings.h,v
retrieving revision 1.33
diff -c -r1.33 settings.h
*** src/bin/psql/settings.h	1 Jan 2008 19:45:56 -0000	1.33
--- src/bin/psql/settings.h	10 Apr 2008 23:55:31 -0000
***************
*** 96,101 ****
--- 96,102 ----
  	bool		quiet;
  	bool		singleline;
  	bool		singlestep;
+ 	bool		show_line_no;
  	int			fetch_count;
  	PSQL_ECHO	echo;
  	PSQL_ECHO_HIDDEN echo_hidden;
Index: src/bin/psql/startup.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/startup.c,v
retrieving revision 1.146
diff -c -r1.146 startup.c
*** src/bin/psql/startup.c	1 Jan 2008 19:45:56 -0000	1.146
--- src/bin/psql/startup.c	10 Apr 2008 23:55:31 -0000
***************
*** 868,873 ****
--- 868,879 ----
  		PQsetErrorVerbosity(pset.db, pset.verbosity);
  }
  
+ static void
+ show_line_no_hook(const char *newval)
+ {
+ 	pset.show_line_no = ParseVariableBool(newval);
+ }
+ 
  
  static void
  EstablishVariableSpace(void)
***************
*** 888,891 ****
--- 894,898 ----
  	SetVariableAssignHook(pset.vars, "PROMPT2", prompt2_hook);
  	SetVariableAssignHook(pset.vars, "PROMPT3", prompt3_hook);
  	SetVariableAssignHook(pset.vars, "VERBOSITY", verbosity_hook);
+ 	SetVariableAssignHook(pset.vars, "SHOW_LINE_NO", show_line_no_hook);
  }
Index: src/bin/psql/tab-complete.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/tab-complete.c,v
retrieving revision 1.170
diff -c -r1.170 tab-complete.c
*** src/bin/psql/tab-complete.c	29 Mar 2008 19:19:14 -0000	1.170
--- src/bin/psql/tab-complete.c	10 Apr 2008 23:55:32 -0000
***************
*** 628,634 ****
  		"\\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
  	};
  
  	(void) end;					/* not used */
--- 628,634 ----
  		"\\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
  	};
  
  	(void) end;					/* not used */