Standardize terminology for pg_statistic_ext entries.

Consistently refer to such an entry as a "statistics object", not just
"statistics" or "extended statistics".  Previously we had a mismash of
terms, accompanied by utter confusion as to whether the term was
singular or plural.  That's not only grating (at least to the ear of
a native English speaker) but could be outright misleading, eg in error
messages that seemed to be referring to multiple objects where only one
could be meant.

This commit fixes the code and a lot of comments (though I may have
missed a few).  I also renamed two new SQL functions,
pg_get_statisticsextdef -> pg_get_statisticsobjdef
pg_statistic_ext_is_visible -> pg_statistics_obj_is_visible
to conform better with this terminology.

I have not touched the SGML docs other than fixing those function
names; the docs certainly need work but it seems like a separable task.

Discussion: https://postgr.es/m/22676.1494557205@sss.pgh.pa.us
This commit is contained in:
Tom Lane 2017-05-14 10:54:47 -04:00
parent 12ad38b3b4
commit f04c9a6146
31 changed files with 133 additions and 125 deletions

View File

@ -16681,7 +16681,7 @@ 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><literal><function>pg_statistics_obj_is_visible(<parameter>stat_oid</parameter>)</function></literal>
</entry>
<entry><type>boolean</type></entry>
<entry>is statistics object visible in search path</entry>
@ -16745,7 +16745,7 @@ 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>
<primary>pg_statistics_obj_is_visible</primary>
</indexterm>
<indexterm>
<primary>pg_table_is_visible</primary>
@ -16836,7 +16836,7 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
</indexterm>
<indexterm>
<primary>pg_get_statisticsextdef</primary>
<primary>pg_get_statisticsobjdef</primary>
</indexterm>
<indexterm>
@ -17009,9 +17009,9 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
uses</entry>
</row>
<row>
<entry><literal><function>pg_get_statisticsextdef(<parameter>statext_oid</parameter>)</function></literal></entry>
<entry><literal><function>pg_get_statisticsobjdef(<parameter>statobj_oid</parameter>)</function></literal></entry>
<entry><type>text</type></entry>
<entry>get <command>CREATE STATISTICS</> command for extended statistics objects</entry>
<entry>get <command>CREATE STATISTICS</> command for extended statistics object</entry>
</row>
<row>
<entry><function>pg_get_triggerdef</function>(<parameter>trigger_oid</parameter>)</entry>
@ -17158,7 +17158,7 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
<para>
<function>pg_get_constraintdef</function>,
<function>pg_get_indexdef</function>, <function>pg_get_ruledef</function>,
<function>pg_get_statisticsextdef</function>, and
<function>pg_get_statisticsobjdef</function>, and
<function>pg_get_triggerdef</function>, respectively reconstruct the
creating command for a constraint, index, rule, extended statistics object,
or trigger. (Note that this is a decompiled reconstruction, not the

View File

@ -3321,7 +3321,7 @@ static const char *const no_priv_msg[MAX_ACL_KIND] =
/* ACL_KIND_CONVERSION */
gettext_noop("permission denied for conversion %s"),
/* ACL_KIND_STATISTICS */
gettext_noop("permission denied for statistics %s"),
gettext_noop("permission denied for statistics object %s"),
/* ACL_KIND_TABLESPACE */
gettext_noop("permission denied for tablespace %s"),
/* ACL_KIND_TSDICTIONARY */
@ -3373,7 +3373,7 @@ static const char *const not_owner_msg[MAX_ACL_KIND] =
/* ACL_KIND_CONVERSION */
gettext_noop("must be owner of conversion %s"),
/* ACL_KIND_STATISTICS */
gettext_noop("must be owner of statistics %s"),
gettext_noop("must be owner of statistics object %s"),
/* ACL_KIND_TABLESPACE */
gettext_noop("must be owner of tablespace %s"),
/* ACL_KIND_TSDICTIONARY */
@ -3490,7 +3490,7 @@ pg_aclmask(AclObjectKind objkind, Oid table_oid, AttrNumber attnum, Oid roleid,
case ACL_KIND_NAMESPACE:
return pg_namespace_aclmask(table_oid, roleid, mask, how);
case ACL_KIND_STATISTICS:
elog(ERROR, "grantable rights not supported for statistics");
elog(ERROR, "grantable rights not supported for statistics objects");
/* not reached, but keep compiler quiet */
return ACL_NO_RIGHTS;
case ACL_KIND_TABLESPACE:
@ -5130,10 +5130,10 @@ pg_subscription_ownercheck(Oid sub_oid, Oid roleid)
}
/*
* Ownership check for a extended statistics (specified by OID).
* Ownership check for a statistics object (specified by OID).
*/
bool
pg_statistics_ownercheck(Oid stat_oid, Oid roleid)
pg_statistics_object_ownercheck(Oid stat_oid, Oid roleid)
{
HeapTuple tuple;
Oid ownerId;
@ -5146,7 +5146,8 @@ pg_statistics_ownercheck(Oid stat_oid, Oid roleid)
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("statistics with OID %u do not exist", stat_oid)));
errmsg("statistics object with OID %u does not exist",
stat_oid)));
ownerId = ((Form_pg_statistic_ext) GETSTRUCT(tuple))->stxowner;

