From: Tom Lane Date: Sun, 14 May 2017 14:54:47 +0000 (-0400) Subject: Standardize terminology for pg_statistic_ext entries. X-Git-Tag: REL_10_BETA1~22 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f04c9a61468904b6815b2bc73a48878817766e0e;p=postgresql 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 --- diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index d55656769b..14aae736c3 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -16681,7 +16681,7 @@ SELECT relname FROM pg_class WHERE pg_table_is_visible(oid); is operator family visible in search path - pg_statistic_ext_is_visible(stat_oid) + pg_statistics_obj_is_visible(stat_oid) boolean is statistics object visible in search path @@ -16745,7 +16745,7 @@ SELECT relname FROM pg_class WHERE pg_table_is_visible(oid); pg_opfamily_is_visible - pg_statistic_ext_is_visible + pg_statistics_obj_is_visible pg_table_is_visible @@ -16836,7 +16836,7 @@ SELECT pg_type_is_visible('myschema.widget'::regtype); - pg_get_statisticsextdef + pg_get_statisticsobjdef @@ -17009,9 +17009,9 @@ SELECT pg_type_is_visible('myschema.widget'::regtype); uses - pg_get_statisticsextdef(statext_oid) + pg_get_statisticsobjdef(statobj_oid) text - get CREATE STATISTICS command for extended statistics objects + get CREATE STATISTICS command for extended statistics object pg_get_triggerdef(trigger_oid) @@ -17158,7 +17158,7 @@ SELECT pg_type_is_visible('myschema.widget'::regtype); pg_get_constraintdef, pg_get_indexdef, pg_get_ruledef, - pg_get_statisticsextdef, and + pg_get_statisticsobjdef, and pg_get_triggerdef, respectively reconstruct the creating command for a constraint, index, rule, extended statistics object, or trigger. (Note that this is a decompiled reconstruction, not the diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index 32989df2b5..387a3be701 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -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; diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c index 5b339222af..2a33eb73fa 100644 --- a/src/backend/catalog/namespace.c +++ b/src/backend/catalog/namespace.c @@ -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); diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c index a373df743b..e3efb98b1d 100644 --- a/src/backend/catalog/objectaddress.c +++ b/src/backend/catalog/objectaddress.c @@ -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); diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c index 2c6435b759..bc897e409c 100644 --- a/src/backend/commands/alter.c +++ b/src/backend/commands/alter.c @@ -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)); diff --git a/src/backend/commands/dropcmds.c b/src/backend/commands/dropcmds.c index c18bc319be..a1a64fa8c9 100644 --- a/src/backend/commands/dropcmds.c +++ b/src/backend/commands/dropcmds.c @@ -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; diff --git a/src/backend/commands/statscmds.c b/src/backend/commands/statscmds.c index db5f4278d5..cab54c962c 100644 --- a/src/backend/commands/statscmds.c +++ b/src/backend/commands/statscmds.c @@ -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; diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 9207c8d809..2a5ec181de 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -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]); diff --git a/src/backend/statistics/README b/src/backend/statistics/README index af7651127e..a8f00a590e 100644 --- a/src/backend/statistics/README +++ b/src/backend/statistics/README @@ -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. diff --git a/src/backend/statistics/README.dependencies b/src/backend/statistics/README.dependencies index 7bc2533dc6..59f9d57657 100644 --- a/src/backend/statistics/README.dependencies +++ b/src/backend/statistics/README.dependencies @@ -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. diff --git a/src/backend/statistics/dependencies.c b/src/backend/statistics/dependencies.c index fe9a9ef5de..0e71f058ad 100644 --- a/src/backend/statistics/dependencies.c +++ b/src/backend/statistics/dependencies.c @@ -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); /* diff --git a/src/backend/statistics/extended_stats.c b/src/backend/statistics/extended_stats.c index b334140c48..3f74cee05f 100644 --- a/src/backend/statistics/extended_stats.c +++ b/src/backend/statistics/extended_stats.c @@ -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)) diff --git a/src/backend/statistics/mvdistinct.c b/src/backend/statistics/mvdistinct.c index f67f576236..47b2490abb 100644 --- a/src/backend/statistics/mvdistinct.c +++ b/src/backend/statistics/mvdistinct.c @@ -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); diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index c9bded082e..43b1475035 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -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, ')'); } diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index 6c4cef9fb3..7028d6387c 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -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; } } diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index c3721d9e43..0cd6289f91 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -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. diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index b26358c770..b6794d06de 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -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); diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index cb17407036..b9d395b4b4 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -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)); diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index ae3730257d..b9e3491aec 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 */ - "pg_catalog.pg_statistic_ext_is_visible(s.oid)", + "pg_catalog.pg_statistics_obj_is_visible(s.oid)", /* namespace */ "s.stxnamespace", /* result */ diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 7adfd328f6..06fff799af 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 201705131 +#define CATALOG_VERSION_NO 201705141 #endif diff --git a/src/include/catalog/namespace.h b/src/include/catalog/namespace.h index 959ee4c50e..5294a52984 100644 --- a/src/include/catalog/namespace.h +++ b/src/include/catalog/namespace.h @@ -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); diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 74346963d9..5c38ab55ec 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -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?"); diff --git a/src/include/catalog/pg_statistic_ext.h b/src/include/catalog/pg_statistic_ext.h index b0fda076fe..f08379699e 100644 --- a/src/include/catalog/pg_statistic_ext.h +++ b/src/include/catalog/pg_statistic_ext.h @@ -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 diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h index c957d8e170..2487020ec1 100644 --- a/src/include/utils/acl.h +++ b/src/include/utils/acl.h @@ -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); diff --git a/src/test/regress/expected/alter_generic.out b/src/test/regress/expected/alter_generic.out index 28e69166be..62347bc47e 100644 --- a/src/test/regress/expected/alter_generic.out +++ b/src/test/regress/expected/alter_generic.out @@ -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 diff --git a/src/test/regress/expected/object_address.out b/src/test/regress/expected/object_address.out index 3ca5c764ca..8c56512007 100644 --- a/src/test/regress/expected/object_address.out +++ b/src/test/regress/expected/object_address.out @@ -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 diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index a4b2d8635d..912360d70a 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -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) diff --git a/src/test/regress/expected/stats_ext.out b/src/test/regress/expected/stats_ext.out index 13780897c5..564521957f 100644 --- a/src/test/regress/expected/stats_ext.out +++ b/src/test/regress/expected/stats_ext.out @@ -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 diff --git a/src/test/regress/sql/object_address.sql b/src/test/regress/sql/object_address.sql index f25ed735e1..ca7ed46e41 100644 --- a/src/test/regress/sql/object_address.sql +++ b/src/test/regress/sql/object_address.sql @@ -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 diff --git a/src/test/regress/sql/rules.sql b/src/test/regress/sql/rules.sql index 98a8a692d8..aada114ab2 100644 --- a/src/test/regress/sql/rules.sql +++ b/src/test/regress/sql/rules.sql @@ -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); diff --git a/src/test/regress/sql/stats_ext.sql b/src/test/regress/sql/stats_ext.sql index 09b7d8e102..a9dda051c2 100644 --- a/src/test/regress/sql/stats_ext.sql +++ b/src/test/regress/sql/stats_ext.sql @@ -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;