Skip to content

Commit dd82ba3

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 7e867f6 commit dd82ba3

1 file changed

Lines changed: 23 additions & 8 deletions

File tree

src/backend/commands/analyzeutils.c

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -759,17 +759,32 @@ 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)) {
767-
valid = false;
768-
break;
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;
769778
}
770779

771-
Assert(ndvbsSlots[i]->valuetype == FLOAT8OID);
772780
Assert(ndvbsSlots[i]->nvalues == 1);
781+
782+
/* Non-empty partition with zero NDV is suspicious */
783+
if (relTuples[i] > 0 && DatumGetFloat8(ndvbsSlots[i]->values[0]) == 0)
784+
{
785+
valid = false;
786+
break;
787+
}
773788
}
774789
return valid;
775790
}

0 commit comments

Comments
 (0)