View File

@ -2087,12 +2087,12 @@ ConversionIsVisible(Oid conid)
}
/*
* get_statistics_oid - find a statistics by possibly qualified name
* get_statistics_object_oid - find a statistics object by possibly qualified name
*
* If not found, returns InvalidOid if missing_ok, else throws error
*/
Oid
get_statistics_oid(List *names, bool missing_ok)
get_statistics_object_oid(List *names, bool missing_ok)
{
char *schemaname;
char *stats_name;
@ -2136,7 +2136,7 @@ get_statistics_oid(List *names, bool missing_ok)
if (!OidIsValid(stats_oid) && !missing_ok)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("statistics \"%s\" do not exist",
errmsg("statistics object \"%s\" does not exist",
NameListToString(names))));
return stats_oid;
@ -4303,7 +4303,7 @@ pg_conversion_is_visible(PG_FUNCTION_ARGS)
}
Datum
pg_statistic_ext_is_visible(PG_FUNCTION_ARGS)
pg_statistics_obj_is_visible(PG_FUNCTION_ARGS)
{
Oid oid = PG_GETARG_OID(0);

View File

@ -712,7 +712,7 @@ static const struct object_type_map
},
/* OBJECT_STATISTIC_EXT */
{
"statistics", OBJECT_STATISTIC_EXT
"statistics object", OBJECT_STATISTIC_EXT
}
};
@ -993,8 +993,8 @@ get_object_address(ObjectType objtype, Node *object,
break;
case OBJECT_STATISTIC_EXT:
address.classId = StatisticExtRelationId;
address.objectId = get_statistics_oid(castNode(List, object),
missing_ok);
address.objectId = get_statistics_object_oid(castNode(List, object),
missing_ok);
address.objectSubId = 0;
break;
default:
@ -2398,7 +2398,7 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
errmsg("must be superuser")));
break;
case OBJECT_STATISTIC_EXT:
if (!pg_statistics_ownercheck(address.objectId, roleid))
if (!pg_statistics_object_ownercheck(address.objectId, roleid))
aclcheck_error_type(ACLCHECK_NOT_OWNER, address.objectId);
break;
default:
@ -3907,11 +3907,12 @@ getObjectTypeDescription(const ObjectAddress *object)
break;
case OCLASS_STATISTIC_EXT:
appendStringInfoString(&buffer, "statistics");
appendStringInfoString(&buffer, "statistics object");
break;
default:
appendStringInfo(&buffer, "unrecognized %u", object->classId);
appendStringInfo(&buffer, "unrecognized object class %u",
object->classId);
break;
}
@ -4946,7 +4947,7 @@ getObjectIdentityParts(const ObjectAddress *object,
tup = SearchSysCache1(STATEXTOID,
ObjectIdGetDatum(object->objectId));
if (!HeapTupleIsValid(tup))
elog(ERROR, "cache lookup failed for statistics %u",
elog(ERROR, "cache lookup failed for statistics object %u",
object->objectId);
formStatistic = (Form_pg_statistic_ext) GETSTRUCT(tup);
schema = get_namespace_name_or_temp(formStatistic->stxnamespace);

View File

@ -123,7 +123,7 @@ report_namespace_conflict(Oid classId, const char *name, Oid nspOid)
break;
case StatisticExtRelationId:
Assert(OidIsValid(nspOid));
msgfmt = gettext_noop("statistics \"%s\" already exists in schema \"%s\"");
msgfmt = gettext_noop("statistics object \"%s\" already exists in schema \"%s\"");
break;
case TSParserRelationId:
Assert(OidIsValid(nspOid));

View File

@ -289,7 +289,7 @@ does_not_exist_skipping(ObjectType objtype, Node *object)
case OBJECT_STATISTIC_EXT:
if (!schema_does_not_exist_skipping(castNode(List, object), &msg, &name))
{
msg = gettext_noop("extended statistics \"%s\" do not exist, skipping");
msg = gettext_noop("statistics object \"%s\" does not exist, skipping");
name = NameListToString(castNode(List, object));
}
break;

View File

@ -1,7 +1,7 @@
/*-------------------------------------------------------------------------
*
* statscmds.c
* Commands for creating and altering extended statistics
* Commands for creating and altering extended statistics objects
*
* Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
@ -64,7 +64,7 @@ CreateStatistics(CreateStatsStmt *stmt)
Oid relid;
ObjectAddress parentobject,
myself;
Datum types[2]; /* one for each possible type of statistics */
Datum types[2]; /* one for each possible type of statistic */
int ntypes;
ArrayType *stxkind;
bool build_ndistinct;
@ -80,7 +80,7 @@ CreateStatistics(CreateStatsStmt *stmt)
namestrcpy(&stxname, namestr);
/*
* Deal with the possibility that the named statistics already exist.
* Deal with the possibility that the statistics object already exists.
*/
if (SearchSysCacheExists2(STATEXTNAMENSP,
NameGetDatum(&stxname),
@ -90,14 +90,14 @@ CreateStatistics(CreateStatsStmt *stmt)
{
ereport(NOTICE,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("statistics \"%s\" already exist, skipping",
errmsg("statistics object \"%s\" already exists, skipping",
namestr)));
return InvalidObjectAddress;
}
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("statistics \"%s\" already exist", namestr)));
errmsg("statistics object \"%s\" already exists", namestr)));
}
/*
@ -263,7 +263,7 @@ CreateStatistics(CreateStatsStmt *stmt)
else
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("unrecognized statistics type \"%s\"",
errmsg("unrecognized statistic type \"%s\"",
type)));
}
/* If no statistic type was specified, build them all. */
@ -307,7 +307,7 @@ CreateStatistics(CreateStatsStmt *stmt)
relation_close(statrel, RowExclusiveLock);
/*
* Invalidate relcache so that others see the new statistics.
* Invalidate relcache so that others see the new statistics object.
*/
CacheInvalidateRelcache(rel);
@ -346,7 +346,7 @@ CreateStatistics(CreateStatsStmt *stmt)
}
/*
* Guts of statistics deletion.
* Guts of statistics object deletion.
*/
void
RemoveStatisticsById(Oid statsOid)
@ -365,7 +365,7 @@ RemoveStatisticsById(Oid statsOid)
tup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(statsOid));
if (!HeapTupleIsValid(tup)) /* should not happen */
elog(ERROR, "cache lookup failed for statistics %u", statsOid);
elog(ERROR, "cache lookup failed for statistics object %u", statsOid);
statext = (Form_pg_statistic_ext) GETSTRUCT(tup);
relid = statext->stxrelid;

