]> granicus.if.org Git - postgresql/commitdiff
psql: Add tab completion for logical replication
authorPeter Eisentraut <peter_e@gmx.net>
Fri, 3 Mar 2017 19:13:48 +0000 (14:13 -0500)
committerPeter Eisentraut <peter_e@gmx.net>
Fri, 3 Mar 2017 19:13:48 +0000 (14:13 -0500)
Add tab completion for publications and subscriptions.  Also, to be able
to get a list of subscriptions, make pg_subscription world-readable but
revoke access to subconninfo using column privileges.

From: Michael Paquier <michael.paquier@gmail.com>

doc/src/sgml/catalogs.sgml
src/backend/catalog/system_views.sql
src/bin/psql/tab-complete.c
src/include/catalog/catversion.h
src/include/catalog/pg_subscription.h

index 96cb9185c264a6d4f618c9e01a60e93e4a6b172c..41e3e1b547ddae493549176f56b15bd721d3f9e9 100644 (file)
   </para>
 
   <para>
-   Access to this catalog is restricted from normal users.  Normal users can
-   use the view <xref linkend="pg-stat-subscription"> to get some information
-   about subscriptions.
+   Access to the column <structfield>subconninfo</structfield> is revoked from
+   normal users, because it could contain plain-text passwords.
   </para>
 
   <table>
index ada542c530b2f67d64ef37bf3ad978f9551f89d1..ba980de86bbf5f71f458b217db8123c498246fc8 100644 (file)
@@ -900,7 +900,11 @@ CREATE VIEW pg_replication_origin_status AS
 
 REVOKE ALL ON pg_replication_origin_status FROM public;
 
+-- All columns of pg_subscription except subconninfo are readable.
 REVOKE ALL ON pg_subscription FROM public;
+GRANT SELECT (subdbid, subname, subowner, subenabled, subslotname, subpublications)
+    ON pg_subscription TO public;
+
 
 --
 -- We have a few function definitions in here, too.
index 115cb5ce716cef6c44714651b5ae5488ed8c4385..4a65ff5b6200169a502006fadbb3a9cdb66110eb 100644 (file)
@@ -845,6 +845,18 @@ static const SchemaQuery Query_for_list_of_matviews = {
 "   FROM pg_catalog.pg_am "\
 "  WHERE substring(pg_catalog.quote_ident(amname),1,%d)='%s'"
 
+#define Query_for_list_of_publications \
+" SELECT pg_catalog.quote_ident(pubname) "\
+"   FROM pg_catalog.pg_publication "\
+"  WHERE substring(pg_catalog.quote_ident(pubname),1,%d)='%s'"
+
+#define Query_for_list_of_subscriptions \
+" SELECT pg_catalog.quote_ident(s.subname) "\
+"   FROM pg_catalog.pg_subscription s, pg_catalog.pg_database d "\
+"  WHERE substring(pg_catalog.quote_ident(s.subname),1,%d)='%s' "\
+"    AND d.datname = pg_catalog.current_database() "\
+"    AND s.subdbid = d.oid"
+
 /* the silly-looking length condition is just to eat up the current word */
 #define Query_for_list_of_arguments \
 "SELECT pg_catalog.oidvectortypes(proargtypes)||')' "\
@@ -985,13 +997,13 @@ static const pgsql_thing_t words_after_create[] = {
        {"OWNED", NULL, NULL, THING_NO_CREATE},         /* for DROP OWNED BY ... */
        {"PARSER", Query_for_list_of_ts_parsers, NULL, THING_NO_SHOW},
        {"POLICY", NULL, NULL},
-       {"PUBLICATION", NULL, NULL},
+       {"PUBLICATION", Query_for_list_of_publications},
        {"ROLE", Query_for_list_of_roles},
        {"RULE", "SELECT pg_catalog.quote_ident(rulename) FROM pg_catalog.pg_rules WHERE substring(pg_catalog.quote_ident(rulename),1,%d)='%s'"},
        {"SCHEMA", Query_for_list_of_schemas},
        {"SEQUENCE", NULL, &Query_for_list_of_sequences},
        {"SERVER", Query_for_list_of_servers},
-       {"SUBSCRIPTION", NULL, NULL},
+       {"SUBSCRIPTION", Query_for_list_of_subscriptions},
        {"TABLE", NULL, &Query_for_list_of_tables},
        {"TABLESPACE", Query_for_list_of_tablespaces},
        {"TEMP", NULL, NULL, THING_NO_DROP},            /* for CREATE TEMP TABLE ... */
@@ -2374,8 +2386,13 @@ psql_completion(const char *text, int start, int end)
 /* CREATE SUBSCRIPTION */
        else if (Matches3("CREATE", "SUBSCRIPTION", MatchAny))
                COMPLETE_WITH_CONST("CONNECTION");
-       else if (Matches5("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION",MatchAny))
+       else if (Matches5("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION", MatchAny))
                COMPLETE_WITH_CONST("PUBLICATION");
+       else if (Matches6("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION",
+                                         MatchAny, "PUBLICATION"))
+       {
+               /* complete with nothing here as this refers to remote publications */
+       }
        /* Complete "CREATE SUBSCRIPTION <name> ...  WITH ( <opt>" */
        else if (HeadMatches2("CREATE", "SUBSCRIPTION") && TailMatches2("WITH", "("))
                COMPLETE_WITH_LIST5("ENABLED", "DISABLED", "CREATE SLOT",
index 57fbc9509ed745a8569c967756defc90bda9cb3c..438378d8faf378810c4e4289840b730b2ee8ec3c 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     201703031
+#define CATALOG_VERSION_NO     201703032
 
 #endif
index 75b618accd664fca33b2410107d7168597f03469..0811880a8f37c772aa6832ec433c8bfba3856e96 100644 (file)
@@ -27,6 +27,8 @@
  * seems weird, but the replication launcher process needs to access all of
  * them to be able to start the workers, so we have to put them in a shared,
  * nailed catalog.
+ *
+ * NOTE:  When adding a column, also update system_views.sql.
  */
 CATALOG(pg_subscription,6100) BKI_SHARED_RELATION BKI_ROWTYPE_OID(6101) BKI_SCHEMA_MACRO
 {