Skip to content

Commit

Permalink
*: Address comment
Browse files Browse the repository at this point in the history
  • Loading branch information
shenli committed Feb 2, 2016
1 parent 0b60991 commit a4503d3
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 36 deletions.
15 changes: 8 additions & 7 deletions ast/expressions.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,9 +229,10 @@ func (n *CaseExpr) Accept(v Visitor) (Node, bool) {
return v.Leave(n)
}

// SubQuery represents a subquery interface.
// SubqueryExec represents a subquery executor interface.
// This interface is implemented in executor and used in plan/evaluator.
type SubQuery interface {
// It will execute the subselect and get the result.
type SubqueryExec interface {
ExprNode

// EvalRows executes the subquery and returns the multi rows with rowCount.
Expand All @@ -249,7 +250,7 @@ type SubqueryExpr struct {
exprNode
// Query is the query SelectNode.
Query ResultSetNode
SubQuery SubQuery
SubqueryExec SubqueryExec
Evaluated bool
UseOuterContext bool
}
Expand All @@ -262,16 +263,16 @@ func (n *SubqueryExpr) Accept(v Visitor) (Node, bool) {
}
n = newNode.(*SubqueryExpr)

if n.SubQuery != nil {
t, ok := n.SubQuery.Accept(v)
if n.SubqueryExec != nil {
t, ok := n.SubqueryExec.Accept(v)
if !ok {
return n, false
}
sq, ok := t.(SubQuery)
sq, ok := t.(SubqueryExec)
if !ok {
return n, false
}
n.SubQuery = sq
n.SubqueryExec = sq
return v.Leave(n)
}

Expand Down
4 changes: 1 addition & 3 deletions executor/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,7 @@ func (c *Compiler) Compile(ctx context.Context, node ast.StmtNode) (stmt.Stateme
if err := optimizer.Validate(node, false); err != nil {
return nil, errors.Trace(err)
}
sb := &subqueryBuilder{
is: is,
}
sb := NewSubQueryBuilder(is)
p, err := optimizer.Optimize(ctx, node, sb)
if err != nil {
return nil, errors.Trace(err)
Expand Down
9 changes: 7 additions & 2 deletions executor/subquery.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import (
"github.com/pingcap/tidb/util/types"
)

var _ ast.SubqueryExec = &subquery{}

// SubQuery is an exprNode with a plan.
type subquery struct {
types.DataItem
Expand Down Expand Up @@ -93,9 +95,12 @@ func (sq *subquery) EvalRows(ctx context.Context, rowCount int) ([]interface{},
// No result fields means no Recordset.
for {
row, err := e.Next()
if err != nil || row == nil {
if err != nil {
return nil, errors.Trace(err)
}
if row == nil {
return nil, nil
}
}
}
var (
Expand Down Expand Up @@ -131,7 +136,7 @@ type subqueryBuilder struct {
is infoschema.InfoSchema
}

func (sb *subqueryBuilder) Build(p plan.Plan) ast.SubQuery {
func (sb *subqueryBuilder) Build(p plan.Plan) ast.SubqueryExec {
return &subquery{
is: sb.is,
plan: p,
Expand Down
36 changes: 19 additions & 17 deletions optimizer/evaluator/evaluator.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ func (e *Evaluator) Leave(in ast.Node) (out ast.Node, ok bool) {
ok = e.row(v)
case *ast.SubqueryExpr:
ok = e.subqueryExpr(v)
case ast.SubQuery:
case ast.SubqueryExec:
ok = e.subqueryExec(v)
case *ast.UnaryOperationExpr:
ok = e.unaryOperation(v)
Expand Down Expand Up @@ -245,6 +245,7 @@ func (e *Evaluator) compareSubquery(cs *ast.CompareSubqueryExpr) bool {
}
x, err := e.checkResult(cs, lv, cs.R.GetValue().([]interface{}))
if err != nil {
e.err = errors.Trace(err)
return false
}
cs.SetValue(x)
Expand Down Expand Up @@ -339,15 +340,15 @@ func (e *Evaluator) existsSubquery(v *ast.ExistsSubqueryExpr) bool {
// Evaluate SubqueryExpr.
// Get the value from v.SubQuery and set it to v.
func (e *Evaluator) subqueryExpr(v *ast.SubqueryExpr) bool {
if v.SubQuery != nil {
v.SetValue(v.SubQuery.GetValue())
if v.SubqueryExec != nil {
v.SetValue(v.SubqueryExec.GetValue())
}
v.Evaluated = true
return true
}

// Do the real work to evaluate subquery.
func (e *Evaluator) subqueryExec(v ast.SubQuery) bool {
func (e *Evaluator) subqueryExec(v ast.SubqueryExec) bool {
rowCount := 2
if e.multipleRows {
rowCount = -1
Expand All @@ -356,7 +357,7 @@ func (e *Evaluator) subqueryExec(v ast.SubQuery) bool {
}
rows, err := v.EvalRows(e.ctx, rowCount)
if err != nil {
e.err = err
e.err = errors.Trace(err)
return false
}
if e.multipleRows || e.existRow {
Expand All @@ -375,7 +376,7 @@ func (e *Evaluator) subqueryExec(v ast.SubQuery) bool {
return true
}

func (e *Evaluator) checkInList(not bool, in interface{}, list []interface{}) (interface{}, error) {
func (e *Evaluator) checkInList(not bool, in interface{}, list []interface{}) interface{} {
hasNull := false
for _, v := range list {
if types.IsNil(v) {
Expand All @@ -385,25 +386,26 @@ func (e *Evaluator) checkInList(not bool, in interface{}, list []interface{}) (i

r, err := types.Compare(in, v)
if err != nil {
return nil, errors.Trace(err)
e.err = errors.Trace(err)
return nil
}
if r == 0 {
if !not {
return 1, nil
return 1
}
return 0, nil
return 0
}
}

if hasNull {
// if no matched but we got null in In, return null
// e.g 1 in (null, 2, 3) returns null
return nil, nil
return nil
}
if not {
return 1, nil
return 1
}
return 0, nil
return 0
}

func (e *Evaluator) patternIn(n *ast.PatternInExpr) bool {
Expand All @@ -417,19 +419,19 @@ func (e *Evaluator) patternIn(n *ast.PatternInExpr) bool {
for _, ei := range n.List {
values = append(values, ei.GetValue())
}
x, err := e.checkInList(n.Not, lhs, values)
if err != nil {
x := e.checkInList(n.Not, lhs, values)
if e.err != nil {
return false
}
n.SetValue(x)
return true
}
se := n.Sel.(*ast.SubqueryExpr)
sel := se.SubQuery
sel := se.SubqueryExec

res := sel.GetValue().([]interface{})
x, err := e.checkInList(n.Not, lhs, res)
if err != nil {
x := e.checkInList(n.Not, lhs, res)
if e.err != nil {
return false
}
n.SetValue(x)
Expand Down
12 changes: 5 additions & 7 deletions optimizer/plan/planbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@
package plan

import (
"fmt"

"github.com/juju/errors"
"github.com/ngaut/log"
"github.com/pingcap/tidb/ast"
"github.com/pingcap/tidb/infoschema"
"github.com/pingcap/tidb/model"
Expand Down Expand Up @@ -163,7 +162,7 @@ func (b *planBuilder) buildSubquery(n ast.Node) {
}
_, ok := n.Accept(sv)
if !ok {
fmt.Println("Extract subquery error")
log.Errorf("Extract subquery error")
}
}

Expand Down Expand Up @@ -551,13 +550,12 @@ func splitWhere(where ast.ExprNode) []ast.ExprNode {

// SubQueryBuilder is the interface for building SubQuery executor.
type SubQueryBuilder interface {
Build(p Plan) ast.SubQuery
Build(p Plan) ast.SubqueryExec
}

// subqueryVisitor visits AST and handles SubqueryExpr.
type subqueryVisitor struct {
subqueries []ast.SubQuery
builder *planBuilder
builder *planBuilder
}

func (se *subqueryVisitor) Enter(in ast.Node) (out ast.Node, skipChildren bool) {
Expand All @@ -567,7 +565,7 @@ func (se *subqueryVisitor) Enter(in ast.Node) (out ast.Node, skipChildren bool)
// The expr pointor is copyed into ResultField when running name resolver.
// So we can not just replace the expr node in AST. We need to put SubQuery into the expr.
// See: optimizer.nameResolver.createResultFields()
x.SubQuery = se.builder.sb.Build(p)
x.SubqueryExec = se.builder.sb.Build(p)
return in, true
case *ast.Join:
// SubSelect in from clause will be handled in buildJoin().
Expand Down

0 comments on commit a4503d3

Please sign in to comment.