View File

@ -1285,13 +1285,13 @@ get_relation_statistics(RelOptInfo *rel, Relation relation)
htup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(statOid));
if (!htup)
elog(ERROR, "cache lookup failed for statistics %u", statOid);
elog(ERROR, "cache lookup failed for statistics object %u", statOid);
staForm = (Form_pg_statistic_ext) GETSTRUCT(htup);
/*
* First, build the array of columns covered. This is ultimately
* wasted if no stats are actually built, but it doesn't seem worth
* troubling over that case.
* wasted if no stats within the object have actually been built, but
* it doesn't seem worth troubling over that case.
*/
for (i = 0; i < staForm->stxkeys.dim1; i++)
keys = bms_add_member(keys, staForm->stxkeys.values[i]);

View File

@ -12,7 +12,7 @@ hopefully improving the estimates and producing better plans.
Types of statistics
-------------------
There are two kinds of extended statistics:
There are currently two kinds of extended statistics:
(a) ndistinct coefficients
@ -36,7 +36,7 @@ Complex clauses
We also support estimating more complex clauses - essentially AND/OR clauses
with (Var op Const) as leaves, as long as all the referenced attributes are
covered by a single statistics.
covered by a single statistics object.
For example this condition
@ -59,7 +59,7 @@ Selectivity estimation
Throughout the planner clauselist_selectivity() still remains in charge of
most selectivity estimate requests. clauselist_selectivity() can be instructed
to try to make use of any extended statistics on the given RelOptInfo, which
it will do, if:
it will do if:
(a) An actual valid RelOptInfo was given. Join relations are passed in as
NULL, therefore are invalid.
@ -77,6 +77,7 @@ performing estimations knows which clauses are to be skipped.
Size of sample in ANALYZE
-------------------------
When performing ANALYZE, the number of rows to sample is determined as
(300 * statistics_target)
@ -93,4 +94,4 @@ those are not necessarily limited by statistics_target.
This however merits further discussion, because collecting the sample is quite
expensive and increasing it further would make ANALYZE even more painful.
Judging by the experiments with the current implementation, the fixed size
seems to work reasonably well for now, so we leave this as a future work.
seems to work reasonably well for now, so we leave this as future work.

View File

@ -48,7 +48,7 @@ rendering the approach mostly useless even for slightly noisy data sets, or
result in sudden changes in behavior depending on minor differences between
samples provided to ANALYZE.
For this reason, the statistics implements "soft" functional dependencies,
For this reason, extended statistics implement "soft" functional dependencies,
associating each functional dependency with a degree of validity (a number
between 0 and 1). This degree is then used to combine selectivities in a
smooth manner.

View File

