github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/petri/acyclic/causet/memo/group_expr.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 "encoding/binary" 18 "reflect" 19 20 causetembedded "github.com/whtcorpsinc/milevadb/causet/embedded" 21 "github.com/whtcorpsinc/milevadb/memex" 22 ) 23 24 // GroupExpr is used to causetstore all the logically equivalent memexs which 25 // have the same root operator. Different from a normal memex, the 26 // Children of a Group memex are memex Groups, not memexs. 27 // Another property of Group memex is that the child Group references will 28 // never be changed once the Group memex is created. 29 type GroupExpr struct { 30 ExprNode causetembedded.LogicalCauset 31 Children []*Group 32 Group *Group 33 34 // ExploreMark is uses to mark whether this GroupExpr has been fully 35 // explored by a transformation rule batch in a certain round. 36 ExploreMark 37 38 selfFingerprint string 39 // appliedMemruleSet saves transformation rules which have been applied to this 40 // GroupExpr, and will not be applied again. Use `uint64` which should be the 41 // id of a Transformation instead of `Transformation` itself to avoid import cycle. 42 appliedMemruleSet map[uint64]struct{} 43 } 44 45 // NewGroupExpr creates a GroupExpr based on a logical plan node. 46 func NewGroupExpr(node causetembedded.LogicalCauset) *GroupExpr { 47 return &GroupExpr{ 48 ExprNode: node, 49 Children: nil, 50 appliedMemruleSet: make(map[uint64]struct{}), 51 } 52 } 53 54 // FingerPrint gets the unique fingerprint of the Group memex. 55 func (e *GroupExpr) FingerPrint() string { 56 if len(e.selfFingerprint) == 0 { 57 planHash := e.ExprNode.HashCode() 58 buffer := make([]byte, 2, 2+len(e.Children)*8+len(planHash)) 59 binary.BigEndian.PutUint16(buffer, uint16(len(e.Children))) 60 for _, child := range e.Children { 61 var buf [8]byte 62 binary.BigEndian.PutUint64(buf[:], uint64(reflect.ValueOf(child).Pointer())) 63 buffer = append(buffer, buf[:]...) 64 } 65 buffer = append(buffer, planHash...) 66 e.selfFingerprint = string(buffer) 67 } 68 return e.selfFingerprint 69 } 70 71 // SetChildren sets Children of the GroupExpr. 72 func (e *GroupExpr) SetChildren(children ...*Group) { 73 e.Children = children 74 } 75 76 // Schema gets GroupExpr's Schema. 77 func (e *GroupExpr) Schema() *memex.Schema { 78 return e.Group.Prop.Schema 79 } 80 81 // AddAppliedMemrule adds a rule into the appliedMemruleSet. 82 func (e *GroupExpr) AddAppliedMemrule(rule interface{}) { 83 ruleID := reflect.ValueOf(rule).Pointer() 84 e.appliedMemruleSet[uint64(ruleID)] = struct{}{} 85 } 86 87 // HasAppliedMemrule returns if the rule has been applied. 88 func (e *GroupExpr) HasAppliedMemrule(rule interface{}) bool { 89 ruleID := reflect.ValueOf(rule).Pointer() 90 _, ok := e.appliedMemruleSet[uint64(ruleID)] 91 return ok 92 }