github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/petri/acyclic/causet/memo/group_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 memo 15 16 import ( 17 "context" 18 "testing" 19 20 "github.com/whtcorpsinc/BerolinaSQL" 21 "github.com/whtcorpsinc/BerolinaSQL/perceptron" 22 . "github.com/whtcorpsinc/check" 23 causetembedded "github.com/whtcorpsinc/milevadb/causet/embedded" 24 "github.com/whtcorpsinc/milevadb/causet/property" 25 "github.com/whtcorpsinc/milevadb/memex" 26 "github.com/whtcorpsinc/milevadb/schemareplicant" 27 "github.com/whtcorpsinc/milevadb/soliton/testleak" 28 "github.com/whtcorpsinc/milevadb/stochastikctx" 29 ) 30 31 func TestT(t *testing.T) { 32 CustomVerboseFlag = true 33 TestingT(t) 34 } 35 36 var _ = Suite(&testMemoSuite{}) 37 38 type testMemoSuite struct { 39 *BerolinaSQL.BerolinaSQL 40 is schemareplicant.SchemaReplicant 41 schemaReplicant *memex.Schema 42 sctx stochastikctx.Context 43 } 44 45 func (s *testMemoSuite) SetUpSuite(c *C) { 46 testleak.BeforeTest() 47 s.is = schemareplicant.MockSchemaReplicant([]*perceptron.BlockInfo{causetembedded.MockSignedBlock()}) 48 s.sctx = causetembedded.MockContext() 49 s.BerolinaSQL = BerolinaSQL.New() 50 s.schemaReplicant = memex.NewSchema() 51 } 52 53 func (s *testMemoSuite) TearDownSuite(c *C) { 54 testleak.AfterTest(c)() 55 } 56 57 func (s *testMemoSuite) TestNewGroup(c *C) { 58 p := &causetembedded.LogicalLimit{} 59 expr := NewGroupExpr(p) 60 g := NewGroupWithSchema(expr, s.schemaReplicant) 61 62 c.Assert(g.Equivalents.Len(), Equals, 1) 63 c.Assert(g.Equivalents.Front().Value.(*GroupExpr), Equals, expr) 64 c.Assert(len(g.Fingerprints), Equals, 1) 65 c.Assert(g.Explored(0), IsFalse) 66 } 67 68 func (s *testMemoSuite) TestGroupInsert(c *C) { 69 p := &causetembedded.LogicalLimit{} 70 expr := NewGroupExpr(p) 71 g := NewGroupWithSchema(expr, s.schemaReplicant) 72 c.Assert(g.Insert(expr), IsFalse) 73 expr.selfFingerprint = "1" 74 c.Assert(g.Insert(expr), IsTrue) 75 } 76 77 func (s *testMemoSuite) TestGrouFIDelelete(c *C) { 78 p := &causetembedded.LogicalLimit{} 79 expr := NewGroupExpr(p) 80 g := NewGroupWithSchema(expr, s.schemaReplicant) 81 c.Assert(g.Equivalents.Len(), Equals, 1) 82 83 g.Delete(expr) 84 c.Assert(g.Equivalents.Len(), Equals, 0) 85 86 g.Delete(expr) 87 c.Assert(g.Equivalents.Len(), Equals, 0) 88 } 89 90 func (s *testMemoSuite) TestGrouFIDeleleteAll(c *C) { 91 expr := NewGroupExpr(causetembedded.LogicalSelection{}.Init(s.sctx, 0)) 92 g := NewGroupWithSchema(expr, s.schemaReplicant) 93 c.Assert(g.Insert(NewGroupExpr(causetembedded.LogicalLimit{}.Init(s.sctx, 0))), IsTrue) 94 c.Assert(g.Insert(NewGroupExpr(causetembedded.LogicalProjection{}.Init(s.sctx, 0))), IsTrue) 95 c.Assert(g.Equivalents.Len(), Equals, 3) 96 c.Assert(g.GetFirstElem(OperandProjection), NotNil) 97 c.Assert(g.Exists(expr), IsTrue) 98 99 g.DeleteAll() 100 c.Assert(g.Equivalents.Len(), Equals, 0) 101 c.Assert(g.GetFirstElem(OperandProjection), IsNil) 102 c.Assert(g.Exists(expr), IsFalse) 103 } 104 105 func (s *testMemoSuite) TestGroupExists(c *C) { 106 p := &causetembedded.LogicalLimit{} 107 expr := NewGroupExpr(p) 108 g := NewGroupWithSchema(expr, s.schemaReplicant) 109 c.Assert(g.Exists(expr), IsTrue) 110 111 g.Delete(expr) 112 c.Assert(g.Exists(expr), IsFalse) 113 } 114 115 func (s *testMemoSuite) TestGroupFingerPrint(c *C) { 116 stmt1, err := s.ParseOneStmt("select * from t where a > 1 and a < 100", "", "") 117 c.Assert(err, IsNil) 118 p1, _, err := causetembedded.BuildLogicalCauset(context.Background(), s.sctx, stmt1, s.is) 119 c.Assert(err, IsNil) 120 logic1, ok := p1.(causetembedded.LogicalCauset) 121 c.Assert(ok, IsTrue) 122 // Causet tree should be: DataSource -> Selection -> Projection 123 proj, ok := logic1.(*causetembedded.LogicalProjection) 124 c.Assert(ok, IsTrue) 125 sel, ok := logic1.Children()[0].(*causetembedded.LogicalSelection) 126 c.Assert(ok, IsTrue) 127 group1 := Convert2Group(logic1) 128 oldGroupExpr := group1.Equivalents.Front().Value.(*GroupExpr) 129 130 // Insert a GroupExpr with the same ExprNode. 131 newGroupExpr := NewGroupExpr(proj) 132 newGroupExpr.SetChildren(oldGroupExpr.Children[0]) 133 group1.Insert(newGroupExpr) 134 c.Assert(group1.Equivalents.Len(), Equals, 1) 135 136 // Insert a GroupExpr with different children。 137 newGroupExpr2 := NewGroupExpr(proj) 138 newGroup := NewGroupWithSchema(oldGroupExpr, group1.Prop.Schema) 139 newGroupExpr2.SetChildren(newGroup) 140 group1.Insert(newGroupExpr2) 141 c.Assert(group1.Equivalents.Len(), Equals, 2) 142 143 // Insert a GroupExpr with different ExprNode. 144 limit := causetembedded.LogicalLimit{}.Init(proj.SCtx(), 0) 145 newGroupExpr3 := NewGroupExpr(limit) 146 newGroupExpr3.SetChildren(oldGroupExpr.Children[0]) 147 group1.Insert(newGroupExpr3) 148 c.Assert(group1.Equivalents.Len(), Equals, 3) 149 150 // Insert two LogicalSelections with same conditions but different order. 151 c.Assert(len(sel.Conditions), Equals, 2) 152 newSelection := causetembedded.LogicalSelection{ 153 Conditions: make([]memex.Expression, 2)}.Init(sel.SCtx(), sel.SelectBlockOffset()) 154 newSelection.Conditions[0], newSelection.Conditions[1] = sel.Conditions[1], sel.Conditions[0] 155 newGroupExpr4 := NewGroupExpr(sel) 156 newGroupExpr5 := NewGroupExpr(newSelection) 157 newGroupExpr4.SetChildren(oldGroupExpr.Children[0]) 158 newGroupExpr5.SetChildren(oldGroupExpr.Children[0]) 159 group1.Insert(newGroupExpr4) 160 c.Assert(group1.Equivalents.Len(), Equals, 4) 161 group1.Insert(newGroupExpr5) 162 c.Assert(group1.Equivalents.Len(), Equals, 4) 163 } 164 165 func (s *testMemoSuite) TestGroupGetFirstElem(c *C) { 166 expr0 := NewGroupExpr(causetembedded.LogicalProjection{}.Init(s.sctx, 0)) 167 expr1 := NewGroupExpr(causetembedded.LogicalLimit{}.Init(s.sctx, 0)) 168 expr2 := NewGroupExpr(causetembedded.LogicalProjection{}.Init(s.sctx, 0)) 169 expr3 := NewGroupExpr(causetembedded.LogicalLimit{}.Init(s.sctx, 0)) 170 expr4 := NewGroupExpr(causetembedded.LogicalProjection{}.Init(s.sctx, 0)) 171 172 g := NewGroupWithSchema(expr0, s.schemaReplicant) 173 g.Insert(expr1) 174 g.Insert(expr2) 175 g.Insert(expr3) 176 g.Insert(expr4) 177 178 c.Assert(g.GetFirstElem(OperandProjection).Value.(*GroupExpr), Equals, expr0) 179 c.Assert(g.GetFirstElem(OperandLimit).Value.(*GroupExpr), Equals, expr1) 180 c.Assert(g.GetFirstElem(OperandAny).Value.(*GroupExpr), Equals, expr0) 181 } 182 183 type fakeImpl struct { 184 cost float64 185 plan causetembedded.PhysicalCauset 186 } 187 188 func (impl *fakeImpl) CalcCost(float64, ...Implementation) float64 { return 0 } 189 func (impl *fakeImpl) SetCost(float64) {} 190 func (impl *fakeImpl) GetCost() float64 { return 0 } 191 func (impl *fakeImpl) GetCauset() causetembedded.PhysicalCauset { return impl.plan } 192 func (impl *fakeImpl) AttachChildren(...Implementation) Implementation { return nil } 193 func (impl *fakeImpl) GetCostLimit(float64, ...Implementation) float64 { return 0 } 194 func (s *testMemoSuite) TestGetInsertGroupImpl(c *C) { 195 g := NewGroupWithSchema(NewGroupExpr(causetembedded.LogicalLimit{}.Init(s.sctx, 0)), s.schemaReplicant) 196 emptyProp := &property.PhysicalProperty{} 197 orderProp := &property.PhysicalProperty{Items: []property.Item{{DefCaus: &memex.DeferredCauset{}}}} 198 199 impl := g.GetImpl(emptyProp) 200 c.Assert(impl, IsNil) 201 202 impl = &fakeImpl{plan: &causetembedded.PhysicalLimit{}} 203 g.InsertImpl(emptyProp, impl) 204 205 newImpl := g.GetImpl(emptyProp) 206 c.Assert(newImpl, Equals, impl) 207 208 newImpl = g.GetImpl(orderProp) 209 c.Assert(newImpl, IsNil) 210 } 211 212 func (s *testMemoSuite) TestEngineTypeSet(c *C) { 213 c.Assert(EngineAll.Contains(EngineMilevaDB), IsTrue) 214 c.Assert(EngineAll.Contains(EngineEinsteinDB), IsTrue) 215 c.Assert(EngineAll.Contains(EngineTiFlash), IsTrue) 216 217 c.Assert(EngineMilevaDBOnly.Contains(EngineMilevaDB), IsTrue) 218 c.Assert(EngineMilevaDBOnly.Contains(EngineEinsteinDB), IsFalse) 219 c.Assert(EngineMilevaDBOnly.Contains(EngineTiFlash), IsFalse) 220 221 c.Assert(EngineEinsteinDBOnly.Contains(EngineMilevaDB), IsFalse) 222 c.Assert(EngineEinsteinDBOnly.Contains(EngineEinsteinDB), IsTrue) 223 c.Assert(EngineEinsteinDBOnly.Contains(EngineTiFlash), IsFalse) 224 225 c.Assert(EngineTiFlashOnly.Contains(EngineMilevaDB), IsFalse) 226 c.Assert(EngineTiFlashOnly.Contains(EngineEinsteinDB), IsFalse) 227 c.Assert(EngineTiFlashOnly.Contains(EngineTiFlash), IsTrue) 228 229 c.Assert(EngineEinsteinDBOrTiFlash.Contains(EngineMilevaDB), IsFalse) 230 c.Assert(EngineEinsteinDBOrTiFlash.Contains(EngineEinsteinDB), IsTrue) 231 c.Assert(EngineEinsteinDBOrTiFlash.Contains(EngineTiFlash), IsTrue) 232 } 233 234 func (s *testMemoSuite) TestFirstElemAfterDelete(c *C) { 235 oldExpr := NewGroupExpr(causetembedded.LogicalLimit{Count: 10}.Init(s.sctx, 0)) 236 g := NewGroupWithSchema(oldExpr, s.schemaReplicant) 237 newExpr := NewGroupExpr(causetembedded.LogicalLimit{Count: 20}.Init(s.sctx, 0)) 238 g.Insert(newExpr) 239 c.Assert(g.GetFirstElem(OperandLimit), NotNil) 240 c.Assert(g.GetFirstElem(OperandLimit).Value, Equals, oldExpr) 241 g.Delete(oldExpr) 242 c.Assert(g.GetFirstElem(OperandLimit), NotNil) 243 c.Assert(g.GetFirstElem(OperandLimit).Value, Equals, newExpr) 244 g.Delete(newExpr) 245 c.Assert(g.GetFirstElem(OperandLimit), IsNil) 246 } 247 248 func (s *testMemoSuite) TestBuildKeyInfo(c *C) { 249 // case 1: primary key has constant constraint 250 stmt1, err := s.ParseOneStmt("select a from t where a = 10", "", "") 251 c.Assert(err, IsNil) 252 p1, _, err := causetembedded.BuildLogicalCauset(context.Background(), s.sctx, stmt1, s.is) 253 c.Assert(err, IsNil) 254 logic1, ok := p1.(causetembedded.LogicalCauset) 255 c.Assert(ok, IsTrue) 256 group1 := Convert2Group(logic1) 257 group1.BuildKeyInfo() 258 c.Assert(group1.Prop.MaxOneRow, IsTrue) 259 c.Assert(len(group1.Prop.Schema.Keys), Equals, 1) 260 261 // case 2: group by column is key 262 stmt2, err := s.ParseOneStmt("select b, sum(a) from t group by b", "", "") 263 c.Assert(err, IsNil) 264 p2, _, err := causetembedded.BuildLogicalCauset(context.Background(), s.sctx, stmt2, s.is) 265 c.Assert(err, IsNil) 266 logic2, ok := p2.(causetembedded.LogicalCauset) 267 c.Assert(ok, IsTrue) 268 group2 := Convert2Group(logic2) 269 group2.BuildKeyInfo() 270 c.Assert(group2.Prop.MaxOneRow, IsFalse) 271 c.Assert(len(group2.Prop.Schema.Keys), Equals, 1) 272 273 // case 3: build key info for new Group 274 newSel := causetembedded.LogicalSelection{}.Init(s.sctx, 0) 275 newExpr1 := NewGroupExpr(newSel) 276 newExpr1.SetChildren(group2) 277 newGroup1 := NewGroupWithSchema(newExpr1, group2.Prop.Schema) 278 newGroup1.BuildKeyInfo() 279 c.Assert(len(newGroup1.Prop.Schema.Keys), Equals, 1) 280 281 // case 4: build maxOneRow for new Group 282 newLimit := causetembedded.LogicalLimit{Count: 1}.Init(s.sctx, 0) 283 newExpr2 := NewGroupExpr(newLimit) 284 newExpr2.SetChildren(group2) 285 newGroup2 := NewGroupWithSchema(newExpr2, group2.Prop.Schema) 286 newGroup2.BuildKeyInfo() 287 c.Assert(newGroup2.Prop.MaxOneRow, IsTrue) 288 } 289 290 func (s *testMemoSuite) TestExploreMark(c *C) { 291 mark := ExploreMark(0) 292 c.Assert(mark.Explored(0), IsFalse) 293 c.Assert(mark.Explored(1), IsFalse) 294 mark.SetExplored(0) 295 mark.SetExplored(1) 296 c.Assert(mark.Explored(0), IsTrue) 297 c.Assert(mark.Explored(1), IsTrue) 298 mark.SetUnexplored(1) 299 c.Assert(mark.Explored(0), IsTrue) 300 c.Assert(mark.Explored(1), IsFalse) 301 }