diff --git a/pkg/sql/opt/memo/interner.go b/pkg/sql/opt/memo/interner.go index 30c063294009..4fd41ba04e6a 100644 --- a/pkg/sql/opt/memo/interner.go +++ b/pkg/sql/opt/memo/interner.go @@ -497,10 +497,14 @@ func (h *hasher) HashTupleOrdinal(val TupleOrdinal) { } func (h *hasher) HashPhysProps(val *physical.Required) { - for i := range val.Presentation { - col := &val.Presentation[i] - h.HashString(col.Alias) - h.HashColumnID(col.ID) + // Note: the Any presentation is not the same as the 0-column presentation. + if !val.Presentation.Any() { + h.HashInt(len(val.Presentation)) + for i := range val.Presentation { + col := &val.Presentation[i] + h.HashString(col.Alias) + h.HashColumnID(col.ID) + } } h.HashOrderingChoice(val.Ordering) } diff --git a/pkg/sql/opt/props/physical/required.go b/pkg/sql/opt/props/physical/required.go index 3943cacbcc2e..7f7f544057e6 100644 --- a/pkg/sql/opt/props/physical/required.go +++ b/pkg/sql/opt/props/physical/required.go @@ -119,6 +119,10 @@ func (p Presentation) Any() bool { // Equals returns true iff this presentation exactly matches the given // presentation. func (p Presentation) Equals(rhs Presentation) bool { + // The 0 column presentation is not the same as the nil presentation. + if p.Any() != rhs.Any() { + return false + } if len(p) != len(rhs) { return false } diff --git a/pkg/sql/opt/props/physical/required_test.go b/pkg/sql/opt/props/physical/required_test.go index 67c5de5ee45d..566454138af9 100644 --- a/pkg/sql/opt/props/physical/required_test.go +++ b/pkg/sql/opt/props/physical/required_test.go @@ -46,10 +46,18 @@ func TestRequiredProps(t *testing.T) { t.Error("presentation should equal itself") } - if presentation.Equals(physical.Presentation{}) { + if presentation.Equals(physical.Presentation(nil)) { t.Error("presentation should not equal the empty presentation") } + if presentation.Equals(physical.Presentation{}) { + t.Error("presentation should not equal the 0 column presentation") + } + + if (physical.Presentation{}).Equals(physical.Presentation(nil)) { + t.Error("0 column presentation should not equal the empty presentation") + } + // Add ordering props. ordering := physical.ParseOrderingChoice("+1,+5") phys.Ordering = ordering