]> granicus.if.org Git - postgresql/commitdiff
Complete tab completion for DROP STATISTICS
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Sat, 13 May 2017 04:05:48 +0000 (01:05 -0300)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Sat, 13 May 2017 04:05:48 +0000 (01:05 -0300)
Tab-completing DROP STATISTICS would only work if you started writing
the schema name containing the statistics object, because the visibility
clause was missing.  To add it, we need to add SQL-callable support for
testing visibility of a statistics object, like all other object types
already have.

Discussion: https://postgr.es/m/22676.1494557205@sss.pgh.pa.us

doc/src/sgml/func.sgml
src/backend/catalog/namespace.c
src/backend/utils/cache/lsyscache.c
src/bin/psql/tab-complete.c
src/include/catalog/catversion.h
src/include/catalog/namespace.h
src/include/catalog/pg_proc.h

index 5f47c59f8ad01797cfca9a7e039476513a26ea20..d55656769b260c4cfc2fcfe1b63a81dfedd19ccc 100644 (file)
@@ -16680,6 +16680,12 @@ SELECT relname FROM pg_class WHERE pg_table_is_visible(oid);
        <entry><type>boolean</type></entry>
        <entry>is operator family visible in search path</entry>
       </row>
+      <row>
+       <entry><literal><function>pg_statistic_ext_is_visible(<parameter>stat_oid</parameter>)</function></literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>is statistics object visible in search path</entry>
+      </row>
       <row>
        <entry><literal><function>pg_table_is_visible(<parameter>table_oid</parameter>)</function></literal>
        </entry>
@@ -16738,6 +16744,9 @@ SELECT relname FROM pg_class WHERE pg_table_is_visible(oid);
    <indexterm>
     <primary>pg_opfamily_is_visible</primary>
    </indexterm>
+   <indexterm>
+    <primary>pg_statistic_ext_is_visible</primary>
+   </indexterm>
    <indexterm>
     <primary>pg_table_is_visible</primary>
    </indexterm>
index e521bd908a22ff24a25a91554d5689b30cdf4029..5b339222af1a28a0f0db4c63adf7ff9107b435a9 100644 (file)
@@ -34,6 +34,7 @@
 #include "catalog/pg_operator.h"
 #include "catalog/pg_opfamily.h"
 #include "catalog/pg_proc.h"
+#include "catalog/pg_statistic_ext.h"
 #include "catalog/pg_ts_config.h"
 #include "catalog/pg_ts_dict.h"
 #include "catalog/pg_ts_parser.h"
@@ -2141,6 +2142,72 @@ get_statistics_oid(List *names, bool missing_ok)
        return stats_oid;
 }
 
+/*
+ * StatisticsObjIsVisible
+ *             Determine whether a statistics object (identified by OID) is visible in
+ *             the current search path.  Visible means "would be found by searching
+ *             for the unqualified statistics object name".
+ */
+bool
+StatisticsObjIsVisible(Oid relid)
+{
+       HeapTuple       stxtup;
+       Form_pg_statistic_ext stxform;
+       Oid                     stxnamespace;
+       bool            visible;
+
+       stxtup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(relid));
+       if (!HeapTupleIsValid(stxtup))
+               elog(ERROR, "cache lookup failed for statistics object %u", relid);
+       stxform = (Form_pg_statistic_ext) GETSTRUCT(stxtup);
+
+       recomputeNamespacePath();
+
+       /*
+        * Quick check: if it ain't in the path at all, it ain't visible. Items in
+        * the system namespace are surely in the path and so we needn't even do
+        * list_member_oid() for them.
+        */
+       stxnamespace = stxform->stxnamespace;
+       if (stxnamespace != PG_CATALOG_NAMESPACE &&
+               !list_member_oid(activeSearchPath, stxnamespace))
+               visible = false;
+       else
+       {
+               /*
+                * If it is in the path, it might still not be visible; it could be
+                * hidden by another statistics object of the same name earlier in the
+                * path. So we must do a slow check for conflicting objects.
+                */
+               char       *stxname = NameStr(stxform->stxname);
+               ListCell   *l;
+
+               visible = false;
+               foreach(l, activeSearchPath)
+               {
+                       Oid                     namespaceId = lfirst_oid(l);
+
+                       if (namespaceId == stxnamespace)
+                       {
+                               /* Found it first in path */
+                               visible = true;
+                               break;
+                       }
+                       if (SearchSysCacheExists2(STATEXTNAMENSP,
+                                                                         PointerGetDatum(stxname),
+                                                                         ObjectIdGetDatum(namespaceId)))
+                       {
+                               /* Found something else first in path */
+                               break;
+                       }
+               }
+       }
+
+       ReleaseSysCache(stxtup);
+
+       return visible;
+}
+
 /*
  * get_ts_parser_oid - find a TS parser by possibly qualified name
  *
@@ -4235,6 +4302,17 @@ pg_conversion_is_visible(PG_FUNCTION_ARGS)
        PG_RETURN_BOOL(ConversionIsVisible(oid));
 }
 
+Datum
+pg_statistic_ext_is_visible(PG_FUNCTION_ARGS)
+{
+       Oid                     oid = PG_GETARG_OID(0);
+
+       if (!SearchSysCacheExists1(STATEXTOID, ObjectIdGetDatum(oid)))
+               PG_RETURN_NULL();
+
+       PG_RETURN_BOOL(StatisticsObjIsVisible(oid));
+}
+
 Datum
 pg_ts_parser_is_visible(PG_FUNCTION_ARGS)
 {
index 236d876b1c614e0f85726cbe51e28014eb3c8ae1..720e54027682f26a23c9ff651f992995bcfa5484 100644 (file)
@@ -32,6 +32,7 @@
 #include "catalog/pg_proc.h"
 #include "catalog/pg_range.h"
 #include "catalog/pg_statistic.h"
+#include "catalog/pg_statistic_ext.h"
 #include "catalog/pg_transform.h"
 #include "catalog/pg_type.h"
 #include "miscadmin.h"
index 09fb30f270cf715bd627c173a9bddd97ec416890..ae3730257d106ede1b5a43998a564c1ee5ace29d 100644 (file)
@@ -622,7 +622,7 @@ static const SchemaQuery Query_for_list_of_statistics = {
        /* selcondition */
        NULL,
        /* viscondition */
