github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/petri/acyclic/causet/embedded/optimize_test.go (about)

     1  // Copyright 2020 WHTCORPS INC, 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 cascades
    15  
    16  import (
    17  	"context"
    18  	"math"
    19  	"testing"
    20  
    21  	"github.com/whtcorpsinc/BerolinaSQL"
    22  	"github.com/whtcorpsinc/BerolinaSQL/perceptron"
    23  	. "github.com/whtcorpsinc/check"
    24  	causetembedded "github.com/whtcorpsinc/milevadb/causet/embedded"
    25  	"github.com/whtcorpsinc/milevadb/causet/memo"
    26  	"github.com/whtcorpsinc/milevadb/causet/property"
    27  	"github.com/whtcorpsinc/milevadb/memex"
    28  	"github.com/whtcorpsinc/milevadb/schemareplicant"
    29  	"github.com/whtcorpsinc/milevadb/soliton/testleak"
    30  	"github.com/whtcorpsinc/milevadb/stochastikctx"
    31  )
    32  
    33  func TestT(t *testing.T) {
    34  	CustomVerboseFlag = true
    35  	TestingT(t)
    36  }
    37  
    38  var _ = Suite(&testCascadesSuite{})
    39  
    40  type testCascadesSuite struct {
    41  	*BerolinaSQL.BerolinaSQL
    42  	is        schemareplicant.SchemaReplicant
    43  	sctx      stochastikctx.Context
    44  	optimizer *Optimizer
    45  }
    46  
    47  func (s *testCascadesSuite) SetUpSuite(c *C) {
    48  	testleak.BeforeTest()
    49  	s.is = schemareplicant.MockSchemaReplicant([]*perceptron.BlockInfo{causetembedded.MockSignedBlock()})
    50  	s.sctx = causetembedded.MockContext()
    51  	s.BerolinaSQL = BerolinaSQL.New()
    52  	s.optimizer = NewOptimizer()
    53  }
    54  
    55  func (s *testCascadesSuite) TearDownSuite(c *C) {
    56  	testleak.AfterTest(c)()
    57  }
    58  
    59  func (s *testCascadesSuite) TestImplGroupZeroCost(c *C) {
    60  	stmt, err := s.ParseOneStmt("select t1.a, t2.a from t as t1 left join t as t2 on t1.a = t2.a where t1.a < 1.0", "", "")
    61  	c.Assert(err, IsNil)
    62  	p, _, err := causetembedded.BuildLogicalCauset(context.Background(), s.sctx, stmt, s.is)
    63  	c.Assert(err, IsNil)
    64  	logic, ok := p.(causetembedded.LogicalCauset)
    65  	c.Assert(ok, IsTrue)
    66  	rootGroup := memo.Convert2Group(logic)
    67  	prop := &property.PhysicalProperty{
    68  		ExpectedCnt: math.MaxFloat64,
    69  	}
    70  	impl, err := s.optimizer.implGroup(rootGroup, prop, 0.0)
    71  	c.Assert(impl, IsNil)
    72  	c.Assert(err, IsNil)
    73  }
    74  
    75  func (s *testCascadesSuite) TestInitGroupSchema(c *C) {
    76  	stmt, err := s.ParseOneStmt("select a from t", "", "")
    77  	c.Assert(err, IsNil)
    78  	p, _, err := causetembedded.BuildLogicalCauset(context.Background(), s.sctx, stmt, s.is)
    79  	c.Assert(err, IsNil)
    80  	logic, ok := p.(causetembedded.LogicalCauset)
    81  	c.Assert(ok, IsTrue)
    82  	g := memo.Convert2Group(logic)
    83  	c.Assert(g, NotNil)
    84  	c.Assert(g.Prop, NotNil)
    85  	c.Assert(g.Prop.Schema.Len(), Equals, 1)
    86  	c.Assert(g.Prop.Stats, IsNil)
    87  }
    88  
    89  func (s *testCascadesSuite) TestFillGroupStats(c *C) {
    90  	stmt, err := s.ParseOneStmt("select * from t t1 join t t2 on t1.a = t2.a", "", "")
    91  	c.Assert(err, IsNil)
    92  	p, _, err := causetembedded.BuildLogicalCauset(context.Background(), s.sctx, stmt, s.is)
    93  	c.Assert(err, IsNil)
    94  	logic, ok := p.(causetembedded.LogicalCauset)
    95  	c.Assert(ok, IsTrue)
    96  	rootGroup := memo.Convert2Group(logic)
    97  	err = s.optimizer.fillGroupStats(rootGroup)
    98  	c.Assert(err, IsNil)
    99  	c.Assert(rootGroup.Prop.Stats, NotNil)
   100  }
   101  
   102  func (s *testCascadesSuite) TestPreparePossibleProperties(c *C) {
   103  	s.optimizer.ResetTransformationMemrules(map[memo.Operand][]Transformation{
   104  		memo.OperandDataSource: {
   105  			NewMemruleEnumeratePaths(),
   106  		},
   107  	})
   108  	defer func() {
   109  		s.optimizer.ResetTransformationMemrules(DefaultMemruleBatches...)
   110  	}()
   111  	stmt, err := s.ParseOneStmt("select f, sum(a) from t group by f", "", "")
   112  	c.Assert(err, IsNil)
   113  	p, _, err := causetembedded.BuildLogicalCauset(context.Background(), s.sctx, stmt, s.is)
   114  	c.Assert(err, IsNil)
   115  	logic, ok := p.(causetembedded.LogicalCauset)
   116  	c.Assert(ok, IsTrue)
   117  	logic, err = s.optimizer.onPhasePreprocessing(s.sctx, logic)
   118  	c.Assert(err, IsNil)
   119  	// defCauslect the target defCausumns: f, a
   120  	ds, ok := logic.Children()[0].Children()[0].(*causetembedded.DataSource)
   121  	c.Assert(ok, IsTrue)
   122  	var defCausumnF, defCausumnA *memex.DeferredCauset
   123  	for i, defCaus := range ds.DeferredCausets {
   124  		if defCaus.Name.L == "f" {
   125  			defCausumnF = ds.Schema().DeferredCausets[i]
   126  		} else if defCaus.Name.L == "a" {
   127  			defCausumnA = ds.Schema().DeferredCausets[i]
   128  		}
   129  	}
   130  	c.Assert(defCausumnF, NotNil)
   131  	c.Assert(defCausumnA, NotNil)
   132  
   133  	agg, ok := logic.Children()[0].(*causetembedded.LogicalAggregation)
   134  	c.Assert(ok, IsTrue)
   135  	group := memo.Convert2Group(agg)
   136  	err = s.optimizer.onPhaseExploration(s.sctx, group)
   137  	c.Assert(err, IsNil)
   138  	// The memo looks like this:
   139  	// Group#0 Schema:[DeferredCauset#13,test.t.f]
   140  	//   Aggregation_2 input:[Group#1], group by:test.t.f, funcs:sum(test.t.a), firstrow(test.t.f)
   141  	// Group#1 Schema:[test.t.a,test.t.f]
   142  	//   EinsteinDBSingleGather_5 input:[Group#2], causet:t
   143  	//   EinsteinDBSingleGather_9 input:[Group#3], causet:t, index:f_g
   144  	//   EinsteinDBSingleGather_7 input:[Group#4], causet:t, index:f
   145  	// Group#2 Schema:[test.t.a,test.t.f]
   146  	//   BlockScan_4 causet:t, pk defCaus:test.t.a
   147  	// Group#3 Schema:[test.t.a,test.t.f]
   148  	//   IndexScan_8 causet:t, index:f, g
   149  	// Group#4 Schema:[test.t.a,test.t.f]
   150  	//   IndexScan_6 causet:t, index:f
   151  	propMap := make(map[*memo.Group][][]*memex.DeferredCauset)
   152  	aggProp := preparePossibleProperties(group, propMap)
   153  	// We only have one prop for Group0 : f
   154  	c.Assert(len(aggProp), Equals, 1)
   155  	c.Assert(aggProp[0][0].Equal(nil, defCausumnF), IsTrue)
   156  
   157  	gatherGroup := group.Equivalents.Front().Value.(*memo.GroupExpr).Children[0]
   158  	gatherProp, ok := propMap[gatherGroup]
   159  	c.Assert(ok, IsTrue)
   160  	// We have 2 props for Group1: [f], [a]
   161  	c.Assert(len(gatherProp), Equals, 2)
   162  	for _, prop := range gatherProp {
   163  		c.Assert(len(prop), Equals, 1)
   164  		c.Assert(prop[0].Equal(nil, defCausumnA) || prop[0].Equal(nil, defCausumnF), IsTrue)
   165  	}
   166  }
   167  
   168  // fakeTransformation is used for TestAppliedMemruleSet.
   169  type fakeTransformation struct {
   170  	baseMemrule
   171  	appliedTimes int
   172  }
   173  
   174  // OnTransform implements Transformation interface.
   175  func (rule *fakeTransformation) OnTransform(old *memo.ExprIter) (newExprs []*memo.GroupExpr, eraseOld bool, eraseAll bool, err error) {
   176  	rule.appliedTimes++
   177  	old.GetExpr().AddAppliedMemrule(rule)
   178  	return []*memo.GroupExpr{old.GetExpr()}, true, false, nil
   179  }
   180  
   181  func (s *testCascadesSuite) TestAppliedMemruleSet(c *C) {
   182  	rule := fakeTransformation{}
   183  	rule.pattern = memo.NewPattern(memo.OperandProjection, memo.EngineAll)
   184  	s.optimizer.ResetTransformationMemrules(map[memo.Operand][]Transformation{
   185  		memo.OperandProjection: {
   186  			&rule,
   187  		},
   188  	})
   189  	defer func() {
   190  		s.optimizer.ResetTransformationMemrules(DefaultMemruleBatches...)
   191  	}()
   192  	stmt, err := s.ParseOneStmt("select 1", "", "")
   193  	c.Assert(err, IsNil)
   194  	p, _, err := causetembedded.BuildLogicalCauset(context.Background(), s.sctx, stmt, s.is)
   195  	c.Assert(err, IsNil)
   196  	logic, ok := p.(causetembedded.LogicalCauset)
   197  	c.Assert(ok, IsTrue)
   198  	group := memo.Convert2Group(logic)
   199  	err = s.optimizer.onPhaseExploration(s.sctx, group)
   200  	c.Assert(err, IsNil)
   201  	c.Assert(rule.appliedTimes, Equals, 1)
   202  }