github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/tidb/optimizer/new_plan_test.go (about)

     1  // Copyright 2016 PingCAP, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package optimizer
    15  
    16  import (
    17  	"testing"
    18  
    19  	. "github.com/insionng/yougam/libraries/pingcap/check"
    20  	"github.com/insionng/yougam/libraries/pingcap/tidb/ast"
    21  	"github.com/insionng/yougam/libraries/pingcap/tidb/infoschema"
    22  	"github.com/insionng/yougam/libraries/pingcap/tidb/model"
    23  	"github.com/insionng/yougam/libraries/pingcap/tidb/mysql"
    24  	"github.com/insionng/yougam/libraries/pingcap/tidb/optimizer/plan"
    25  	"github.com/insionng/yougam/libraries/pingcap/tidb/parser"
    26  	"github.com/insionng/yougam/libraries/pingcap/tidb/util/testleak"
    27  )
    28  
    29  var _ = Suite(&testPlanSuite{})
    30  
    31  func TestT(t *testing.T) {
    32  	TestingT(t)
    33  }
    34  
    35  type testPlanSuite struct{}
    36  
    37  func newMockResolve(node ast.Node) error {
    38  	indices := []*model.IndexInfo{
    39  		{
    40  			Name: model.NewCIStr("b"),
    41  			Columns: []*model.IndexColumn{
    42  				{
    43  					Name: model.NewCIStr("b"),
    44  				},
    45  			},
    46  		},
    47  		{
    48  			Name: model.NewCIStr("c_d_e"),
    49  			Columns: []*model.IndexColumn{
    50  				{
    51  					Name: model.NewCIStr("c"),
    52  				},
    53  				{
    54  					Name: model.NewCIStr("d"),
    55  				},
    56  				{
    57  					Name: model.NewCIStr("e"),
    58  				},
    59  			},
    60  		},
    61  	}
    62  	pkColumn := &model.ColumnInfo{
    63  		State: model.StatePublic,
    64  		Name:  model.NewCIStr("a"),
    65  	}
    66  	col1 := &model.ColumnInfo{
    67  		State: model.StatePublic,
    68  		Name:  model.NewCIStr("d"),
    69  	}
    70  	pkColumn.Flag = mysql.PriKeyFlag
    71  	table := &model.TableInfo{
    72  		Columns:    []*model.ColumnInfo{pkColumn, col1},
    73  		Indices:    indices,
    74  		Name:       model.NewCIStr("t"),
    75  		PKIsHandle: true,
    76  	}
    77  	is := infoschema.MockInfoSchema([]*model.TableInfo{table})
    78  	return MockResolveName(node, is, "test")
    79  }
    80  
    81  func (s *testPlanSuite) TestPredicatePushDown(c *C) {
    82  	plan.UseNewPlanner = true
    83  	defer testleak.AfterTest(c)()
    84  	cases := []struct {
    85  		sql   string
    86  		first string
    87  		best  string
    88  	}{
    89  		{
    90  			sql:   "select a from (select a from t where d = 0) k where k.a = 5",
    91  			first: "Table(t)->Filter->Fields->Filter->Fields",
    92  			best:  "Range(t)->Fields->Fields",
    93  		},
    94  		{
    95  			sql:   "select a from (select 1+2 as a from t where d = 0) k where k.a = 5",
    96  			first: "Table(t)->Filter->Fields->Filter->Fields",
    97  			best:  "Table(t)->Fields->Filter->Fields",
    98  		},
    99  		{
   100  			sql:   "select a from (select d as a from t where d = 0) k where k.a = 5",
   101  			first: "Table(t)->Filter->Fields->Filter->Fields",
   102  			best:  "Table(t)->Fields->Fields",
   103  		},
   104  		{
   105  			sql:   "select * from t ta join t tb on ta.d = tb.d and ta.d > 1 where tb.a = 0",
   106  			first: "Join{Table(t)->Table(t)}->Filter->Fields",
   107  			best:  "Join{Table(t)->Range(t)}->Fields",
   108  		},
   109  		{
   110  			sql:   "select * from t ta left outer join t tb on ta.d = tb.d and ta.d > 1 where tb.a = 0",
   111  			first: "Join{Table(t)->Table(t)}->Filter->Fields",
   112  			best:  "Join{Table(t)->Table(t)}->Filter->Fields",
   113  		},
   114  		{
   115  			sql:   "select * from t ta right outer join t tb on ta.d = tb.d and ta.a > 1 where tb.a = 0",
   116  			first: "Join{Table(t)->Table(t)}->Filter->Fields",
   117  			best:  "Join{Range(t)->Range(t)}->Fields",
   118  		},
   119  	}
   120  	for _, ca := range cases {
   121  		comment := Commentf("for %s", ca.sql)
   122  		stmt, err := parser.ParseOneStmt(ca.sql, "", "")
   123  		c.Assert(err, IsNil, comment)
   124  		ast.SetFlag(stmt)
   125  
   126  		err = newMockResolve(stmt)
   127  		c.Assert(err, IsNil)
   128  
   129  		p, err := plan.BuildPlan(stmt, nil)
   130  		c.Assert(err, IsNil)
   131  		c.Assert(plan.ToString(p), Equals, ca.first, Commentf("for %s", ca.sql))
   132  
   133  		_, err = plan.PredicatePushDown(p, []ast.ExprNode{})
   134  		c.Assert(err, IsNil)
   135  		err = plan.Refine(p)
   136  		c.Assert(err, IsNil)
   137  		c.Assert(plan.ToString(p), Equals, ca.best, Commentf("for %s", ca.sql))
   138  	}
   139  	plan.UseNewPlanner = false
   140  }