Skip to content

Commit 037d40c

Browse files
committed
[binder] hoist projections in certain cases where we can combine with top-level projection
1 parent 999a371 commit 037d40c

File tree

6 files changed

+24580
-25872
lines changed

6 files changed

+24580
-25872
lines changed

enginetest/queries/imdb_plans.go

Lines changed: 22664 additions & 23880 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

enginetest/queries/integration_plans.go

Lines changed: 1615 additions & 1696 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

enginetest/queries/query_plans.go

Lines changed: 252 additions & 294 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sql/plan/project.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ type Project struct {
2828
UnaryNode
2929
Projections []sql.Expression
3030
CanDefer bool
31+
deps sql.ColSet
3132
}
3233

3334
var _ sql.Expressioner = (*Project)(nil)
@@ -94,6 +95,23 @@ func unwrapGetField(expr sql.Expression) *expression.GetField {
9495
}
9596
}
9697

98+
func ExprDeps(exprs []sql.Expression) sql.ColSet {
99+
var deps sql.ColSet
100+
for _, e := range exprs {
101+
sql.Inspect(e, func(e sql.Expression) bool {
102+
switch e := e.(type) {
103+
case sql.IdExpression:
104+
deps.Add(e.Id())
105+
case *Subquery:
106+
deps.Union(e.Correlated())
107+
default:
108+
}
109+
return true
110+
})
111+
}
112+
return deps
113+
}
114+
97115
// Schema implements the Node interface.
98116
func (p *Project) Schema() sql.Schema {
99117
var s = make(sql.Schema, len(p.Projections))

sql/planbuilder/factory.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,3 +220,28 @@ func (f *factory) buildDistinct(child sql.Node) sql.Node {
220220
}
221221
return plan.NewDistinct(child)
222222
}
223+
224+
func (f *factory) buildSort(child sql.Node, exprs []sql.SortField, deps sql.ColSet, subquery bool) (sql.Node, error) {
225+
{
226+
// if Sort->Projection with no alias dependency, hoist projection
227+
// for opportunity to squash with top-level projection
228+
// sort -> proj -> child
229+
// =>
230+
// proj -> sort -> child
231+
if p, ok := child.(*plan.Project); ok {
232+
var aliases []sql.Expression
233+
for _, p := range p.Projections {
234+
if _, ok := p.(*expression.Alias); ok {
235+
aliases = append(aliases, p)
236+
}
237+
}
238+
aliasCols := plan.ExprDeps(aliases)
239+
if !aliasCols.Intersects(deps) {
240+
newP := plan.NewProject(p.Projections, plan.NewSort(exprs, p.Child))
241+
return f.buildProject(newP, subquery)
242+
}
243+
}
244+
}
245+
246+
return plan.NewSort(exprs, child), nil
247+
}

sql/planbuilder/orderby.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222

2323
"github.com/dolthub/go-mysql-server/sql"
2424
"github.com/dolthub/go-mysql-server/sql/expression"
25-
"github.com/dolthub/go-mysql-server/sql/plan"
2625
"github.com/dolthub/go-mysql-server/sql/transform"
2726
"github.com/dolthub/go-mysql-server/sql/types"
2827
)
@@ -199,6 +198,7 @@ func (b *Builder) buildOrderBy(inScope, orderByScope *scope) {
199198
return
200199
}
201200
var sortFields sql.SortFields
201+
var deps sql.ColSet
202202
for _, c := range orderByScope.cols {
203203
so := sql.Ascending
204204
if c.descending {
@@ -213,8 +213,12 @@ func (b *Builder) buildOrderBy(inScope, orderByScope *scope) {
213213
Order: so,
214214
}
215215
sortFields = append(sortFields, sf)
216+
deps.Add(sql.ColumnId(c.id))
217+
}
218+
sort, err := b.f.buildSort(inScope.node, sortFields, deps, inScope.refsSubquery)
219+
if err != nil {
220+
b.handleErr(err)
216221
}
217-
sort := plan.NewSort(sortFields, inScope.node)
218222
inScope.node = sort
219223
return
220224
}

0 commit comments

Comments
 (0)