Hi

Patch looks excellent now. No issues.

Found a typo which I have fixed in the attached patch.

Thanks

-- 
Jeevan B Chalke
Principal Software Engineer, Product Development
EnterpriseDB Corporation
The Enterprise PostgreSQL Company
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index 62a3b21..4467b8c 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -1651,6 +1651,34 @@ Tue Oct 26 21:40:57 CEST 1999
 
 
       <varlistentry>
+        <term><literal>\ev <optional> <replaceable 
class="parameter">viewname</> <optional>  <replaceable 
class="parameter">line_number</> </optional> </optional> </literal></term>
+
+        <listitem>
+        <para>
+         This command fetches and edits the definition of the named view,
+         in the form of a <command>CREATE OR REPLACE VIEW</> command.
+         Editing is done in the same way as for <literal>\edit</>.
+         After the editor exits, the updated command waits in the query buffer;
+         type semicolon or <literal>\g</> to send it, or <literal>\r</>
+         to cancel.
+        </para>
+
+        <para>
+         If no view is specified, a blank <command>CREATE VIEW</>
+         template is presented for editing.
+        </para>
+
+        <para>
+         If a line number is specified, <application>psql</application> will
+         position the cursor on the specified line of the view definition.
+         (Note that the view definition typically does not begin on the first
+         line of the file.)
+        </para>
+        </listitem>
+      </varlistentry>
+
+
+      <varlistentry>
         <term><literal>\encoding [ <replaceable 
class="parameter">encoding</replaceable> ]</literal></term>
 
         <listitem>
@@ -2522,6 +2550,26 @@ testdb=&gt; <userinput>\setenv LESS -imx4F</userinput>
 
 
       <varlistentry>
+        <term><literal>\sv[+] <replaceable class="parameter">viewname</> 
</literal></term>
+
+        <listitem>
+         <para>
+          This command fetches and shows the definition of the named view,
+          in the form of a <command>CREATE OR REPLACE VIEW</> command.
+          The definition is printed to the current query output channel,
+          as set by <command>\o</command>.
+         </para>
+
+         <para>
+          If <literal>+</literal> is appended to the command name, then the
+          output lines are numbered, with the first line of the view definition
+          being line 1.
+         </para>
+        </listitem>
+      </varlistentry>
+
+
+      <varlistentry>
         <term><literal>\t</literal></term>
         <listitem>
         <para>
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 38253fa..71a2dfd 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -49,6 +49,16 @@
 #include "settings.h"
 #include "variables.h"
 
