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  }