-       NULL,
+       "pg_catalog.pg_statistic_ext_is_visible(s.oid)",
        /* namespace */
        "s.stxnamespace",
        /* result */
index 85ee2f6bdee985c945230fad8dff086e5a814074..8e5b95a5eea19cbbc48b6f8e6d3efcc79495981e 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     201705121
+#define CATALOG_VERSION_NO     201705122
 
 #endif
index 35e0e2b089b7811c69daa60346a489d3e4dcc962..959ee4c50e992d20f07dca7a5cfcddaf112c51b7 100644 (file)
@@ -92,6 +92,9 @@ extern bool CollationIsVisible(Oid collid);
 extern Oid     ConversionGetConid(const char *conname);
 extern bool ConversionIsVisible(Oid conid);
 
+extern Oid     get_statistics_oid(List *names, bool missing_ok);
+extern bool StatisticsObjIsVisible(Oid stxid);
+
 extern Oid     get_ts_parser_oid(List *names, bool missing_ok);
 extern bool TSParserIsVisible(Oid prsId);
 
@@ -141,7 +144,6 @@ extern Oid  get_collation_oid(List *collname, bool missing_ok);
 extern Oid     get_conversion_oid(List *conname, bool missing_ok);
 extern Oid     FindDefaultConversionProc(int32 for_encoding, int32 to_encoding);
 
-extern Oid     get_statistics_oid(List *names, bool missing_ok);
 
 /* initialization & transaction cleanup code */
 extern void InitializeSearchPath(void);
index 77d8ed51849f836b70efc25bd08890a585a98ace..8d84d9a8908ce9a79ee6f3848ef8a2043a2f0b24 100644 (file)
@@ -3181,6 +3181,8 @@ DATA(insert OID = 3829 (  pg_opfamily_is_visible  PGNSP PGUID 12 10 0 0 0 f f f f
 DESCR("is opfamily visible in search path?");
 DATA(insert OID = 2093 (  pg_conversion_is_visible     PGNSP PGUID 12 10 0 0 0 f f f f t f s s 1 0 16 "26" _null_ _null_ _null_ _null_ _null_ pg_conversion_is_visible _null_ _null_ _null_ ));
 DESCR("is conversion visible in search path?");
+DATA(insert OID = 3403 (  pg_statistic_ext_is_visible  PGNSP PGUID 12 10 0 0 0 f f f f t f s s 1 0 16 "26" _null_ _null_ _null_ _null_ _null_ pg_statistic_ext_is_visible _null_ _null_ _null_ ));
+DESCR("is statistics object visible in search path?");
 DATA(insert OID = 3756 (  pg_ts_parser_is_visible      PGNSP PGUID 12 10 0 0 0 f f f f t f s s 1 0 16 "26" _null_ _null_ _null_ _null_ _null_ pg_ts_parser_is_visible _null_ _null_ _null_ ));
 DESCR("is text search parser visible in search path?");
 DATA(insert OID = 3757 (  pg_ts_dict_is_visible                PGNSP PGUID 12 10 0 0 0 f f f f t f s s 1 0 16 "26" _null_ _null_ _null_ _null_ _null_ pg_ts_dict_is_visible _null_ _null_ _null_ ));