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
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 */
}
attnum = ((Var *) varinfo->var)->varattno;
+
+ if (!AttrNumberIsForUserDefinedAttr(attnum))
+ continue;
+
if (!bms_is_member(attnum, matched))
newlist = lappend(newlist, varinfo);
}
{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
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');