github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/petri/acyclic/causet/embedded/util.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 embedded 15 16 import ( 17 "fmt" 18 "sort" 19 "strings" 20 21 "github.com/whtcorpsinc/BerolinaSQL/ast" 22 "github.com/whtcorpsinc/BerolinaSQL/perceptron" 23 "github.com/whtcorpsinc/milevadb/memex" 24 "github.com/whtcorpsinc/milevadb/soliton/ranger" 25 "github.com/whtcorpsinc/milevadb/soliton/set" 26 "github.com/whtcorpsinc/milevadb/stochastikctx" 27 "github.com/whtcorpsinc/milevadb/types" 28 ) 29 30 // AggregateFuncExtractor visits Expr tree. 31 // It converts DefCausunmNameExpr to AggregateFuncExpr and collects AggregateFuncExpr. 32 type AggregateFuncExtractor struct { 33 inAggregateFuncExpr bool 34 // AggFuncs is the collected AggregateFuncExprs. 35 AggFuncs []*ast.AggregateFuncExpr 36 } 37 38 // Enter implements Visitor interface. 39 func (a *AggregateFuncExtractor) Enter(n ast.Node) (ast.Node, bool) { 40 switch n.(type) { 41 case *ast.AggregateFuncExpr: 42 a.inAggregateFuncExpr = true 43 case *ast.SelectStmt, *ast.SetOprStmt: 44 return n, true 45 } 46 return n, false 47 } 48 49 // Leave implements Visitor interface. 50 func (a *AggregateFuncExtractor) Leave(n ast.Node) (ast.Node, bool) { 51 switch v := n.(type) { 52 case *ast.AggregateFuncExpr: 53 a.inAggregateFuncExpr = false 54 a.AggFuncs = append(a.AggFuncs, v) 55 } 56 return n, true 57 } 58 59 // WindowFuncExtractor visits Expr tree. 60 // It converts DefCausunmNameExpr to WindowFuncExpr and collects WindowFuncExpr. 61 type WindowFuncExtractor struct { 62 // WindowFuncs is the collected WindowFuncExprs. 63 windowFuncs []*ast.WindowFuncExpr 64 } 65 66 // Enter implements Visitor interface. 67 func (a *WindowFuncExtractor) Enter(n ast.Node) (ast.Node, bool) { 68 switch n.(type) { 69 case *ast.SelectStmt, *ast.SetOprStmt: 70 return n, true 71 } 72 return n, false 73 } 74 75 // Leave implements Visitor interface. 76 func (a *WindowFuncExtractor) Leave(n ast.Node) (ast.Node, bool) { 77 switch v := n.(type) { 78 case *ast.WindowFuncExpr: 79 a.windowFuncs = append(a.windowFuncs, v) 80 } 81 return n, true 82 } 83 84 // logicalSchemaProducer stores the schemaReplicant for the logical plans who can produce schemaReplicant directly. 85 type logicalSchemaProducer struct { 86 schemaReplicant *memex.Schema 87 names types.NameSlice 88 baseLogicalCauset 89 } 90 91 // Schema implements the Causet.Schema interface. 92 func (s *logicalSchemaProducer) Schema() *memex.Schema { 93 if s.schemaReplicant == nil { 94 s.schemaReplicant = memex.NewSchema() 95 } 96 return s.schemaReplicant 97 } 98 99 func (s *logicalSchemaProducer) OutputNames() types.NameSlice { 100 return s.names 101 } 102 103 func (s *logicalSchemaProducer) SetOutputNames(names types.NameSlice) { 104 s.names = names 105 } 106 107 // SetSchema implements the Causet.SetSchema interface. 108 func (s *logicalSchemaProducer) SetSchema(schemaReplicant *memex.Schema) { 109 s.schemaReplicant = schemaReplicant 110 } 111 112 func (s *logicalSchemaProducer) setSchemaAndNames(schemaReplicant *memex.Schema, names types.NameSlice) { 113 s.schemaReplicant = schemaReplicant 114 s.names = names 115 } 116 117 // inlineProjection prunes unneeded columns inline a interlock. 118 func (s *logicalSchemaProducer) inlineProjection(parentUsedDefCauss []*memex.DeferredCauset) { 119 used := memex.GetUsedList(parentUsedDefCauss, s.schemaReplicant) 120 for i := len(used) - 1; i >= 0; i-- { 121 if !used[i] { 122 s.schemaReplicant.DeferredCausets = append(s.schemaReplicant.DeferredCausets[:i], s.schemaReplicant.DeferredCausets[i+1:]...) 123 } 124 } 125 } 126 127 // physicalSchemaProducer stores the schemaReplicant for the physical plans who can produce schemaReplicant directly. 128 type physicalSchemaProducer struct { 129 schemaReplicant *memex.Schema 130 basePhysicalCauset 131 } 132 133 func (s *physicalSchemaProducer) cloneWithSelf(newSelf PhysicalCauset) (*physicalSchemaProducer, error) { 134 base, err := s.basePhysicalCauset.cloneWithSelf(newSelf) 135 if err != nil { 136 return nil, err 137 } 138 return &physicalSchemaProducer{ 139 basePhysicalCauset: *base, 140 schemaReplicant: s.schemaReplicant.Clone(), 141 }, nil 142 } 143 144 // Schema implements the Causet.Schema interface. 145 func (s *physicalSchemaProducer) Schema() *memex.Schema { 146 if s.schemaReplicant == nil { 147 s.schemaReplicant = memex.NewSchema() 148 } 149 return s.schemaReplicant 150 } 151 152 // SetSchema implements the Causet.SetSchema interface. 153 func (s *physicalSchemaProducer) SetSchema(schemaReplicant *memex.Schema) { 154 s.schemaReplicant = schemaReplicant 155 } 156 157 // baseSchemaProducer stores the schemaReplicant for the base plans who can produce schemaReplicant directly. 158 type baseSchemaProducer struct { 159 schemaReplicant *memex.Schema 160 names types.NameSlice 161 baseCauset 162 } 163 164 // OutputNames returns the outputting names of each column. 165 func (s *baseSchemaProducer) OutputNames() types.NameSlice { 166 return s.names 167 } 168 169 func (s *baseSchemaProducer) SetOutputNames(names types.NameSlice) { 170 s.names = names 171 } 172 173 // Schema implements the Causet.Schema interface. 174 func (s *baseSchemaProducer) Schema() *memex.Schema { 175 if s.schemaReplicant == nil { 176 s.schemaReplicant = memex.NewSchema() 177 } 178 return s.schemaReplicant 179 } 180 181 // SetSchema implements the Causet.SetSchema interface. 182 func (s *baseSchemaProducer) SetSchema(schemaReplicant *memex.Schema) { 183 s.schemaReplicant = schemaReplicant 184 } 185 186 func (s *baseSchemaProducer) setSchemaAndNames(schemaReplicant *memex.Schema, names types.NameSlice) { 187 s.schemaReplicant = schemaReplicant 188 s.names = names 189 } 190 191 // Schema implements the Causet.Schema interface. 192 func (p *LogicalMaxOneRow) Schema() *memex.Schema { 193 s := p.Children()[0].Schema().Clone() 194 resetNotNullFlag(s, 0, s.Len()) 195 return s 196 } 197 198 func buildLogicalJoinSchema(joinType JoinType, join LogicalCauset) *memex.Schema { 199 leftSchema := join.Children()[0].Schema() 200 switch joinType { 201 case SemiJoin, AntiSemiJoin: 202 return leftSchema.Clone() 203 case LeftOuterSemiJoin, AntiLeftOuterSemiJoin: 204 newSchema := leftSchema.Clone() 205 newSchema.Append(join.Schema().DeferredCausets[join.Schema().Len()-1]) 206 return newSchema 207 } 208 newSchema := memex.MergeSchema(leftSchema, join.Children()[1].Schema()) 209 if joinType == LeftOuterJoin { 210 resetNotNullFlag(newSchema, leftSchema.Len(), newSchema.Len()) 211 } else if joinType == RightOuterJoin { 212 resetNotNullFlag(newSchema, 0, leftSchema.Len()) 213 } 214 return newSchema 215 } 216 217 // BuildPhysicalJoinSchema builds the schemaReplicant of PhysicalJoin from it's children's schemaReplicant. 218 func BuildPhysicalJoinSchema(joinType JoinType, join PhysicalCauset) *memex.Schema { 219 switch joinType { 220 case SemiJoin, AntiSemiJoin: 221 return join.Children()[0].Schema().Clone() 222 case LeftOuterSemiJoin, AntiLeftOuterSemiJoin: 223 newSchema := join.Children()[0].Schema().Clone() 224 newSchema.Append(join.Schema().DeferredCausets[join.Schema().Len()-1]) 225 return newSchema 226 } 227 return memex.MergeSchema(join.Children()[0].Schema(), join.Children()[1].Schema()) 228 } 229 230 // GetStatsInfo gets the statistics info from a physical plan tree. 231 func GetStatsInfo(i interface{}) map[string]uint64 { 232 if i == nil { 233 // it's a workaround for https://github.com/whtcorpsinc/milevadb/issues/17419 234 // To entirely fix this, uncomment the assertion in TestPreparedIssue17419 235 return nil 236 } 237 p := i.(Causet) 238 var physicalCauset PhysicalCauset 239 switch x := p.(type) { 240 case *Insert: 241 physicalCauset = x.SelectCauset 242 case *UFIDelate: 243 physicalCauset = x.SelectCauset 244 case *Delete: 245 physicalCauset = x.SelectCauset 246 case PhysicalCauset: 247 physicalCauset = x 248 } 249 250 if physicalCauset == nil { 251 return nil 252 } 253 254 statsInfos := make(map[string]uint64) 255 statsInfos = DefCauslectCausetStatsVersion(physicalCauset, statsInfos) 256 return statsInfos 257 } 258 259 // extractStringFromStringSet helps extract string info from set.StringSet 260 func extractStringFromStringSet(set set.StringSet) string { 261 if len(set) < 1 { 262 return "" 263 } 264 l := make([]string, 0, len(set)) 265 for k := range set { 266 l = append(l, fmt.Sprintf(`"%s"`, k)) 267 } 268 sort.Strings(l) 269 return fmt.Sprintf("%s", strings.Join(l, ",")) 270 } 271 272 func blockHasDirtyContent(ctx stochastikctx.Context, blockInfo *perceptron.BlockInfo) bool { 273 pi := blockInfo.GetPartitionInfo() 274 if pi == nil { 275 return ctx.HasDirtyContent(blockInfo.ID) 276 } 277 // Currently, we add UnionScan on every partition even though only one partition's data is changed. 278 // This is limited by current implementation of Partition Prune. It'll be uFIDelated once we modify that part. 279 for _, partition := range pi.Definitions { 280 if ctx.HasDirtyContent(partition.ID) { 281 return true 282 } 283 } 284 return false 285 } 286 287 func cloneExprs(exprs []memex.Expression) []memex.Expression { 288 cloned := make([]memex.Expression, 0, len(exprs)) 289 for _, e := range exprs { 290 cloned = append(cloned, e.Clone()) 291 } 292 return cloned 293 } 294 295 func cloneDefCauss(defcaus []*memex.DeferredCauset) []*memex.DeferredCauset { 296 cloned := make([]*memex.DeferredCauset, 0, len(defcaus)) 297 for _, c := range defcaus { 298 cloned = append(cloned, c.Clone().(*memex.DeferredCauset)) 299 } 300 return cloned 301 } 302 303 func cloneDefCausInfos(defcaus []*perceptron.DeferredCausetInfo) []*perceptron.DeferredCausetInfo { 304 cloned := make([]*perceptron.DeferredCausetInfo, 0, len(defcaus)) 305 for _, c := range defcaus { 306 cloned = append(cloned, c.Clone()) 307 } 308 return cloned 309 } 310 311 func cloneRanges(ranges []*ranger.Range) []*ranger.Range { 312 cloned := make([]*ranger.Range, 0, len(ranges)) 313 for _, r := range ranges { 314 cloned = append(cloned, r.Clone()) 315 } 316 return cloned 317 } 318 319 func clonePhysicalCauset(plans []PhysicalCauset) ([]PhysicalCauset, error) { 320 cloned := make([]PhysicalCauset, 0, len(plans)) 321 for _, p := range plans { 322 c, err := p.Clone() 323 if err != nil { 324 return nil, err 325 } 326 cloned = append(cloned, c) 327 } 328 return cloned, nil 329 }