summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlvaro Herrera <alvherre@alvh.no-ip.org>2017-05-13 01:05:48 -0300
committerAlvaro Herrera <alvherre@alvh.no-ip.org>2017-05-13 01:05:48 -0300
commitd99d58cdc8c0b5b50ee92995e8575c100b1a458a (patch)
tree69410eae02097c010e21eb7972524a80538e87d5
parent2df5d465558b6f17c161cbbe246b050b453ec99c (diff)
downloadpostgresql-d99d58cdc8c0b5b50ee92995e8575c100b1a458a.tar.gz
Complete tab completion for DROP STATISTICS
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
-rw-r--r--doc/src/sgml/func.sgml9
-rw-r--r--src/backend/catalog/namespace.c78
-rw-r--r--src/backend/utils/cache/lsyscache.c1
-rw-r--r--src/bin/psql/tab-complete.c2
-rw-r--r--src/include/catalog/catversion.h2
-rw-r--r--src/include/catalog/namespace.h4
-rw-r--r--src/include/catalog/pg_proc.h2
7 files changed, 95 insertions, 3 deletions
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 5f47c59f8a..d55656769b 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -16681,6 +16681,12 @@ SELECT relname FROM pg_class WHERE pg_table_is_visible(oid);
<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>
<entry><type>boolean</type></entry>
@@ -16739,6 +16745,9 @@ SELECT relname FROM pg_class WHERE pg_table_is_visible(oid);
<primary>pg_opfamily_is_visible</primary>
</indexterm>
<indexterm>
+ <primary>pg_statistic_ext_is_visible</primary>
+ </indexterm>
+ <indexterm>
<primary>pg_table_is_visible</primary>
</indexterm>
<indexterm>
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index e521bd908a..5b339222af 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -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"
@@ -2142,6 +2143,72 @@ get_statistics_oid(List *names, bool missing_ok)
}
/*
+ * 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
*
* If not found, returns InvalidOid if missing_ok, else throws error
@@ -4236,6 +4303,17 @@ pg_conversion_is_visible(PG_FUNCTION_ARGS)
}
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)
{
Oid oid = PG_GETARG_OID(0);
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index 236d876b1c..720e540276 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -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"
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 09fb30f270..ae3730257d 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -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 */
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 85ee2f6bde..8e5b95a5ee 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 201705121
+#define CATALOG_VERSION_NO 201705122
#endif
diff --git a/src/include/catalog/namespace.h b/src/include/catalog/namespace.h
index 35e0e2b089..959ee4c50e 100644
--- a/src/include/catalog/namespace.h
+++ b/src/include/catalog/namespace.h
@@ -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);
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 77d8ed5184..8d84d9a890 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -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_ ));