Skip to content

Commit 493a8a4

Browse files
Fix assertion failure in getNdvBySegHeapTuple for empty partitions.
When merging leaf partition statistics for a partitioned table, getNdvBySegHeapTuple could hit Assert(valuetype == FLOAT8OID) if a partition had relTuples == 0 and its pg_statistic entry lacked a valid STATISTIC_KIND_NDV_BY_SEGMENTS slot (or the slot had an unexpected element type). The original guard condition only handled two cases: 1. Non-empty partition with NDV value == 0 2. Non-empty partition without NDV_BY_SEGMENTS It missed the case where an empty partition (relTuples == 0) has a pg_statistic entry but no valid FLOAT8OID NDV_BY_SEGMENTS slot, causing the code to fall through to the assertion. Fix by checking valuetype != FLOAT8OID upfront: skip empty partitions gracefully, and mark non-empty partitions as invalid. Authored-by: Zhang Wenchao zwcpostgres@gmail.com
1 parent 8ecc326 commit 493a8a4

1 file changed

Lines changed: 28 additions & 7 deletions

File tree

src/backend/commands/analyzeutils.c

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -759,17 +759,38 @@ getNdvBySegHeapTuple(AttStatsSlot * *ndvbsSlots, HeapTuple *heaptupleStats, floa
759759
(void) get_attstatsslot(ndvbsSlots[i], heaptupleStats[i],
760760
STATISTIC_KIND_NDV_BY_SEGMENTS, InvalidOid, ATTSTATSSLOT_VALUES);
761761

762-
if ((InvalidOid != ndvbsSlots[i]->valuetype && // result is not empty
763-
// not empty partition with invalid ndvbs
764-
(relTuples[i] > 0 && DatumGetFloat8(ndvbsSlots[i]->values[0]) == 0)) ||
765-
// not empty partition without ndvbs
766-
(InvalidOid == ndvbsSlots[i]->valuetype && relTuples[i] > 0)) {
762+
if (ndvbsSlots[i]->valuetype != FLOAT8OID)
763+
{
764+
/*
765+
* NDV_BY_SEGMENTS slot not found or has unexpected type.
766+
* Non-empty partitions must have valid NDV_BY_SEGMENTS;
767+
* empty partitions (relTuples == 0) can be skipped.
768+
*/
769+
if (relTuples[i] > 0)
770+
{
771+
valid = false;
772+
break;
773+
}
774+
free_attstatsslot(ndvbsSlots[i]);
775+
pfree(ndvbsSlots[i]);
776+
ndvbsSlots[i] = NULL;
777+
continue;
778+
}
779+
780+
Assert(ndvbsSlots[i]->valuetype == FLOAT8OID);
781+
782+
if (ndvbsSlots[i]->nvalues != 1)
783+
{
767784
valid = false;
768785
break;
769786
}
770787

771-
Assert(ndvbsSlots[i]->valuetype == FLOAT8OID);
772-
Assert(ndvbsSlots[i]->nvalues == 1);
788+
/* Non-empty partition with zero NDV is suspicious */
789+
if (relTuples[i] > 0 && DatumGetFloat8(ndvbsSlots[i]->values[0]) == 0)
790+
{
791+
valid = false;
792+
break;
793+
}
773794
}
774795
return valid;
775796
}

0 commit comments

Comments
 (0)