+/*
+ * Editable database object types.
+ * Currently functions and views are supported.
+ */
+typedef enum PgObjType
+{
+       PgObjTypeFunction,
+       PgObjTypeView
+       /* add new editable object type here */
+} PgObjType;
 
 /* functions for use in this file */
 static backslashResult exec_command(const char *cmd,
@@ -59,10 +69,17 @@ 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 do_watch(PQExpBuffer query_buf, long sleep);
-static bool lookup_function_oid(const char *desc, Oid *foid);
-static bool get_create_function_cmd(Oid oid, PQExpBuffer buf);
-static int     strip_lineno_from_funcdesc(char *func);
+static bool lookup_object_oid(const char *desc,
+                                                         PgObjType obj_type,
+                                                         Oid *obj_oid);
+static bool get_create_object_cmd(Oid oid, PQExpBuffer buf, PgObjType type);
+static void format_create_view_cmd(char *view, PQExpBuffer buf);
+static int     strip_lineno_from_objdesc(char *obj);
 static void minimal_error_message(PGresult *res);
+static int count_lines_in_buf(PQExpBuffer buf);
+static void print_with_linenumbers(FILE *output,
+                                                                  char *lines,
+                                                                  const char 
*header_cmp_keyword);
 
 static void printSSLInfo(void);
 static bool printPsetInfo(const char *param, struct printQueryOpt *popt);
@@ -612,7 +629,7 @@ exec_command(const char *cmd,
 
                        func = psql_scan_slash_option(scan_state,
                                                                                
  OT_WHOLE_LINE, NULL, true);
-                       lineno = strip_lineno_from_funcdesc(func);
+                       lineno = strip_lineno_from_objdesc(func);
                        if (lineno == 0)
                        {
                                /* error already reported */
@@ -629,12 +646,12 @@ exec_command(const char *cmd,
                                                                  "AS 
$function$\n"
                                                                  
"\n$function$\n");
                        }
-                       else if (!lookup_function_oid(func, &foid))
+                       else if (!lookup_object_oid(func, PgObjTypeFunction, 
&foid))
                        {
                                /* error already reported */
                                status = PSQL_CMD_ERROR;
                        }
-                       else if (!get_create_function_cmd(foid, query_buf))
+                       else if (!get_create_object_cmd(foid, query_buf, 
PgObjTypeFunction))
                        {
                                /* error already reported */
                                status = PSQL_CMD_ERROR;
@@ -682,6 +699,108 @@ exec_command(const char *cmd,
                }
        }
 
+       /*
+        * \ev -- edit the named view, or present a blank CREATE VIEW viewname 
AS
+        * template if no argument is given
+        */
+       else if (strcmp(cmd, "ev") == 0)
+       {
+               int                     lineno = -1;
+
+               if (pset.sversion < 70100)
+               {
+                       psql_error("The server (version %d.%d) does not support 
editing view definition.\n",
+                                          pset.sversion / 10000, 
(pset.sversion / 100) % 100);
+                       status = PSQL_CMD_ERROR;
+               }
+               else if (!query_buf)
+               {
+                       psql_error("no query buffer\n");
+                       status = PSQL_CMD_ERROR;
+               }
+               else
+               {
+                       char       *view;
+                       Oid                     view_oid = InvalidOid;
+
+                       view = psql_scan_slash_option(scan_state,
+                                                                               
  OT_WHOLE_LINE, NULL, true);
+                       lineno = strip_lineno_from_objdesc(view);
+
+                       if (lineno == 0)
+                       {
+                               /* error already reported */
+                               status = PSQL_CMD_ERROR;
+                       }
+                       if (!view)
+                       {
+                               /* set up an empty command to fill in */
+                               printfPQExpBuffer(query_buf,
+                                                                 "CREATE VIEW 
viewname AS \n"
+                                                                 " SELECT \n"
+                                                                 "  -- 
something... \n");
+                       }
+                       else if (!lookup_object_oid(view, PgObjTypeView, 
&view_oid))
+                       {
+                               /* error already reported */
+                               status = PSQL_CMD_ERROR;
+                       }
+                       else if (!get_create_object_cmd(view_oid, query_buf, 
PgObjTypeView))
+                       {
+                               /* error already reported */
+                               status = PSQL_CMD_ERROR;
+                       }
+                       else if (lineno > 0)
+                       {
+                               /*
+                                * lineno "1" should correspond to the first 
line of the
+                                * view definition.  We expect that 
pg_get_viewdef() will
+                                * emit that on a line beginning with " 
SELECT", and that there
+                                * can be no such line before the real start of 
the view
+                                * definition.  Increment lineno by the number 
of lines before that
+                                * line, so that it becomes relative to the 
first line of the
+                                * view definition.
+                                */
+                               const char *lines = query_buf->data;
+
+                               while (*lines != '\0')
+                               {
+                                       if (strncmp(lines, " SELECT", 7) == 0)
+                                               break;
+                                       lineno++;
+                                       /* find start of next line */
+                                       lines = strchr(lines, '\n');
+                                       if (!lines)
+                                               break;
+                                       lines++;
+                               }
+                       }
+
+                       if (view) {
+                               format_create_view_cmd(view, query_buf);
+                               free(view);
+
+                               /*
+                                * format_create_view_cmd() adds one extra line
+                                * so we need to compensate it.
+                                */
+                               lineno++;
+                       }
+               }
+
+               if (status != PSQL_CMD_ERROR)
+               {
+                       bool            edited = false;
+
+                       if (!do_edit(NULL, query_buf, lineno, &edited))
+                               status = PSQL_CMD_ERROR;
+                       else if (!edited)
+                               puts(_("No changes"));
+                       else
+                               status = PSQL_CMD_NEWEDIT;
+               }
+       }
+
        /* \echo and \qecho */
        else if (strcmp(cmd, "echo") == 0 || strcmp(cmd, "qecho") == 0)
        {
@@ -1235,12 +1354,12 @@ exec_command(const char *cmd,
                        psql_error("function name is required\n");
                        status = PSQL_CMD_ERROR;
                }
-               else if (!lookup_function_oid(func, &foid))
+               else if (!lookup_object_oid(func, PgObjTypeFunction, &foid))
                {
                        /* error already reported */
                        status = PSQL_CMD_ERROR;
                }
-               else if (!get_create_function_cmd(foid, func_buf))
+               else if (!get_create_object_cmd(foid, func_buf, 
PgObjTypeFunction))
                {
                        /* error already reported */
                        status = PSQL_CMD_ERROR;
@@ -1254,18 +1373,7 @@ exec_command(const char *cmd,
                        if (pset.queryFout == stdout)
                        {
                                /* count lines in function to see if pager is 
needed */
-                               int                     lineno = 0;
-                               const char *lines = func_buf->data;
-
-                               while (*lines != '\0')
-                               {
-                                       lineno++;
-                                       /* find start of next line */
-                                       lines = strchr(lines, '\n');
-                                       if (!lines)
-                                               break;
-                                       lines++;
-                               }
+                               int lineno = count_lines_in_buf(func_buf);
 
                                output = PageOutput(lineno, &(pset.popt.topt));
                                is_pager = true;
@@ -1279,45 +1387,16 @@ exec_command(const char *cmd,
 
                        if (show_linenumbers)
                        {
-                               bool            in_header = true;
-                               int                     lineno = 0;
-                               char       *lines = func_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 ", 
and that there
                                 * can be no such line before the real start of 
the function
                                 * body.
-                                *
-                                * Note that this loop scribbles on func_buf.
                                 */
-                               while (*lines != '\0')
-                               {
-                                       char       *eol;
-
-                                       if (in_header && strncmp(lines, "AS ", 
3) == 0)
-                                               in_header = false;
-                                       /* increment lineno only for body's 
lines */
-                                       if (!in_header)
-                                               lineno++;
-
-                                       /* find and mark end of current line */
-                                       eol = strchr(lines, '\n');
-                                       if (eol != NULL)
-                                               *eol = '\0';
-
-                                       /* show current line as appropriate */
-                                       if (in_header)
-                                               fprintf(output, "        %s\n", 
lines);
-                                       else
-                                               fprintf(output, "%-7d %s\n", 
lineno, lines);
-
-                                       /* advance to next line, if any */
-                                       if (eol == NULL)
-                                               break;
-                                       lines = ++eol;
-                               }
+
+                               char *lines = func_buf->data;
+                               print_with_linenumbers(output, lines, "AS ");
                        }
                        else
                        {
@@ -1334,6 +1413,89 @@ exec_command(const char *cmd,
                destroyPQExpBuffer(func_buf);
        }
 
+       /* \sv -- show a view's source code */
+       else if (strcmp(cmd, "sv") == 0 || strcmp(cmd, "sv+") == 0)
+       {
+               bool            show_linenumbers = (strcmp(cmd, "sv+") == 0);
+               PQExpBuffer view_buf;
+               char       *view;
+               Oid                     view_oid = InvalidOid;
+
+               view_buf = createPQExpBuffer();
+               view = psql_scan_slash_option(scan_state,
+                                                                         
OT_WHOLE_LINE, NULL, true);
+
+               if (pset.sversion < 70100)
+               {
+                       psql_error("The server (version %d.%d) does not support 
showing view definition.\n",
+                                          pset.sversion / 10000, 
(pset.sversion / 100) % 100);
+                       status = PSQL_CMD_ERROR;
+               }
+               if (!view)
+               {
+                       psql_error("view name is required\n");
+                       status = PSQL_CMD_ERROR;
+               }
+               else if (!lookup_object_oid(view, PgObjTypeView, &view_oid))
+               {
+                       /* error already reported */
+                       status = PSQL_CMD_ERROR;
+               }
+               else if (!get_create_object_cmd(view_oid, view_buf, 
PgObjTypeView))
+               {
+                       /* error already reported */
+                       status = PSQL_CMD_ERROR;
+               }
+               else
+               {
+                       FILE *output;
+                       bool is_pager;
+
+                       format_create_view_cmd(view, view_buf);
+
+                       if (pset.queryFout == stdout)
+                       {
+                               /* count lines in view to see if pager is 
needed */
+                               int lineno = count_lines_in_buf(view_buf);
+
+                               output = PageOutput(lineno, &(pset.popt.topt));
+                               is_pager = true;
+                       }
+                       else
+                       {
+                               /* use previously set output file, without 
pager */
+                               output = pset.queryFout;
+                               is_pager = false;
+                       }
+
+                       if (show_linenumbers)
+                       {
+                               /*
+                                * lineno "1" should correspond to the first 
line of the
+                                * view definition.  We expect that 
pg_get_viewdef() will
+                                * emit that on a line beginning with " 
SELECT", and that there
+                                * can be no such line before the real start of 
the view
+                                * definition.
+                                */
+
+                               char       *lines = view_buf->data;
+                               print_with_linenumbers(output, lines, " 
SELECT");
+                       }
+                       else
+                       {
+                               /* just send the function definition to output 
*/
+                               fputs(view_buf->data, output);
+                       }
+
+                       if (is_pager)
+                               ClosePager(output);
+               }
+
+               if (view)
+                       free(view);
+               destroyPQExpBuffer(view_buf);
+       }
+
        /* \t -- turn off headers and row count */
        else if (strcmp(cmd, "t") == 0)
        {
@@ -3002,7 +3164,7 @@ do_watch(PQExpBuffer query_buf, long sleep)
  * returns true unless we have ECHO_HIDDEN_NOEXEC.
  */
 static bool
-lookup_function_echo_hidden(char *query)
+lookup_object_echo_hidden(char *query)
 {
        if (pset.echo_hidden != PSQL_ECHO_HIDDEN_OFF)
        {
@@ -3025,35 +3187,51 @@ lookup_function_echo_hidden(char *query)
        return true;
 }
 
-/*
- * This function takes a function description, e.g. "x" or "x(int)", and
- * issues a query on the given connection to retrieve the function's OID
- * using a cast to regproc or regprocedure (as appropriate). The result,
- * if there is one, is returned at *foid.  Note that we'll fail if the
- * function doesn't exist OR if there are multiple matching candidates
- * OR if there's something syntactically wrong with the function description;
- * unfortunately it can be hard to tell the difference.
- */
 static bool
-lookup_function_oid(const char *desc, Oid *foid)
+lookup_object_oid(const char *desc, PgObjType obj_type, Oid *obj_oid)
 {
+       PQExpBuffer query = createPQExpBuffer();
+
        bool            result = true;
-       PQExpBuffer query;
        PGresult   *res;
 
-       query = createPQExpBuffer();
-       appendPQExpBufferStr(query, "SELECT ");
-       appendStringLiteralConn(query, desc, pset.db);
-       appendPQExpBuffer(query, "::pg_catalog.%s::pg_catalog.oid",
-                                         strchr(desc, '(') ? "regprocedure" : 
"regproc");
-       if (!lookup_function_echo_hidden(query->data))
+       if (!lookup_object_echo_hidden(query->data))
        {
                destroyPQExpBuffer(query);
                return false;
        }
+
+       switch (obj_type)
+       {
+               /*
+                * We got a function description, e.g. "x" or "x(int)", and
+                * issue a query on the given connection to retrieve the 
function's OID
+                * using a cast to regproc or regprocedure (as appropriate). 
The result,
+                * if there is one, is returned at *foid.  Note that we'll fail 
if the
+                * function doesn't exist OR if there are multiple matching 
candidates
+                * OR if there's something syntactically wrong with the function
+                * description; unfortunately it can be hard to tell the 
difference.
+                */
+               case PgObjTypeFunction:
+                       appendPQExpBufferStr(query, "SELECT ");
+                       appendStringLiteralConn(query, desc, pset.db);
+                       appendPQExpBuffer(query, 
"::pg_catalog.%s::pg_catalog.oid",
+                                                         strchr(desc, '(') ? 
"regprocedure" : "regproc");
+                       break;
+
+               /*
+                * Convert viewname to corresponding oid.
+                */
+               case PgObjTypeView:
+                       appendPQExpBufferStr(query, "SELECT ");
+                       appendStringLiteralConn(query, desc, pset.db);
+                       appendPQExpBuffer(query, 
"::pg_catalog.regclass::pg_catalog.oid");
+                       break;
+       }
+
        res = PQexec(pset.db, query->data);
        if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1)
-               *foid = atooid(PQgetvalue(res, 0, 0));
+               *obj_oid = atooid(PQgetvalue(res, 0, 0));
        else
        {
                minimal_error_message(res);
@@ -3067,24 +3245,48 @@ lookup_function_oid(const char *desc, Oid *foid)
 }
 
 /*
- * Fetches the "CREATE OR REPLACE FUNCTION ..." command that describes the
- * function with the given OID.  If successful, the result is stored in buf.
+ * Fetches the "CREATE ..." command that describes the
+ * database object by given query.
+ * If successful, the result is stored in buf.
  */
 static bool
-get_create_function_cmd(Oid oid, PQExpBuffer buf)
+get_create_object_cmd(Oid oid, PQExpBuffer buf, PgObjType type)
 {
+       PQExpBuffer query = createPQExpBuffer();
+
        bool            result = true;
-       PQExpBuffer query;
        PGresult   *res;
 
-       query = createPQExpBuffer();
-       printfPQExpBuffer(query, "SELECT pg_catalog.pg_get_functiondef(%u)", 
oid);
-
-       if (!lookup_function_echo_hidden(query->data))
+       if (!lookup_object_echo_hidden(query->data))
        {
                destroyPQExpBuffer(query);
                return false;
        }
+
+       switch (type)
+       {
+               /*
+                * Fetch the "CREATE OR REPLACE FUNCTION ..." command that 
describes
+                * the function with the given OID.
+                * If successful, the result is stored in buf.
+                */
+               case PgObjTypeFunction:
+                       printfPQExpBuffer(query,
+                                                         "SELECT 
pg_catalog.pg_get_functiondef(%u)",
+                                                         oid);
+                       break;
+
+               /*
+                * Fetch a view definition that describes the view with the 
given OID.
+                * If successful, the result is stored in buf.
+                */
+               case PgObjTypeView:
+                       printfPQExpBuffer(query,
+                                                         "SELECT 
pg_catalog.pg_get_viewdef(%u, true)",
+                                                         oid);
+                       break;
+       }
+
        res = PQexec(pset.db, query->data);
        if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1)
        {
@@ -3104,24 +3306,45 @@ get_create_function_cmd(Oid oid, PQExpBuffer buf)
 }
 
 /*
- * If the given argument of \ef ends with a line number, delete the line
+ * Unfortunately pg_get_viewdef() doesn't return "CREATE OR REPLACE"
+ * statement prefix.
+ * We need to format "CREATE" statement manually.
+ * Originally allocated buffer contents will be replaced with formatted one.
+ */
+static void
+format_create_view_cmd(char *view, PQExpBuffer buf)
+{
+       PQExpBuffer t = createPQExpBuffer();
+       printfPQExpBuffer(t,
+                                         "CREATE OR REPLACE VIEW %s AS\n%s\n",
+                                         view,
+                                         buf->data);
+
+       resetPQExpBuffer(buf);
+       printfPQExpBuffer(buf, "%s", t->data);
+
+       destroyPQExpBuffer(t);
+}
+
+/*
+ * If the given argument of \ef or \ev ends with a line number, delete the line
  * number from the argument string and return it as an integer.  (We need
- * this kluge because we're too lazy to parse \ef's function name argument
- * carefully --- we just slop it up in OT_WHOLE_LINE mode.)
+ * this kluge because we're too lazy to parse \ef's function or \ev's view
+ * argument carefully --- we just slop it up in OT_WHOLE_LINE mode.)
  *
  * Returns -1 if no line number is present, 0 on error, or a positive value
  * on success.
  */
 static int
-strip_lineno_from_funcdesc(char *func)
+strip_lineno_from_objdesc(char *obj)
 {
        char       *c;
        int                     lineno;
 
-       if (!func || func[0] == '\0')
+       if (!obj || obj[0] == '\0')
                return -1;
 
-       c = func + strlen(func) - 1;
+       c = obj + strlen(obj) - 1;
 
        /*
         * This business of parsing backwards is dangerous as can be in a
@@ -3134,20 +3357,20 @@ strip_lineno_from_funcdesc(char *func)
         */
 
        /* skip trailing whitespace */
-       while (c > func && isascii((unsigned char) *c) && isspace((unsigned 
char) *c))
+       while (c > obj && isascii((unsigned char) *c) && isspace((unsigned 
char) *c))
                c--;
 
        /* must have a digit as last non-space char */
-       if (c == func || !isascii((unsigned char) *c) || !isdigit((unsigned 
char) *c))
+       if (c == obj || !isascii((unsigned char) *c) || !isdigit((unsigned 
char) *c))
                return -1;
 
        /* find start of digit string */
-       while (c > func && isascii((unsigned char) *c) && isdigit((unsigned 
char) *c))
+       while (c > obj && isascii((unsigned char) *c) && isdigit((unsigned 
char) *c))
                c--;
 
        /* digits must be separated from func name by space or closing paren */
        /* notice also that we are not allowing an empty func name ... */
-       if (c == func || !isascii((unsigned char) *c) ||
+       if (c == obj || !isascii((unsigned char) *c) ||
                !(isspace((unsigned char) *c) || *c == ')'))
                return -1;
 
@@ -3194,3 +3417,69 @@ minimal_error_message(PGresult *res)
 
        destroyPQExpBuffer(msg);
 }
+
+/*
+ * Count number of lines in the buffer.
+ * It is used to test that pager is needed or not.
+ */
+static int
+count_lines_in_buf(PQExpBuffer buf)
+{
+       int                     lineno = 0;
+       const char *lines = buf->data;
+
+       while (*lines != '\0')
+       {
+               lineno++;
+               /* find start of next line */
+               lines = strchr(lines, '\n');
+               if (!lines)
+                       break;
+               lines++;
+       }
+
+       return lineno;
+}
+
+/*
+ * Produce line-numbered output of object's definition.
+ * Note that the object definition does not begin on the first line.
+ */
+static void
+print_with_linenumbers(FILE *output,
+                                          char *lines,
+                                          const char *header_cmp_keyword)
+{
+       bool            in_header = true;
+       int                     lineno = 0;
+
+       size_t header_cmp_sz = strlen(header_cmp_keyword);
+
+       while (*lines != '\0')
+       {
+               char       *eol;
+
+               if (in_header && strncmp(lines, header_cmp_keyword, 
header_cmp_sz) == 0)
+                       in_header = false;
+
+               /* increment lineno only for body's lines */
+               if (!in_header)
+                       lineno++;
+
+               /* find and mark end of current line */
+               eol = strchr(lines, '\n');
+               if (eol != NULL)
+                       *eol = '\0';
+
+               /* show current line as appropriate */
+               if (in_header)
+                       fprintf(output, "        %s\n", lines);
+               else
+                       fprintf(output, "%-7d %s\n", lineno, lines);
+
+               /* advance to next line, if any */
+               if (eol == NULL)
+                       break;
+               lines = ++eol;
+       }
+}
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index b523054..da9b954 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -181,6 +181,7 @@ slashUsage(unsigned short int pager)
        fprintf(output, _("Query Buffer\n"));
        fprintf(output, _("  \\e [FILE] [LINE]       edit the query buffer (or 
file) with external editor\n"));
        fprintf(output, _("  \\ef [FUNCNAME [LINE]]  edit function definition 
with external editor\n"));
+       fprintf(output, _("  \\ev [VIEWNAME [LINE]]  edit view 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
@@ -238,6 +239,7 @@ slashUsage(unsigned short int pager)
        fprintf(output, _("  \\dy     [PATTERN]      list event triggers\n"));
        fprintf(output, _("  \\l[+]   [PATTERN]      list databases\n"));
        fprintf(output, _("  \\sf[+] FUNCNAME        show a function's 
definition\n"));
+       fprintf(output, _("  \\sv[+] VIEWNAME        show a view's 
definition\n"));
        fprintf(output, _("  \\z      [PATTERN]      same as \\dp\n"));
        fprintf(output, "\n");
 
@@ -388,7 +390,7 @@ helpVariables(unsigned short int pager)
        fprintf(output, _("  PGPASSWORD         connection password (not 
recommended)\n"));
        fprintf(output, _("  PGPASSFILE         password file name\n"));
        fprintf(output, _("  PSQL_EDITOR, EDITOR, VISUAL\n"
-                "                     editor used by the \\e and \\ef 
commands\n"));
+                "                     editor used by the \\e, \\ef, and \\ev 
commands\n"));
        fprintf(output, _("  PSQL_EDITOR_LINENUMBER_ARG\n"
                                          "                     how to specify 
a line number when invoking the editor\n"));
        fprintf(output, _("  PSQL_HISTORY       alternative location for the 
command history file\n"));
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index b9f5acc..d4a1c1f 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -895,11 +895,11 @@ psql_completion(const char *text, int start, int end)
                "\\d", "\\da", "\\db", "\\dc", "\\dC", "\\dd", "\\dD", "\\des", 
"\\det", "\\deu", "\\dew", "\\df",
                "\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl", 
"\\dL",
                "\\dn", "\\do", "\\dp", "\\drds", "\\ds", "\\dS", "\\dt", 
"\\dT", "\\dv", "\\du", "\\dx",
-               "\\e", "\\echo", "\\ef", "\\encoding",
+               "\\e", "\\ef", "\\ev", "\\echo", "\\encoding",
                "\\f", "\\g", "\\gset", "\\h", "\\help", "\\H", "\\i", "\\ir", 
"\\l",
                "\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
                "\\o", "\\p", "\\password", "\\prompt", "\\pset", "\\q", 
"\\qecho", "\\r",
-               "\\set", "\\sf", "\\t", "\\T",
+               "\\set", "\\sf", "\\sf+", "\\sv", "\\sv+", "\\t", "\\T",
                "\\timing", "\\unset", "\\x", "\\w", "\\watch", "\\z", "\\!", 
NULL
        };
 
@@ -3784,6 +3784,8 @@ psql_completion(const char *text, int start, int end)
 
        else if (strcmp(prev_wd, "\\ef") == 0)
                COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
+       else if (strcmp(prev_wd, "\\ev") == 0)
+               COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
 
        else if (strcmp(prev_wd, "\\encoding") == 0)
                COMPLETE_WITH_QUERY(Query_for_list_of_encodings);
@@ -3898,6 +3900,8 @@ psql_completion(const char *text, int start, int end)
        }
        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, "\\sv") == 0 || strcmp(prev_wd, "\\sv+") == 0)
+               COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
        else if (strcmp(prev_wd, "\\cd") == 0 ||
                         strcmp(prev_wd, "\\e") == 0 || strcmp(prev_wd, 
"\\edit") == 0 ||
                         strcmp(prev_wd, "\\g") == 0 ||
-- 
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