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 }