postgres.git / summary / log / commit / refs
commit 28555a53cb75d00ed0e73f63a6481b4fffcc3dea
Author: Tomas Vondra <tomas.vondra@postgresql.org>
Date: Sat Nov 16 00:17:15 2019 +0000
First released in: 13.0, 10.12, 11.7, 12.2
Skip system attributes when applying mvdistinct stats
When estimating number of distinct groups, we failed to ignore system
attributes when matching the group expressions to mvdistinct stats,
causing failures like
ERROR: negative bitmapset member not allowed
Fix that by simply skipping anything that is not a regular attribute.
Backpatch to PostgreSQL 10, where the extended stats were introduced.
Bug: #16111
Reported-by: Tuomas Leikola
Author: Tomas Vondra
Backpatch-through: 10
Discussion: https://postgr.es/m/16111-687799584c3a7e73@postgresql.org
src/backend/utils/adt/selfuncs.c | 19 ++++++++++++++-----
src/test/regress/expected/stats_ext.out | 7 +++++++
src/test/regress/sql/stats_ext.sql | 3 +++
3 files changed, 24 insertions(+), 5 deletions(-)
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index a314ecc4fe3..8f9d0211f85 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -3587,14 +3587,19 @@ estimate_multivariate_ndistinct(PlannerInfo *root, RelOptInfo *rel,
foreach(lc, *varinfos)
{
GroupVarInfo *varinfo = (GroupVarInfo *) lfirst(lc);
+ AttrNumber attnum;
Assert(varinfo->rel == rel);
- if (IsA(varinfo->var, Var))
- {
- attnums = bms_add_member(attnums,
- ((Var *) varinfo->var)->varattno);
- }
+ if (!IsA(varinfo->var, Var))
+ continue;
+
+ attnum = ((Var *) varinfo->var)->varattno;
+
+ if (!AttrNumberIsForUserDefinedAttr(attnum))
+ continue;
+
+ attnums = bms_add_member(attnums, attnum);
}
/* look for the ndistinct statistics matching the most vars */
@@ -3674,6 +3679,10 @@ estimate_multivariate_ndistinct(PlannerInfo *root, RelOptInfo *rel,
}
attnum = ((Var *) varinfo->var)->varattno;
+
+ if (!AttrNumberIsForUserDefinedAttr(attnum))
+ continue;
+
if (!bms_is_member(attnum, matched))
newlist = lappend(newlist, varinfo);
}
diff --git a/src/test/regress/expected/stats_ext.out b/src/test/regress/expected/stats_ext.out
index 4af61b41195..f827c8f2df5 100644
--- a/src/test/regress/expected/stats_ext.out
+++ b/src/test/regress/expected/stats_ext.out
@@ -216,6 +216,13 @@ SELECT s.stxkind, d.stxdndistinct
{d,f,m} | {"3, 4": 11, "3, 6": 11, "4, 6": 11, "3, 4, 6": 11}
(1 row)
+-- minor improvement, make sure the ctid does not break the matching
+SELECT * FROM check_estimated_rows('SELECT COUNT(*) FROM ndistinct GROUP BY ctid, a, b');
+ estimated | actual
+-----------+--------
+ 11 | 1000
+(1 row)
+
-- Hash Aggregate, thanks to estimates improved by the statistic
SELECT * FROM check_estimated_rows('SELECT COUNT(*) FROM ndistinct GROUP BY a, b');
estimated | actual
diff --git a/src/test/regress/sql/stats_ext.sql b/src/test/regress/sql/stats_ext.sql
index 279158ff026..45ad2654068 100644
--- a/src/test/regress/sql/stats_ext.sql
+++ b/src/test/regress/sql/stats_ext.sql
@@ -157,6 +157,9 @@ SELECT s.stxkind, d.stxdndistinct
WHERE s.stxrelid = 'ndistinct'::regclass
AND d.stxoid = s.oid;
+-- minor improvement, make sure the ctid does not break the matching
+SELECT * FROM check_estimated_rows('SELECT COUNT(*) FROM ndistinct GROUP BY ctid, a, b');
+
-- Hash Aggregate, thanks to estimates improved by the statistic
SELECT * FROM check_estimated_rows('SELECT COUNT(*) FROM ndistinct GROUP BY a, b');
[parent: 24897e1a1af2]