From 9b66aa006f81b2705337ca223daeeabf4db6453a Mon Sep 17 00:00:00 2001 From: Dean Rasheed Date: Fri, 6 May 2016 12:48:27 +0100 Subject: [PATCH] Fix psql's \ev and \sv commands so that they handle view reloptions. 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 | 77 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 70 insertions(+), 7 deletions(-) diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index 4fa7760a2a..87adfce9c1 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -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; } -- 2.40.0