Skip to content

Commit

Permalink
[memo] merge joins must use globally sorted indexes (#2803)
Browse files Browse the repository at this point in the history
* [memo] merge joins must use globally sorted indexes

* explicitly label default unordered

* second merge join side idx order check
  • Loading branch information
max-hoffman authored Dec 26, 2024
1 parent 999a371 commit 5425a89
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 10 deletions.
9 changes: 9 additions & 0 deletions sql/analyzer/indexed_joins.go
Original file line number Diff line number Diff line change
Expand Up @@ -1070,9 +1070,18 @@ func addMergeJoins(ctx *sql.Context, m *memo.Memo) error {
// Check to see if any rIndexes match that set of filters
// Remove the last matched filter
for _, lIndex := range lIndexes {
if lIndex.Order() == sql.IndexOrderNone {
// lookups can be unordered, merge indexes need to
// be globally ordered
continue
}

matchedEqFilters := matchedFiltersForLeftIndex(lIndex, join.Left.RelProps.FuncDeps().Constants(), eqFilters)
for len(matchedEqFilters) > 0 {
for _, rIndex := range rIndexes {
if rIndex.Order() == sql.IndexOrderNone {
continue
}
if rightIndexMatchesFilters(rIndex, join.Left.RelProps.FuncDeps().Constants(), matchedEqFilters) {
jb := join.Copy()
if d, ok := jb.Left.First.(*memo.Distinct); ok && lIndex.SqlIdx().IsUnique() {
Expand Down
13 changes: 9 additions & 4 deletions sql/memo/memo.go
Original file line number Diff line number Diff line change
Expand Up @@ -743,14 +743,15 @@ type SourceRel interface {

type Index struct {
// ordered list of index columns
order []sql.ColumnId
cols []sql.ColumnId
// unordered column set
set sql.ColSet
idx sql.Index
set sql.ColSet
idx sql.Index
order sql.IndexOrder
}

func (i *Index) Cols() []sql.ColumnId {
return i.order
return i.cols
}

func (i *Index) ColSet() sql.ColSet {
Expand All @@ -761,6 +762,10 @@ func (i *Index) SqlIdx() sql.Index {
return i.idx
}

func (i *Index) Order() sql.IndexOrder {
return i.order
}

type sourceBase struct {
*relBase
indexes []*Index
Expand Down
7 changes: 5 additions & 2 deletions sql/memo/rel_props.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,10 @@ func (p *relProps) populateFds() {
// strict if primary key or all nonNull and unique
columns := idxExprsColumns(idx)
strict := true
normIdx := &Index{idx: idx, order: make([]sql.ColumnId, len(columns))}
normIdx := &Index{idx: idx, cols: make([]sql.ColumnId, len(columns)), order: sql.IndexOrderNone}
if oidx, ok := idx.(sql.OrderedIndex); ok {
normIdx.order = oidx.Order()
}
for i, c := range columns {
ord := sch.IndexOfColName(strings.ToLower(c))
idOffset := firstCol + sql.ColumnId(ord)
Expand All @@ -236,7 +239,7 @@ func (p *relProps) populateFds() {
p.grp.m.HandleErr(err)
}
normIdx.set.Add(colId)
normIdx.order[i] = colId
normIdx.cols[i] = colId
if !notNull.Contains(colId) {
strict = false
}
Expand Down
8 changes: 4 additions & 4 deletions sql/memo/rel_props_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ func TestPopulateFDs(t *testing.T) {
notNull: sql.NewColSet(1, 2, 3),
indexes: []*Index{
{
order: []sql.ColumnId{2, 1},
set: sql.NewColSet(1, 2),
cols: []sql.ColumnId{2, 1},
set: sql.NewColSet(1, 2),
},
},
key: sql.NewColSet(1, 2),
Expand All @@ -62,8 +62,8 @@ func TestPopulateFDs(t *testing.T) {
notNull: sql.NewColSet(1, 2, 3),
indexes: []*Index{
{
order: []sql.ColumnId{1, 2, 3},
set: sql.NewColSet(1, 2, 3),
cols: []sql.ColumnId{1, 2, 3},
set: sql.NewColSet(1, 2, 3),
},
},
key: sql.NewColSet(1, 2, 3),
Expand Down

0 comments on commit 5425a89

Please sign in to comment.