]> granicus.if.org Git - postgresql/commitdiff
Fix psql's \ev and \sv commands so that they handle view reloptions.
authorDean Rasheed <dean.a.rasheed@gmail.com>
Fri, 6 May 2016 11:48:27 +0000 (12:48 +0100)
committerDean Rasheed <dean.a.rasheed@gmail.com>
Fri, 6 May 2016 11:48:27 +0000 (12:48 +0100)
Commit 8eb6407aaeb6cbd972839e356b436bb698f51cff added support for
editing and showing view definitions, but neglected to account for
view options such as security_barrier and WITH CHECK OPTION which are
not returned by pg_get_viewdef() and so need special handling.

Author: Dean Rasheed
Reviewed-by: Peter Eisentraut
Discussion: http://www.postgresql.org/message-id/CAEZATCWZjCgKRyM-agE0p8ax15j9uyQoF=qew7D2xB6cF76T8A@mail.gmail.com

src/bin/psql/command.c

index 4fa7760a2a94af2d78fecea6324309a985fdfcc2..87adfce9c114e136cca7fcccbf360fa694972847 100644 (file)
@@ -3274,12 +3274,51 @@ get_create_object_cmd(EditableObjectType obj_type, Oid oid,
                         * CREATE for ourselves.  We must fully qualify the view name to
                         * ensure the right view gets replaced.  Also, check relation kind
                         * to be sure it's a view.
+                        *
+                        * Starting with 9.2, views may have reloptions (security_barrier)
+                        * and from 9.4 onwards they may also have WITH [LOCAL|CASCADED]
+                        * CHECK OPTION.  These are not part of the view definition
+                        * returned by pg_get_viewdef() and so need to be retrieved
+                        * separately.  Materialized views (introduced in 9.3) may have
+                        * arbitrary storage parameter reloptions.
                         */
-                       printfPQExpBuffer(query,
-                                                         "SELECT nspname, relname, relkind, pg_catalog.pg_get_viewdef(c.oid, true) FROM "
-                                "pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n "
-                                                         "ON c.relnamespace = n.oid WHERE c.oid = %u",
-                                                         oid);
+                       if (pset.sversion >= 90400)
+                       {
+                               printfPQExpBuffer(query,
+                                                                 "SELECT nspname, relname, relkind, "
+                                                                 "pg_catalog.pg_get_viewdef(c.oid, true), "
+                                                                 "array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, "
+                                                                 "CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text "
+                                                                 "WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption "
+                                                                 "FROM pg_catalog.pg_class c "
+                                                                 "LEFT JOIN pg_catalog.pg_namespace n "
+                                                               "ON c.relnamespace = n.oid WHERE c.oid = %u",
+                                                                 oid);
+                       }
+                       else if (pset.sversion >= 90200)
+                       {
+                               printfPQExpBuffer(query,
+                                                                 "SELECT nspname, relname, relkind, "
+                                                                 "pg_catalog.pg_get_viewdef(c.oid, true), "
+                                                                 "c.reloptions AS reloptions, "
+                                                                 "NULL AS checkoption "
+                                                                 "FROM pg_catalog.pg_class c "
+                                                                 "LEFT JOIN pg_catalog.pg_namespace n "
+                                                               "ON c.relnamespace = n.oid WHERE c.oid = %u",
+                                                                 oid);
+                       }
+                       else
+                       {
+                               printfPQExpBuffer(query,
+                                                                 "SELECT nspname, relname, relkind, "
+                                                                 "pg_catalog.pg_get_viewdef(c.oid, true), "
+                                                                 "NULL AS reloptions, "
+                                                                 "NULL AS checkoption "
+                                                                 "FROM pg_catalog.pg_class c "
+                                                                 "LEFT JOIN pg_catalog.pg_namespace n "
+                                                               "ON c.relnamespace = n.oid WHERE c.oid = %u",
+                                                                 oid);
+                       }
                        break;
        }
 
@@ -3304,6 +3343,8 @@ get_create_object_cmd(EditableObjectType obj_type, Oid oid,
                                        char       *relname = PQgetvalue(res, 0, 1);
                                        char       *relkind = PQgetvalue(res, 0, 2);
                                        char       *viewdef = PQgetvalue(res, 0, 3);
+                                       char       *reloptions = PQgetvalue(res, 0, 4);
+                                       char       *checkoption = PQgetvalue(res, 0, 5);
 
                                        /*
                                         * If the backend ever supports CREATE OR REPLACE
@@ -3328,11 +3369,33 @@ get_create_object_cmd(EditableObjectType obj_type, Oid oid,
                                                        break;
                                        }
                                        appendPQExpBuffer(buf, "%s.", fmtId(nspname));
-                                       appendPQExpBuffer(buf, "%s AS\n", fmtId(relname));
-                                       appendPQExpBufferStr(buf, viewdef);
+                                       appendPQExpBufferStr(buf, fmtId(relname));
+
+                                       /* reloptions, if not an empty array "{}" */
+                                       if (reloptions != NULL && strlen(reloptions) > 2)
+                                       {
+                                               appendPQExpBufferStr(buf, "\n WITH (");
+                                               if (!appendReloptionsArray(buf, reloptions, "",
+                                                                                                  pset.encoding,
+                                                                                                  standard_strings()))
+                                               {
+                                                       psql_error("Could not parse reloptions array\n");
+                                                       result = false;
+                                               }
+                                               appendPQExpBufferStr(buf, ")");
+                                       }
+
+                                       /* View definition from pg_get_viewdef (a SELECT query) */
+                                       appendPQExpBuffer(buf, " AS\n%s", viewdef);
+
                                        /* Get rid of the semicolon that pg_get_viewdef appends */
                                        if (buf->len > 0 && buf->data[buf->len - 1] == ';')
                                                buf->data[--(buf->len)] = '\0';
+
+                                       /* WITH [LOCAL|CASCADED] CHECK OPTION */
+                                       if (checkoption && checkoption[0] != '\0')
+                                               appendPQExpBuffer(buf, "\n WITH %s CHECK OPTION",
+                                                                                 checkoption);
                                }
                                break;
                }