-
-
Notifications
You must be signed in to change notification settings - Fork 221
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
hashjoin indexing #1728
hashjoin indexing #1728
Changes from 27 commits
eee289b
ee224a5
521bb1a
f93f3d4
dfbd936
5b8915c
87b5a9d
88b1d10
e2ef855
da0ceb4
61c8b43
410b82e
b2e52c8
59d1484
98aa934
d261dd8
118dcae
783fc06
c778cf3
db7fcd0
0d34d51
8a4eebe
1e039b4
6a981ed
3917790
9821fe3
b801fd7
51c5d0a
b8b7e57
117063b
b85582c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -180,10 +180,18 @@ func (b *ExecBuilder) buildHashJoin(j *hashJoin, input sql.Schema, children ...s | |
if err != nil { | ||
return nil, err | ||
} | ||
oldInJoin := false | ||
if j.g.m.scope != nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rather than temporarily monkeying with the scope like this, why not pass a modified copy directly to this function? |
||
oldInJoin = j.g.m.scope.inJoin | ||
j.g.m.scope.SetJoin(false) | ||
} | ||
outerAttrs, err := b.buildFilters(j.g.m.scope, j.right.relProps.OutputCols(), expression.Tuple(j.outerAttrs)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
if j.g.m.scope != nil { | ||
j.g.m.scope.SetJoin(oldInJoin) | ||
} | ||
filters, err := b.buildFilters(j.g.m.scope, input, j.filter...) | ||
if err != nil { | ||
return nil, err | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,9 +50,31 @@ func finalizeSubqueries(ctx *sql.Context, a *Analyzer, n sql.Node, scope *Scope, | |
// finalizeSubqueriesHelper finalizes all subqueries and subquery expressions, | ||
// fixing parent scopes before recursing into child nodes. | ||
func finalizeSubqueriesHelper(ctx *sql.Context, a *Analyzer, node sql.Node, scope *Scope, sel RuleSelector) (sql.Node, transform.TreeIdentity, error) { | ||
return transform.Node(node, func(n sql.Node) (sql.Node, transform.TreeIdentity, error) { | ||
var joinParent *plan.JoinNode | ||
var selFunc transform.SelectorFunc = func(c transform.Context) bool { | ||
if jp, ok := c.Node.(*plan.JoinNode); ok { | ||
joinParent = jp | ||
} | ||
return true | ||
} | ||
Comment on lines
+53
to
+59
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this seems like it could have unpredictable effects. any reason why |
||
|
||
var conFunc transform.CtxFunc = func(c transform.Context) (sql.Node, transform.TreeIdentity, error) { | ||
n := c.Node | ||
if sqa, ok := n.(*plan.SubqueryAlias); ok { | ||
newSqa, same2, err := analyzeSubqueryAlias(ctx, a, sqa, scope, sel, true) | ||
var newSqa sql.Node | ||
var same2 transform.TreeIdentity | ||
var err error | ||
if sqa.OuterScopeVisibility && joinParent != nil && !joinParent.Op.IsLeftOuter() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar to above comment, I think we should make sure There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
if stripChild, ok := joinParent.Right().(*plan.StripRowNode); ok && stripChild.Child == sqa { | ||
subScope := scope.newScopeInJoin(joinParent.Children()[0]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should add a comment that this only fixes 1-degree of join nesting, and that a proper fix would re-index the entire tree at the end of analysis. If the subquery has more than 1 sibling, or a sibling higher in the join tree, we currently do not detect it. We probably don't need tests for those edge cases yet. Just gotta hope no one hits them soon. |
||
newSqa, same2, err = analyzeSubqueryAlias(ctx, a, sqa, subScope, sel, true) | ||
} else { | ||
newSqa, same2, err = analyzeSubqueryAlias(ctx, a, sqa, scope, sel, true) | ||
} | ||
} else { | ||
newSqa, same2, err = analyzeSubqueryAlias(ctx, a, sqa, scope, sel, true) | ||
} | ||
|
||
if err != nil { | ||
return n, transform.SameTree, err | ||
} | ||
|
@@ -68,37 +90,38 @@ func finalizeSubqueriesHelper(ctx *sql.Context, a *Analyzer, node sql.Node, scop | |
newNode, err = newSqa.WithChildren(newNode) | ||
return newNode, transform.NewTree, err | ||
} | ||
} else { | ||
return transform.OneNodeExprsWithNode(n, func(node sql.Node, e sql.Expression) (sql.Expression, transform.TreeIdentity, error) { | ||
if sq, ok := e.(*plan.Subquery); ok { | ||
newSq, same2, err := analyzeSubqueryExpression(ctx, a, node, sq, scope, sel, true) | ||
if err != nil { | ||
if analyzererrors.ErrValidationResolved.Is(err) { | ||
// if a parent is unresolved, we want to dig deeper to find the unresolved | ||
// child dependency | ||
_, _, err := finalizeSubqueriesHelper(ctx, a, sq.Query, scope.newScopeFromSubqueryExpression(node), sel) | ||
if err != nil { | ||
return e, transform.SameTree, err | ||
} | ||
} | ||
return transform.OneNodeExprsWithNode(n, func(node sql.Node, e sql.Expression) (sql.Expression, transform.TreeIdentity, error) { | ||
if sq, ok := e.(*plan.Subquery); ok { | ||
newSq, same2, err := analyzeSubqueryExpression(ctx, a, node, sq, scope, sel, true) | ||
if err != nil { | ||
if analyzererrors.ErrValidationResolved.Is(err) { | ||
// if a parent is unresolved, we want to dig deeper to find the unresolved | ||
// child dependency | ||
_, _, err := finalizeSubqueriesHelper(ctx, a, sq.Query, scope.newScopeFromSubqueryExpression(node), sel) | ||
if err != nil { | ||
return e, transform.SameTree, err | ||
} | ||
return e, transform.SameTree, err | ||
} | ||
newExpr, same1, err := finalizeSubqueriesHelper(ctx, a, newSq.(*plan.Subquery).Query, scope.newScopeFromSubqueryExpression(node), sel) | ||
if err != nil { | ||
return e, transform.SameTree, err | ||
} | ||
return e, transform.SameTree, err | ||
} | ||
newExpr, same1, err := finalizeSubqueriesHelper(ctx, a, newSq.(*plan.Subquery).Query, scope.newScopeFromSubqueryExpression(node), sel) | ||
if err != nil { | ||
return e, transform.SameTree, err | ||
} | ||
|
||
if same1 && same2 { | ||
return e, transform.SameTree, nil | ||
} else { | ||
return newSq.(*plan.Subquery).WithQuery(newExpr), transform.NewTree, nil | ||
} | ||
} else { | ||
if same1 && same2 { | ||
return e, transform.SameTree, nil | ||
} else { | ||
return newSq.(*plan.Subquery).WithQuery(newExpr), transform.NewTree, nil | ||
} | ||
}) | ||
} | ||
}) | ||
} else { | ||
return e, transform.SameTree, nil | ||
} | ||
}) | ||
} | ||
|
||
return transform.NodeWithCtx(node, selFunc, conFunc) | ||
} | ||
|
||
func resolveSubqueriesHelper(ctx *sql.Context, a *Analyzer, node sql.Node, scope *Scope, sel RuleSelector, finalize bool) (sql.Node, transform.TreeIdentity, error) { | ||
|
@@ -420,10 +443,27 @@ func setJoinScopeLen(ctx *sql.Context, a *Analyzer, n sql.Node, scope *Scope, se | |
if scopeLen == 0 { | ||
return n, transform.SameTree, nil | ||
} | ||
|
||
joinlessScopeLen := scopeLen | ||
if scope.inJoin { | ||
scope.SetJoin(false) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comment. Use these as values to compute things you need, rather than temporarily modifying |
||
joinlessScopeLen = len(scope.Schema()) | ||
scope.SetJoin(true) | ||
} | ||
return transform.Node(n, func(n sql.Node) (sql.Node, transform.TreeIdentity, error) { | ||
if j, ok := n.(*plan.JoinNode); ok { | ||
nj := j.WithScopeLen(scopeLen) | ||
if _, ok := nj.Left().(*plan.StripRowNode); !ok { | ||
if _, ok := nj.Right().(*plan.HashLookup); ok { | ||
nnj, err := nj.WithChildren( | ||
plan.NewStripRowNode(nj.Left(), joinlessScopeLen), | ||
plan.NewStripRowNode(nj.Right(), joinlessScopeLen), | ||
) | ||
if err != nil { | ||
return nil, transform.SameTree, err | ||
} | ||
return nnj, transform.NewTree, nil | ||
} | ||
nj, err := nj.WithChildren( | ||
plan.NewStripRowNode(nj.Left(), scopeLen), | ||
plan.NewStripRowNode(nj.Right(), scopeLen), | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a comment tagging the original issue might be worthwhile