@ -342,8 +342,8 @@ dependency_degree(int numrows, HeapTuple *rows, int k, AttrNumber *dependency,
* detects functional dependencies between groups of columns
*
* Generates all possible subsets of columns (variations) and computes
* the degree of validity for each one. For example with a statistic on
* three columns (a,b,c) there are 9 possible dependencies
* the degree of validity for each one. For example when creating statistics
* on three columns (a,b,c) there are 9 possible dependencies
*
* two columns three columns
* ----------- -------------
@ -383,8 +383,8 @@ statext_dependencies_build(int numrows, HeapTuple *rows, Bitmapset *attrs,
/*
* We'll try build functional dependencies starting from the smallest ones
* covering just 2 columns, to the largest ones, covering all columns
* included in the statistics. We start from the smallest ones because we
* want to be able to skip already implied ones.
* included in the statistics object. We start from the smallest ones
* because we want to be able to skip already implied ones.
*/
for (k = 2; k <= numattrs; k++)
{
@ -644,7 +644,7 @@ staext_dependencies_load(Oid mvoid)
HeapTuple htup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(mvoid));
if (!HeapTupleIsValid(htup))
elog(ERROR, "cache lookup failed for extended statistics %u", mvoid);
elog(ERROR, "cache lookup failed for statistics object %u", mvoid);
deps = SysCacheGetAttr(STATEXTOID, htup,
Anum_pg_statistic_ext_stxdependencies, &isnull);
@ -975,7 +975,7 @@ dependencies_clauselist_selectivity(PlannerInfo *root,
return 1.0;
}
/* find the best suited statistics for these attnums */
/* find the best suited statistics object for these attnums */
stat = choose_best_statistics(rel->statlist, clauses_attnums,
STATS_EXT_DEPENDENCIES);
@ -986,7 +986,7 @@ dependencies_clauselist_selectivity(PlannerInfo *root,
return 1.0;
}
/* load the dependency items stored in the statistics */
/* load the dependency items stored in the statistics object */
dependencies = staext_dependencies_load(stat->statOid);
/*

View File

@ -3,7 +3,7 @@
* extended_stats.c
* POSTGRES extended statistics
*
* Generic code supporting statistic objects created via CREATE STATISTICS.
* Generic code supporting statistics objects created via CREATE STATISTICS.
*
*
* Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
@ -35,14 +35,15 @@
/*
* Used internally to refer to an individual pg_statistic_ext entry.
* Used internally to refer to an individual statistics object, i.e.,
* a pg_statistic_ext entry.
*/
typedef struct StatExtEntry
{
Oid statOid; /* OID of pg_statistic_ext entry */
char *schema; /* statistics schema */
char *name; /* statistics name */
Bitmapset *columns; /* attribute numbers covered by the statistics */
char *schema; /* statistics object's schema */
char *name; /* statistics object's name */
Bitmapset *columns; /* attribute numbers covered by the object */
List *types; /* 'char' list of enabled statistic kinds */
} StatExtEntry;
@ -59,8 +60,8 @@ static void statext_store(Relation pg_stext, Oid relid,
* Compute requested extended stats, using the rows sampled for the plain
* (single-column) stats.
*
* This fetches a list of stats from pg_statistic_ext, computes the stats
* and serializes them back into the catalog (as bytea values).
* This fetches a list of stats types from pg_statistic_ext, computes the
* requested stats, and serializes them back into the catalog.
*/
void
BuildRelationExtStatistics(Relation onerel, double totalrows,
@ -98,7 +99,7 @@ BuildRelationExtStatistics(Relation onerel, double totalrows,
{
ereport(WARNING,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("extended statistics \"%s.%s\" could not be collected for relation %s.%s",
errmsg("statistics object \"%s.%s\" could not be computed for relation \"%s.%s\"",
stat->schema, stat->name,
get_namespace_name(onerel->rd_rel->relnamespace),
RelationGetRelationName(onerel)),
@ -110,7 +111,7 @@ BuildRelationExtStatistics(Relation onerel, double totalrows,
Assert(bms_num_members(stat->columns) >= 2 &&
bms_num_members(stat->columns) <= STATS_MAX_DIMENSIONS);
/* compute statistic of each type */
/* compute statistic of each requested type */
foreach(lc2, stat->types)
{
char t = (char) lfirst_int(lc2);
@ -160,7 +161,7 @@ statext_is_kind_built(HeapTuple htup, char type)
}
/*
* Return a list (of StatExtEntry) of statistics for the given relation.
* Return a list (of StatExtEntry) of statistics objects for the given relation.
*/
static List *
fetch_statentries_for_relation(Relation pg_statext, Oid relid)
@ -171,7 +172,7 @@ fetch_statentries_for_relation(Relation pg_statext, Oid relid)
List *result = NIL;
/*
* Prepare to scan pg_statistic_ext for entries having indrelid = this
* Prepare to scan pg_statistic_ext for entries having stxrelid = this
* rel.
*/
ScanKeyInit(&skey,
@ -329,7 +330,7 @@ statext_store(Relation pg_stext, Oid statOid,
/* there should already be a pg_statistic_ext tuple */
oldtup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(statOid));
if (!HeapTupleIsValid(oldtup))
elog(ERROR, "cache lookup failed for extended statistics %u", statOid);
elog(ERROR, "cache lookup failed for statistics object %u", statOid);
/* replace it */
stup = heap_modify_tuple(oldtup,
@ -433,7 +434,7 @@ multi_sort_compare_dims(int start, int end,
/*
* has_stats_of_kind
* Check that the list contains statistic of a given kind
* Check whether the list contains statistic of a given kind
*/
bool
has_stats_of_kind(List *stats, char requiredkind)
@ -458,11 +459,12 @@ has_stats_of_kind(List *stats, char requiredkind)
* there's no match.
*
* The current selection criteria is very simple - we choose the statistics
* referencing the most attributes with the least keys.
* object referencing the most of the requested attributes, breaking ties
* in favor of objects with fewer keys overall.
*
* XXX if multiple statistics exists of the same size matching the same number
* of keys, then the statistics which are chosen depend on the order that they
* appear in the stats list. Perhaps this needs to be more definitive.
* XXX if multiple statistics objects tie on both criteria, then which object
* is chosen depends on the order that they appear in the stats list. Perhaps
* further tiebreakers are needed.
*/
StatisticExtInfo *
choose_best_statistics(List *stats, Bitmapset *attnums, char requiredkind)
@ -479,7 +481,7 @@ choose_best_statistics(List *stats, Bitmapset *attnums, char requiredkind)
int numkeys;
Bitmapset *matched;
/* skip statistics that are not the correct type */
/* skip statistics that are not of the correct type */
if (info->kind != requiredkind)
continue;
@ -495,9 +497,9 @@ choose_best_statistics(List *stats, Bitmapset *attnums, char requiredkind)
numkeys = bms_num_members(info->keys);
/*
* Use these statistics when it increases the number of matched
* clauses or when it matches the same number of attributes but these
* stats have fewer keys than any previous match.
* Use this object when it increases the number of matched clauses or
* when it matches the same number of attributes but these stats have
* fewer keys than any previous match.
*/
if (num_matched > best_num_matched ||
(num_matched == best_num_matched && numkeys < best_match_keys))

View File

@ -9,7 +9,7 @@
* The multivariate ndistinct coefficients address this by storing ndistinct
* estimates for combinations of the user-specified columns. So for example
* given a statistics object on three columns (a,b,c), this module estimates
* and store n-distinct for (a,b), (a,c), (b,c) and (a,b,c). The per-column
* and stores n-distinct for (a,b), (a,c), (b,c) and (a,b,c). The per-column
* estimates are already available in pg_statistic.
*
*
@ -18,6 +18,7 @@
*
* IDENTIFICATION
* src/backend/statistics/mvdistinct.c
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
@ -131,13 +132,13 @@ statext_ndistinct_load(Oid mvoid)
htup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(mvoid));
if (!htup)
elog(ERROR, "cache lookup failed for statistics %u", mvoid);
elog(ERROR, "cache lookup failed for statistics object %u", mvoid);
ndist = SysCacheGetAttr(STATEXTOID, htup,
Anum_pg_statistic_ext_stxndistinct, &isnull);
if (isnull)
elog(ERROR,
"requested statistic kind %c not yet built for statistics %u",
"requested statistic kind %c is not yet built for statistics object %u",
STATS_EXT_NDISTINCT, mvoid);
ReleaseSysCache(htup);

View File

@ -319,7 +319,7 @@ static char *pg_get_indexdef_worker(Oid indexrelid, int colno,
const Oid *excludeOps,
bool attrsOnly, bool showTblSpc,
int prettyFlags, bool missing_ok);
static char *pg_get_statisticsext_worker(Oid statextid, bool missing_ok);
static char *pg_get_statisticsobj_worker(Oid statextid, bool missing_ok);
static char *pg_get_partkeydef_worker(Oid relid, int prettyFlags,
bool attrsOnly, bool missing_ok);
static char *pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
@ -1425,16 +1425,16 @@ pg_get_indexdef_worker(Oid indexrelid, int colno,
}
/*
* pg_get_statisticsextdef
* pg_get_statisticsobjdef
* Get the definition of an extended statistics object
*/
Datum
pg_get_statisticsextdef(PG_FUNCTION_ARGS)
pg_get_statisticsobjdef(PG_FUNCTION_ARGS)
{
Oid statextid = PG_GETARG_OID(0);
char *res;
res = pg_get_statisticsext_worker(statextid, true);
res = pg_get_statisticsobj_worker(statextid, true);
if (res == NULL)
PG_RETURN_NULL();
@ -1446,7 +1446,7 @@ pg_get_statisticsextdef(PG_FUNCTION_ARGS)
* Internal workhorse to decompile an extended statistics object.
*/
static char *
pg_get_statisticsext_worker(Oid statextid, bool missing_ok)
pg_get_statisticsobj_worker(Oid statextid, bool missing_ok)
{
Form_pg_statistic_ext statextrec;
HeapTuple statexttup;
@ -1467,7 +1467,7 @@ pg_get_statisticsext_worker(Oid statextid, bool missing_ok)
{
if (missing_ok)
return NULL;
elog(ERROR, "cache lookup failed for extended statistics %u", statextid);
elog(ERROR, "cache lookup failed for statistics object %u", statextid);
}
statextrec = (Form_pg_statistic_ext) GETSTRUCT(statexttup);
@ -1480,8 +1480,7 @@ pg_get_statisticsext_worker(Oid statextid, bool missing_ok)
NameStr(statextrec->stxname)));
/*
* Lookup the stxkind column so that we know how to handle the WITH
* clause.
* Decode the stxkind column so that we know which stats types to print.
*/
datum = SysCacheGetAttr(STATEXTOID, statexttup,
Anum_pg_statistic_ext_stxkind, &isnull);
@ -1518,7 +1517,6 @@ pg_get_statisticsext_worker(Oid statextid, bool missing_ok)
appendStringInfoString(&buf, "ndistinct");
else if (dependencies_enabled)
appendStringInfoString(&buf, "dependencies");
appendStringInfoChar(&buf, ')');
}

View File

@ -3707,25 +3707,27 @@ estimate_multivariate_ndistinct(PlannerInfo *root, RelOptInfo *rel,
{
StatisticExtInfo *info = (StatisticExtInfo *) lfirst(lc);
Bitmapset *shared;
int nshared;
/* skip statistics of other kinds */
if (info->kind != STATS_EXT_NDISTINCT)
continue;
/* compute attnums shared by the vars and the statistic */
/* compute attnums shared by the vars and the statistics object */
shared = bms_intersect(info->keys, attnums);
nshared = bms_num_members(shared);
/*
* Does this statistics matches more columns than the currently
* best statistic? If so, use this one instead.
* Does this statistics object match more columns than the currently
* best object? If so, use this one instead.
*
* XXX This should break ties using name of the statistic, or
* something like that, to make the outcome stable.
* XXX This should break ties using name of the object, or something
* like that, to make the outcome stable.
*/
if (bms_num_members(shared) > nmatches)
if (nshared > nmatches)
{
statOid = info->statOid;
nmatches = bms_num_members(shared);
nmatches = nshared;
matched = shared;
}
}

View File

@ -4462,7 +4462,7 @@ RelationGetIndexList(Relation relation)
/*
* RelationGetStatExtList
* get a list of OIDs of extended statistics on this relation
* get a list of OIDs of statistics objects on this relation
*
* The statistics list is created only if someone requests it, in a way
* similar to RelationGetIndexList(). We scan pg_statistic_ext to find
@ -4470,7 +4470,7 @@ RelationGetIndexList(Relation relation)
* won't have to compute it again. Note that shared cache inval of a
* relcache entry will delete the old list and set rd_statvalid to 0,
* so that we must recompute the statistics list on next request. This
* handles creation or deletion of a statistic.
* handles creation or deletion of a statistics object.
*
* The returned list is guaranteed to be sorted in order by OID, although
* this is not currently needed.

View File

@ -6713,7 +6713,7 @@ getExtendedStatistics(Archive *fout, TableInfo tblinfo[], int numTables)
"tableoid, "
"oid, "
"stxname, "
"pg_catalog.pg_get_statisticsextdef(oid) AS stxdef "
"pg_catalog.pg_get_statisticsobjdef(oid) AS stxdef "
"FROM pg_statistic_ext "
"WHERE stxrelid = '%u' "
"ORDER BY stxname", tbinfo->dobj.catId.oid);

View File

@ -2402,7 +2402,7 @@ describeOneTableDetails(const char *schemaname,
if (tuples > 0)
{
printTableAddFooter(&cont, _("Statistics:"));
printTableAddFooter(&cont, _("Statistics objects:"));
for (i = 0; i < tuples; i++)
{
@ -2410,7 +2410,7 @@ describeOneTableDetails(const char *schemaname,
printfPQExpBuffer(&buf, " ");
/* statistics name (qualified with namespace) */
/* statistics object name (qualified with namespace) */
appendPQExpBuffer(&buf, "\"%s\".\"%s\" (",
PQgetvalue(result, i, 2),
PQgetvalue(result, i, 3));

View File

@ -622,7 +622,7 @@ static const SchemaQuery Query_for_list_of_statistics = {
/* selcondition */
NULL,
/* viscondition */
"pg_catalog.pg_statistic_ext_is_visible(s.oid)",
"pg_catalog.pg_statistics_obj_is_visible(s.oid)",
/* namespace */
"s.stxnamespace",
/* result */

View File

@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 201705131
#define CATALOG_VERSION_NO 201705141
#endif

View File

@ -92,7 +92,7 @@ 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 Oid get_statistics_object_oid(List *names, bool missing_ok);
extern bool StatisticsObjIsVisible(Oid stxid);
extern Oid get_ts_parser_oid(List *names, bool missing_ok);

View File

@ -1987,9 +1987,9 @@ DESCR("select statement of a view");
DATA(insert OID = 1642 ( pg_get_userbyid PGNSP PGUID 12 1 0 0 0 f f f f t f s s 1 0 19 "26" _null_ _null_ _null_ _null_ _null_ pg_get_userbyid _null_ _null_ _null_ ));
DESCR("role name by OID (with fallback)");
DATA(insert OID = 1643 ( pg_get_indexdef PGNSP PGUID 12 1 0 0 0 f f f f t f s s 1 0 25 "26" _null_ _null_ _null_ _null_ _null_ pg_get_indexdef _null_ _null_ _null_ ));
DESCR("extended statistics description");
DATA(insert OID = 3415 ( pg_get_statisticsextdef PGNSP PGUID 12 1 0 0 0 f f f f t f s s 1 0 25 "26" _null_ _null_ _null_ _null_ _null_ pg_get_statisticsextdef _null_ _null_ _null_ ));
DESCR("index description");
DATA(insert OID = 3415 ( pg_get_statisticsobjdef PGNSP PGUID 12 1 0 0 0 f f f f t f s s 1 0 25 "26" _null_ _null_ _null_ _null_ _null_ pg_get_statisticsobjdef _null_ _null_ _null_ ));
DESCR("extended statistics object description");
DATA(insert OID = 3352 ( pg_get_partkeydef PGNSP PGUID 12 1 0 0 0 f f f f t f s s 1 0 25 "26" _null_ _null_ _null_ _null_ _null_ pg_get_partkeydef _null_ _null_ _null_ ));
DESCR("partition key description");
DATA(insert OID = 3408 ( pg_get_partition_constraintdef PGNSP PGUID 12 1 0 0 0 f f f f t f s s 1 0 25 "26" _null_ _null_ _null_ _null_ _null_ pg_get_partition_constraintdef _null_ _null_ _null_ ));
@ -3183,7 +3183,7 @@ 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_ ));
DATA(insert OID = 3403 ( pg_statistics_obj_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_statistics_obj_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?");

View File

@ -30,11 +30,13 @@
CATALOG(pg_statistic_ext,3381)
{
/* These fields form the unique key for the entry: */
Oid stxrelid; /* relation containing attributes */
NameData stxname; /* statistics name */
Oid stxnamespace; /* OID of namespace containing this statistics */
Oid stxowner; /* statistics owner */
/* These two fields form the unique key for the entry: */
NameData stxname; /* statistics object name */
Oid stxnamespace; /* OID of statistics object's namespace */
Oid stxowner; /* statistics object's owner */
/*
* variable-length fields start here, but we allow direct access to

View File

@ -327,7 +327,7 @@ extern bool pg_event_trigger_ownercheck(Oid et_oid, Oid roleid);
extern bool pg_extension_ownercheck(Oid ext_oid, Oid roleid);
extern bool pg_publication_ownercheck(Oid pub_oid, Oid roleid);
extern bool pg_subscription_ownercheck(Oid sub_oid, Oid roleid);
extern bool pg_statistics_ownercheck(Oid stat_oid, Oid roleid);
extern bool pg_statistics_object_ownercheck(Oid stat_oid, Oid roleid);
extern bool has_createrole_privilege(Oid roleid);
extern bool has_bypassrls_privilege(Oid roleid);

View File

@ -504,7 +504,7 @@ CREATE TABLE alt_regress_1 (a INTEGER, b INTEGER);
CREATE STATISTICS alt_stat1 ON a, b FROM alt_regress_1;
CREATE STATISTICS alt_stat2 ON a, b FROM alt_regress_1;
ALTER STATISTICS alt_stat1 RENAME TO alt_stat2; -- failed (name conflict)
ERROR: statistics "alt_stat2" already exists in schema "alt_nsp1"
ERROR: statistics object "alt_stat2" already exists in schema "alt_nsp1"
ALTER STATISTICS alt_stat1 RENAME TO alt_stat3; -- failed (name conflict)
ALTER STATISTICS alt_stat2 OWNER TO regress_alter_user2; -- failed (no role membership)
ERROR: must be member of role "regress_alter_user2"
@ -515,16 +515,16 @@ CREATE TABLE alt_regress_2 (a INTEGER, b INTEGER);
CREATE STATISTICS alt_stat1 ON a, b FROM alt_regress_2;
CREATE STATISTICS alt_stat2 ON a, b FROM alt_regress_2;
ALTER STATISTICS alt_stat3 RENAME TO alt_stat4; -- failed (not owner)
ERROR: must be owner of statistics alt_stat3
ERROR: must be owner of statistics object alt_stat3
ALTER STATISTICS alt_stat1 RENAME TO alt_stat4; -- OK
ALTER STATISTICS alt_stat3 OWNER TO regress_alter_user2; -- failed (not owner)
ERROR: must be owner of statistics alt_stat3
ERROR: must be owner of statistics object alt_stat3
ALTER STATISTICS alt_stat2 OWNER TO regress_alter_user3; -- failed (no role membership)
ERROR: must be member of role "regress_alter_user3"
ALTER STATISTICS alt_stat3 SET SCHEMA alt_nsp2; -- failed (not owner)
ERROR: must be owner of statistics alt_stat3
ERROR: must be owner of statistics object alt_stat3
ALTER STATISTICS alt_stat2 SET SCHEMA alt_nsp2; -- failed (name conflict)
ERROR: statistics "alt_stat2" already exists in schema "alt_nsp2"
ERROR: statistics object "alt_stat2" already exists in schema "alt_nsp2"
RESET SESSION AUTHORIZATION;
SELECT nspname, stxname, rolname
FROM pg_statistic_ext s, pg_namespace n, pg_authid a

View File

@ -411,7 +411,7 @@ WITH objects (type, name, args) AS (VALUES
('publication', '{addr_pub}', '{}'),
('publication relation', '{addr_nsp, gentable}', '{addr_pub}'),
('subscription', '{addr_sub}', '{}'),
('statistics', '{addr_nsp, gentable_stat}', '{}')
('statistics object', '{addr_nsp, gentable_stat}', '{}')
)
SELECT (pg_identify_object(addr1.classid, addr1.objid, addr1.objsubid)).*,
-- test roundtrip through pg_identify_object_as_address
@ -459,7 +459,7 @@ SELECT (pg_identify_object(addr1.classid, addr1.objid, addr1.objsubid)).*,
trigger | | | t on addr_nsp.gentable | t
operator family | pg_catalog | integer_ops | pg_catalog.integer_ops USING btree | t
policy | | | genpol on addr_nsp.gentable | t
statistics | addr_nsp | gentable_stat | addr_nsp.gentable_stat | t
statistics object | addr_nsp | gentable_stat | addr_nsp.gentable_stat | t
collation | pg_catalog | "default" | pg_catalog."default" | t
transform | | | for integer on language sql | t
text search dictionary | addr_nsp | addr_ts_dict | addr_nsp.addr_ts_dict | t

View File

@ -3166,8 +3166,8 @@ SELECT pg_get_ruledef(0);
(1 row)
SELECT pg_get_statisticsextdef(0);
pg_get_statisticsextdef
SELECT pg_get_statisticsobjdef(0);
pg_get_statisticsobjdef
-------------------------
(1 row)

View File

@ -29,16 +29,16 @@ ERROR: only simple column references are allowed in CREATE STATISTICS
CREATE STATISTICS tst ON (relpages, reltuples) FROM pg_class;
ERROR: only simple column references are allowed in CREATE STATISTICS
CREATE STATISTICS tst (unrecognized) ON relname, relnatts FROM pg_class;
ERROR: unrecognized statistics type "unrecognized"
ERROR: unrecognized statistic type "unrecognized"
-- Ensure stats are dropped sanely
CREATE TABLE ab1 (a INTEGER, b INTEGER, c INTEGER);
CREATE STATISTICS ab1_a_b_stats ON a, b FROM ab1;
DROP STATISTICS ab1_a_b_stats;
CREATE SCHEMA regress_schema_2;
CREATE STATISTICS regress_schema_2.ab1_a_b_stats ON a, b FROM ab1;
-- Let's also verify the pg_get_statisticsextdef output looks sane.
SELECT pg_get_statisticsextdef(oid) FROM pg_statistic_ext WHERE stxname = 'ab1_a_b_stats';
pg_get_statisticsextdef
-- Let's also verify the pg_get_statisticsobjdef output looks sane.
SELECT pg_get_statisticsobjdef(oid) FROM pg_statistic_ext WHERE stxname = 'ab1_a_b_stats';
pg_get_statisticsobjdef
-------------------------------------------------------------------
CREATE STATISTICS regress_schema_2.ab1_a_b_stats ON a, b FROM ab1
(1 row)
@ -55,7 +55,7 @@ ALTER TABLE ab1 DROP COLUMN a;
--------+---------+-----------+----------+---------
b | integer | | |
c | integer | | |
Statistics:
Statistics objects:
"public"."ab1_b_c_stats" (ndistinct, dependencies) ON b, c FROM ab1
-- Ensure statistics are dropped when table is
@ -77,11 +77,11 @@ ALTER TABLE ab1 ALTER a SET STATISTICS 0;
INSERT INTO ab1 SELECT a, a%23 FROM generate_series(1, 1000) a;
CREATE STATISTICS ab1_a_b_stats ON a, b FROM ab1;
ANALYZE ab1;
WARNING: extended statistics "public.ab1_a_b_stats" could not be collected for relation public.ab1
WARNING: statistics object "public.ab1_a_b_stats" could not be computed for relation "public.ab1"
ALTER TABLE ab1 ALTER a SET STATISTICS -1;
-- partial analyze doesn't build stats either
ANALYZE ab1 (a);
WARNING: extended statistics "public.ab1_a_b_stats" could not be collected for relation public.ab1
WARNING: statistics object "public.ab1_a_b_stats" could not be computed for relation "public.ab1"
ANALYZE ab1;
DROP TABLE ab1;
-- Verify supported object types for extended statistics

View File

@ -187,7 +187,7 @@ WITH objects (type, name, args) AS (VALUES
('publication', '{addr_pub}', '{}'),
('publication relation', '{addr_nsp, gentable}', '{addr_pub}'),
('subscription', '{addr_sub}', '{}'),
('statistics', '{addr_nsp, gentable_stat}', '{}')
('statistics object', '{addr_nsp, gentable_stat}', '{}')
)
SELECT (pg_identify_object(addr1.classid, addr1.objid, addr1.objsubid)).*,
-- test roundtrip through pg_identify_object_as_address

View File

@ -1155,7 +1155,7 @@ SELECT pg_get_constraintdef(0);
SELECT pg_get_functiondef(0);
SELECT pg_get_indexdef(0);
SELECT pg_get_ruledef(0);
SELECT pg_get_statisticsextdef(0);
SELECT pg_get_statisticsobjdef(0);
SELECT pg_get_triggerdef(0);
SELECT pg_get_viewdef(0);
SELECT pg_get_function_arguments(0);

View File

@ -26,8 +26,8 @@ DROP STATISTICS ab1_a_b_stats;
CREATE SCHEMA regress_schema_2;
CREATE STATISTICS regress_schema_2.ab1_a_b_stats ON a, b FROM ab1;
-- Let's also verify the pg_get_statisticsextdef output looks sane.
SELECT pg_get_statisticsextdef(oid) FROM pg_statistic_ext WHERE stxname = 'ab1_a_b_stats';
-- Let's also verify the pg_get_statisticsobjdef output looks sane.
SELECT pg_get_statisticsobjdef(oid) FROM pg_statistic_ext WHERE stxname = 'ab1_a_b_stats';
DROP STATISTICS regress_schema_2.ab1_a_b_stats;