github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/petri/acyclic/causet/embedded/implementation_rules.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 "math" 18 19 causetembedded "github.com/whtcorpsinc/milevadb/causet/embedded" 20 impl "github.com/whtcorpsinc/milevadb/causet/implementation" 21 "github.com/whtcorpsinc/milevadb/causet/memo" 22 "github.com/whtcorpsinc/milevadb/causet/property" 23 "github.com/whtcorpsinc/milevadb/memex" 24 ) 25 26 // ImplementationMemrule defines the interface for implementation rules. 27 type ImplementationMemrule interface { 28 // Match checks if current GroupExpr matches this rule under required physical property. 29 Match(expr *memo.GroupExpr, prop *property.PhysicalProperty) (matched bool) 30 // OnImplement generates physical plan using this rule for current GroupExpr. Note that 31 // childrenReqProps of generated physical plan should be set correspondingly in this function. 32 OnImplement(expr *memo.GroupExpr, reqProp *property.PhysicalProperty) ([]memo.Implementation, error) 33 } 34 35 var defaultImplementationMap = map[memo.Operand][]ImplementationMemrule{ 36 memo.OperandBlockDual: { 37 &ImplBlockDual{}, 38 }, 39 memo.OperandMemBlockScan: { 40 &ImplMemBlockScan{}, 41 }, 42 memo.OperandProjection: { 43 &ImplProjection{}, 44 }, 45 memo.OperandBlockScan: { 46 &ImplBlockScan{}, 47 }, 48 memo.OperandIndexScan: { 49 &ImplIndexScan{}, 50 }, 51 memo.OperandEinsteinDBSingleGather: { 52 &ImplEinsteinDBSingleReadGather{}, 53 }, 54 memo.OperandShow: { 55 &ImplShow{}, 56 }, 57 memo.OperandSelection: { 58 &ImplSelection{}, 59 }, 60 memo.OperandSort: { 61 &ImplSort{}, 62 }, 63 memo.OperanPosetDaggregation: { 64 &ImplHashAgg{}, 65 }, 66 memo.OperandLimit: { 67 &ImplLimit{}, 68 }, 69 memo.OperandTopN: { 70 &ImplTopN{}, 71 &ImplTopNAsLimit{}, 72 }, 73 memo.OperandJoin: { 74 &ImplHashJoinBuildLeft{}, 75 &ImplHashJoinBuildRight{}, 76 &ImplMergeJoin{}, 77 }, 78 memo.OperandUnionAll: { 79 &ImplUnionAll{}, 80 }, 81 memo.OperandApply: { 82 &ImplApply{}, 83 }, 84 memo.OperandMaxOneRow: { 85 &ImplMaxOneRow{}, 86 }, 87 memo.OperandWindow: { 88 &ImplWindow{}, 89 }, 90 } 91 92 // ImplBlockDual implements LogicalBlockDual as PhysicalBlockDual. 93 type ImplBlockDual struct { 94 } 95 96 // Match implements ImplementationMemrule Match interface. 97 func (r *ImplBlockDual) Match(expr *memo.GroupExpr, prop *property.PhysicalProperty) (matched bool) { 98 if !prop.IsEmpty() { 99 return false 100 } 101 return true 102 } 103 104 // OnImplement implements ImplementationMemrule OnImplement interface. 105 func (r *ImplBlockDual) OnImplement(expr *memo.GroupExpr, reqProp *property.PhysicalProperty) ([]memo.Implementation, error) { 106 logicProp := expr.Group.Prop 107 logicDual := expr.ExprNode.(*causetembedded.LogicalBlockDual) 108 dual := causetembedded.PhysicalBlockDual{RowCount: logicDual.RowCount}.Init(logicDual.SCtx(), logicProp.Stats, logicDual.SelectBlockOffset()) 109 dual.SetSchema(logicProp.Schema) 110 return []memo.Implementation{impl.NewBlockDualImpl(dual)}, nil 111 } 112 113 // ImplMemBlockScan implements LogicalMemBlock as PhysicalMemBlock. 114 type ImplMemBlockScan struct { 115 } 116 117 // Match implements ImplementationMemrule Match interface. 118 func (r *ImplMemBlockScan) Match(expr *memo.GroupExpr, prop *property.PhysicalProperty) (matched bool) { 119 if !prop.IsEmpty() { 120 return false 121 } 122 return true 123 } 124 125 // OnImplement implements ImplementationMemrule OnImplement interface. 126 func (r *ImplMemBlockScan) OnImplement( 127 expr *memo.GroupExpr, 128 reqProp *property.PhysicalProperty, 129 ) ([]memo.Implementation, error) { 130 logic := expr.ExprNode.(*causetembedded.LogicalMemBlock) 131 logicProp := expr.Group.Prop 132 physical := causetembedded.PhysicalMemBlock{ 133 DBName: logic.DBName, 134 Block: logic.BlockInfo, 135 DeferredCausets: logic.BlockInfo.DeferredCausets, 136 Extractor: logic.Extractor, 137 }.Init(logic.SCtx(), logicProp.Stats.ScaleByExpectCnt(reqProp.ExpectedCnt), logic.SelectBlockOffset()) 138 physical.SetSchema(logicProp.Schema) 139 return []memo.Implementation{impl.NewMemBlockScanImpl(physical)}, nil 140 } 141 142 // ImplProjection implements LogicalProjection as PhysicalProjection. 143 type ImplProjection struct { 144 } 145 146 // Match implements ImplementationMemrule Match interface. 147 func (r *ImplProjection) Match(expr *memo.GroupExpr, prop *property.PhysicalProperty) (matched bool) { 148 return true 149 } 150 151 // OnImplement implements ImplementationMemrule OnImplement interface. 152 func (r *ImplProjection) OnImplement(expr *memo.GroupExpr, reqProp *property.PhysicalProperty) ([]memo.Implementation, error) { 153 logicProp := expr.Group.Prop 154 logicProj := expr.ExprNode.(*causetembedded.LogicalProjection) 155 childProp, ok := logicProj.TryToGetChildProp(reqProp) 156 if !ok { 157 return nil, nil 158 } 159 proj := causetembedded.PhysicalProjection{ 160 Exprs: logicProj.Exprs, 161 CalculateNoDelay: logicProj.CalculateNoDelay, 162 AvoidDeferredCausetEvaluator: logicProj.AvoidDeferredCausetEvaluator, 163 }.Init(logicProj.SCtx(), logicProp.Stats.ScaleByExpectCnt(reqProp.ExpectedCnt), logicProj.SelectBlockOffset(), childProp) 164 proj.SetSchema(logicProp.Schema) 165 return []memo.Implementation{impl.NewProjectionImpl(proj)}, nil 166 } 167 168 // ImplEinsteinDBSingleReadGather implements EinsteinDBSingleGather 169 // as PhysicalBlockReader or PhysicalIndexReader. 170 type ImplEinsteinDBSingleReadGather struct { 171 } 172 173 // Match implements ImplementationMemrule Match interface. 174 func (r *ImplEinsteinDBSingleReadGather) Match(expr *memo.GroupExpr, prop *property.PhysicalProperty) (matched bool) { 175 return true 176 } 177 178 // OnImplement implements ImplementationMemrule OnImplement interface. 179 func (r *ImplEinsteinDBSingleReadGather) OnImplement(expr *memo.GroupExpr, reqProp *property.PhysicalProperty) ([]memo.Implementation, error) { 180 logicProp := expr.Group.Prop 181 sg := expr.ExprNode.(*causetembedded.EinsteinDBSingleGather) 182 if sg.IsIndexGather { 183 reader := sg.GetPhysicalIndexReader(logicProp.Schema, logicProp.Stats.ScaleByExpectCnt(reqProp.ExpectedCnt), reqProp) 184 return []memo.Implementation{impl.NewIndexReaderImpl(reader, sg.Source.TblDefCausHists)}, nil 185 } 186 reader := sg.GetPhysicalBlockReader(logicProp.Schema, logicProp.Stats.ScaleByExpectCnt(reqProp.ExpectedCnt), reqProp) 187 return []memo.Implementation{impl.NewBlockReaderImpl(reader, sg.Source.TblDefCausHists)}, nil 188 } 189 190 // ImplBlockScan implements BlockScan as PhysicalBlockScan. 191 type ImplBlockScan struct { 192 } 193 194 // Match implements ImplementationMemrule Match interface. 195 func (r *ImplBlockScan) Match(expr *memo.GroupExpr, prop *property.PhysicalProperty) (matched bool) { 196 ts := expr.ExprNode.(*causetembedded.LogicalBlockScan) 197 return prop.IsEmpty() || (len(prop.Items) == 1 && ts.HandleDefCauss != nil && prop.Items[0].DefCaus.Equal(nil, ts.HandleDefCauss.GetDefCaus(0))) 198 } 199 200 // OnImplement implements ImplementationMemrule OnImplement interface. 201 func (r *ImplBlockScan) OnImplement(expr *memo.GroupExpr, reqProp *property.PhysicalProperty) ([]memo.Implementation, error) { 202 logicProp := expr.Group.Prop 203 logicalScan := expr.ExprNode.(*causetembedded.LogicalBlockScan) 204 ts := logicalScan.GetPhysicalScan(logicProp.Schema, logicProp.Stats.ScaleByExpectCnt(reqProp.ExpectedCnt)) 205 if !reqProp.IsEmpty() { 206 ts.KeepOrder = true 207 ts.Desc = reqProp.Items[0].Desc 208 } 209 tblDefCauss, tblDefCausHists := logicalScan.Source.TblDefCauss, logicalScan.Source.TblDefCausHists 210 return []memo.Implementation{impl.NewBlockScanImpl(ts, tblDefCauss, tblDefCausHists)}, nil 211 } 212 213 // ImplIndexScan implements IndexScan as PhysicalIndexScan. 214 type ImplIndexScan struct { 215 } 216 217 // Match implements ImplementationMemrule Match interface. 218 func (r *ImplIndexScan) Match(expr *memo.GroupExpr, prop *property.PhysicalProperty) (matched bool) { 219 is := expr.ExprNode.(*causetembedded.LogicalIndexScan) 220 return is.MatchIndexProp(prop) 221 } 222 223 // OnImplement implements ImplementationMemrule OnImplement interface. 224 func (r *ImplIndexScan) OnImplement(expr *memo.GroupExpr, reqProp *property.PhysicalProperty) ([]memo.Implementation, error) { 225 logicalScan := expr.ExprNode.(*causetembedded.LogicalIndexScan) 226 is := logicalScan.GetPhysicalIndexScan(expr.Group.Prop.Schema, expr.Group.Prop.Stats.ScaleByExpectCnt(reqProp.ExpectedCnt)) 227 if !reqProp.IsEmpty() { 228 is.KeepOrder = true 229 if reqProp.Items[0].Desc { 230 is.Desc = true 231 } 232 } 233 return []memo.Implementation{impl.NewIndexScanImpl(is, logicalScan.Source.TblDefCausHists)}, nil 234 } 235 236 // ImplShow is the implementation rule which implements LogicalShow to 237 // PhysicalShow. 238 type ImplShow struct { 239 } 240 241 // Match implements ImplementationMemrule Match interface. 242 func (r *ImplShow) Match(expr *memo.GroupExpr, prop *property.PhysicalProperty) (matched bool) { 243 return prop.IsEmpty() 244 } 245 246 // OnImplement implements ImplementationMemrule OnImplement interface. 247 func (r *ImplShow) OnImplement(expr *memo.GroupExpr, reqProp *property.PhysicalProperty) ([]memo.Implementation, error) { 248 logicProp := expr.Group.Prop 249 show := expr.ExprNode.(*causetembedded.LogicalShow) 250 251 // TODO(zz-jason): unifying LogicalShow and PhysicalShow to a single 252 // struct. So that we don't need to create a new PhysicalShow object, which 253 // can help us to reduce the gc pressure of golang runtime and improve the 254 // overall performance. 255 showPhys := causetembedded.PhysicalShow{ShowContents: show.ShowContents}.Init(show.SCtx()) 256 showPhys.SetSchema(logicProp.Schema) 257 return []memo.Implementation{impl.NewShowImpl(showPhys)}, nil 258 } 259 260 // ImplSelection is the implementation rule which implements LogicalSelection 261 // to PhysicalSelection. 262 type ImplSelection struct { 263 } 264 265 // Match implements ImplementationMemrule Match interface. 266 func (r *ImplSelection) Match(expr *memo.GroupExpr, prop *property.PhysicalProperty) (matched bool) { 267 return true 268 } 269 270 // OnImplement implements ImplementationMemrule OnImplement interface. 271 func (r *ImplSelection) OnImplement(expr *memo.GroupExpr, reqProp *property.PhysicalProperty) ([]memo.Implementation, error) { 272 logicalSel := expr.ExprNode.(*causetembedded.LogicalSelection) 273 physicalSel := causetembedded.PhysicalSelection{ 274 Conditions: logicalSel.Conditions, 275 }.Init(logicalSel.SCtx(), expr.Group.Prop.Stats.ScaleByExpectCnt(reqProp.ExpectedCnt), logicalSel.SelectBlockOffset(), reqProp.Clone()) 276 switch expr.Group.EngineType { 277 case memo.EngineMilevaDB: 278 return []memo.Implementation{impl.NewMilevaDBSelectionImpl(physicalSel)}, nil 279 case memo.EngineEinsteinDB: 280 return []memo.Implementation{impl.NewEinsteinDBSelectionImpl(physicalSel)}, nil 281 default: 282 return nil, causetembedded.ErrInternal.GenWithStack("Unsupported EngineType '%s' for Selection.", expr.Group.EngineType.String()) 283 } 284 } 285 286 // ImplSort is the implementation rule which implements LogicalSort 287 // to PhysicalSort or NominalSort. 288 type ImplSort struct { 289 } 290 291 // Match implements ImplementationMemrule match interface. 292 func (r *ImplSort) Match(expr *memo.GroupExpr, prop *property.PhysicalProperty) (matched bool) { 293 ls := expr.ExprNode.(*causetembedded.LogicalSort) 294 return causetembedded.MatchItems(prop, ls.ByItems) 295 } 296 297 // OnImplement implements ImplementationMemrule OnImplement interface. 298 // If all of the sort items are defCausumns, generate a NominalSort, otherwise 299 // generate a PhysicalSort. 300 func (r *ImplSort) OnImplement(expr *memo.GroupExpr, reqProp *property.PhysicalProperty) ([]memo.Implementation, error) { 301 ls := expr.ExprNode.(*causetembedded.LogicalSort) 302 if newProp, canUseNominal := causetembedded.GetPropByOrderByItems(ls.ByItems); canUseNominal { 303 newProp.ExpectedCnt = reqProp.ExpectedCnt 304 ns := causetembedded.NominalSort{}.Init( 305 ls.SCtx(), expr.Group.Prop.Stats.ScaleByExpectCnt(reqProp.ExpectedCnt), ls.SelectBlockOffset(), newProp) 306 return []memo.Implementation{impl.NewNominalSortImpl(ns)}, nil 307 } 308 ps := causetembedded.PhysicalSort{ByItems: ls.ByItems}.Init( 309 ls.SCtx(), 310 expr.Group.Prop.Stats.ScaleByExpectCnt(reqProp.ExpectedCnt), 311 ls.SelectBlockOffset(), 312 &property.PhysicalProperty{ExpectedCnt: math.MaxFloat64}, 313 ) 314 return []memo.Implementation{impl.NewSortImpl(ps)}, nil 315 } 316 317 // ImplHashAgg is the implementation rule which implements LogicalAggregation 318 // to PhysicalHashAgg. 319 type ImplHashAgg struct { 320 } 321 322 // Match implements ImplementationMemrule Match interface. 323 func (r *ImplHashAgg) Match(expr *memo.GroupExpr, prop *property.PhysicalProperty) (matched bool) { 324 // TODO: deal with the hints when we have implemented StreamAgg. 325 return prop.IsEmpty() 326 } 327 328 // OnImplement implements ImplementationMemrule OnImplement interface. 329 func (r *ImplHashAgg) OnImplement(expr *memo.GroupExpr, reqProp *property.PhysicalProperty) ([]memo.Implementation, error) { 330 la := expr.ExprNode.(*causetembedded.LogicalAggregation) 331 hashAgg := causetembedded.NewPhysicalHashAgg( 332 la, 333 expr.Group.Prop.Stats.ScaleByExpectCnt(reqProp.ExpectedCnt), 334 &property.PhysicalProperty{ExpectedCnt: math.MaxFloat64}, 335 ) 336 hashAgg.SetSchema(expr.Group.Prop.Schema.Clone()) 337 switch expr.Group.EngineType { 338 case memo.EngineMilevaDB: 339 return []memo.Implementation{impl.NewMilevaDBHashAggImpl(hashAgg)}, nil 340 case memo.EngineEinsteinDB: 341 return []memo.Implementation{impl.NewEinsteinDBHashAggImpl(hashAgg)}, nil 342 default: 343 return nil, causetembedded.ErrInternal.GenWithStack("Unsupported EngineType '%s' for HashAggregation.", expr.Group.EngineType.String()) 344 } 345 } 346 347 // ImplLimit is the implementation rule which implements LogicalLimit 348 // to PhysicalLimit. 349 type ImplLimit struct { 350 } 351 352 // Match implements ImplementationMemrule Match interface. 353 func (r *ImplLimit) Match(expr *memo.GroupExpr, prop *property.PhysicalProperty) (matched bool) { 354 return prop.IsEmpty() 355 } 356 357 // OnImplement implements ImplementationMemrule OnImplement interface. 358 func (r *ImplLimit) OnImplement(expr *memo.GroupExpr, reqProp *property.PhysicalProperty) ([]memo.Implementation, error) { 359 logicalLimit := expr.ExprNode.(*causetembedded.LogicalLimit) 360 newProp := &property.PhysicalProperty{ExpectedCnt: float64(logicalLimit.Count + logicalLimit.Offset)} 361 physicalLimit := causetembedded.PhysicalLimit{ 362 Offset: logicalLimit.Offset, 363 Count: logicalLimit.Count, 364 }.Init(logicalLimit.SCtx(), expr.Group.Prop.Stats, logicalLimit.SelectBlockOffset(), newProp) 365 return []memo.Implementation{impl.NewLimitImpl(physicalLimit)}, nil 366 } 367 368 // ImplTopN is the implementation rule which implements LogicalTopN 369 // to PhysicalTopN. 370 type ImplTopN struct { 371 } 372 373 // Match implements ImplementationMemrule Match interface. 374 func (r *ImplTopN) Match(expr *memo.GroupExpr, prop *property.PhysicalProperty) (matched bool) { 375 topN := expr.ExprNode.(*causetembedded.LogicalTopN) 376 if expr.Group.EngineType != memo.EngineMilevaDB { 377 return prop.IsEmpty() 378 } 379 return causetembedded.MatchItems(prop, topN.ByItems) 380 } 381 382 // OnImplement implements ImplementationMemrule OnImplement interface. 383 func (r *ImplTopN) OnImplement(expr *memo.GroupExpr, reqProp *property.PhysicalProperty) ([]memo.Implementation, error) { 384 lt := expr.ExprNode.(*causetembedded.LogicalTopN) 385 resultProp := &property.PhysicalProperty{ExpectedCnt: math.MaxFloat64} 386 topN := causetembedded.PhysicalTopN{ 387 ByItems: lt.ByItems, 388 Count: lt.Count, 389 Offset: lt.Offset, 390 }.Init(lt.SCtx(), expr.Group.Prop.Stats, lt.SelectBlockOffset(), resultProp) 391 switch expr.Group.EngineType { 392 case memo.EngineMilevaDB: 393 return []memo.Implementation{impl.NewMilevaDBTopNImpl(topN)}, nil 394 case memo.EngineEinsteinDB: 395 return []memo.Implementation{impl.NewEinsteinDBTopNImpl(topN)}, nil 396 default: 397 return nil, causetembedded.ErrInternal.GenWithStack("Unsupported EngineType '%s' for TopN.", expr.Group.EngineType.String()) 398 } 399 } 400 401 // ImplTopNAsLimit is the implementation rule which implements LogicalTopN 402 // as PhysicalLimit with required order property. 403 type ImplTopNAsLimit struct { 404 } 405 406 // Match implements ImplementationMemrule Match interface. 407 func (r *ImplTopNAsLimit) Match(expr *memo.GroupExpr, prop *property.PhysicalProperty) (matched bool) { 408 topN := expr.ExprNode.(*causetembedded.LogicalTopN) 409 _, canUseLimit := causetembedded.GetPropByOrderByItems(topN.ByItems) 410 return canUseLimit && causetembedded.MatchItems(prop, topN.ByItems) 411 } 412 413 // OnImplement implements ImplementationMemrule OnImplement interface. 414 func (r *ImplTopNAsLimit) OnImplement(expr *memo.GroupExpr, reqProp *property.PhysicalProperty) ([]memo.Implementation, error) { 415 lt := expr.ExprNode.(*causetembedded.LogicalTopN) 416 newProp := &property.PhysicalProperty{ExpectedCnt: float64(lt.Count + lt.Offset)} 417 newProp.Items = make([]property.Item, len(lt.ByItems)) 418 for i, item := range lt.ByItems { 419 newProp.Items[i].DefCaus = item.Expr.(*memex.DeferredCauset) 420 newProp.Items[i].Desc = item.Desc 421 } 422 physicalLimit := causetembedded.PhysicalLimit{ 423 Offset: lt.Offset, 424 Count: lt.Count, 425 }.Init(lt.SCtx(), expr.Group.Prop.Stats, lt.SelectBlockOffset(), newProp) 426 return []memo.Implementation{impl.NewLimitImpl(physicalLimit)}, nil 427 } 428 429 func getImplForHashJoin(expr *memo.GroupExpr, prop *property.PhysicalProperty, innerIdx int, useOuterToBuild bool) memo.Implementation { 430 join := expr.ExprNode.(*causetembedded.LogicalJoin) 431 chReqProps := make([]*property.PhysicalProperty, 2) 432 chReqProps[0] = &property.PhysicalProperty{ExpectedCnt: math.MaxFloat64} 433 chReqProps[1] = &property.PhysicalProperty{ExpectedCnt: math.MaxFloat64} 434 stats := expr.Group.Prop.Stats 435 if prop.ExpectedCnt < stats.RowCount { 436 expCntScale := prop.ExpectedCnt / stats.RowCount 437 chReqProps[1-innerIdx].ExpectedCnt = expr.Children[1-innerIdx].Prop.Stats.RowCount * expCntScale 438 } 439 hashJoin := causetembedded.NewPhysicalHashJoin(join, innerIdx, useOuterToBuild, stats.ScaleByExpectCnt(prop.ExpectedCnt), chReqProps...) 440 hashJoin.SetSchema(expr.Group.Prop.Schema) 441 return impl.NewHashJoinImpl(hashJoin) 442 } 443 444 // ImplHashJoinBuildLeft implements LogicalJoin to PhysicalHashJoin which uses the left child to build hash causet. 445 type ImplHashJoinBuildLeft struct { 446 } 447 448 // Match implements ImplementationMemrule Match interface. 449 func (r *ImplHashJoinBuildLeft) Match(expr *memo.GroupExpr, prop *property.PhysicalProperty) (matched bool) { 450 switch expr.ExprNode.(*causetembedded.LogicalJoin).JoinType { 451 case causetembedded.InnerJoin, causetembedded.LeftOuterJoin, causetembedded.RightOuterJoin: 452 return prop.IsEmpty() 453 default: 454 return false 455 } 456 } 457 458 // OnImplement implements ImplementationMemrule OnImplement interface. 459 func (r *ImplHashJoinBuildLeft) OnImplement(expr *memo.GroupExpr, reqProp *property.PhysicalProperty) ([]memo.Implementation, error) { 460 join := expr.ExprNode.(*causetembedded.LogicalJoin) 461 switch join.JoinType { 462 case causetembedded.InnerJoin: 463 return []memo.Implementation{getImplForHashJoin(expr, reqProp, 0, false)}, nil 464 case causetembedded.LeftOuterJoin: 465 return []memo.Implementation{getImplForHashJoin(expr, reqProp, 1, true)}, nil 466 case causetembedded.RightOuterJoin: 467 return []memo.Implementation{getImplForHashJoin(expr, reqProp, 0, false)}, nil 468 default: 469 return nil, nil 470 } 471 } 472 473 // ImplHashJoinBuildRight implements LogicalJoin to PhysicalHashJoin which uses the right child to build hash causet. 474 type ImplHashJoinBuildRight struct { 475 } 476 477 // Match implements ImplementationMemrule Match interface. 478 func (r *ImplHashJoinBuildRight) Match(expr *memo.GroupExpr, prop *property.PhysicalProperty) (matched bool) { 479 return prop.IsEmpty() 480 } 481 482 // OnImplement implements ImplementationMemrule OnImplement interface. 483 func (r *ImplHashJoinBuildRight) OnImplement(expr *memo.GroupExpr, reqProp *property.PhysicalProperty) ([]memo.Implementation, error) { 484 join := expr.ExprNode.(*causetembedded.LogicalJoin) 485 switch join.JoinType { 486 case causetembedded.SemiJoin, causetembedded.AntiSemiJoin, 487 causetembedded.LeftOuterSemiJoin, causetembedded.AntiLeftOuterSemiJoin: 488 return []memo.Implementation{getImplForHashJoin(expr, reqProp, 1, false)}, nil 489 case causetembedded.InnerJoin: 490 return []memo.Implementation{getImplForHashJoin(expr, reqProp, 1, false)}, nil 491 case causetembedded.LeftOuterJoin: 492 return []memo.Implementation{getImplForHashJoin(expr, reqProp, 1, false)}, nil 493 case causetembedded.RightOuterJoin: 494 return []memo.Implementation{getImplForHashJoin(expr, reqProp, 0, true)}, nil 495 } 496 return nil, nil 497 } 498 499 // ImplMergeJoin implements LogicalMergeJoin to PhysicalMergeJoin. 500 type ImplMergeJoin struct { 501 } 502 503 // Match implements ImplementationMemrule Match interface. 504 func (r *ImplMergeJoin) Match(expr *memo.GroupExpr, prop *property.PhysicalProperty) (matched bool) { 505 return true 506 } 507 508 // OnImplement implements ImplementationMemrule OnImplement interface. 509 func (r *ImplMergeJoin) OnImplement(expr *memo.GroupExpr, reqProp *property.PhysicalProperty) ([]memo.Implementation, error) { 510 join := expr.ExprNode.(*causetembedded.LogicalJoin) 511 physicalMergeJoins := join.GetMergeJoin(reqProp, expr.Schema(), expr.Group.Prop.Stats, expr.Children[0].Prop.Stats, expr.Children[1].Prop.Stats) 512 mergeJoinImpls := make([]memo.Implementation, 0, len(physicalMergeJoins)) 513 for _, physicalCauset := range physicalMergeJoins { 514 physicalMergeJoin := physicalCauset.(*causetembedded.PhysicalMergeJoin) 515 mergeJoinImpls = append(mergeJoinImpls, impl.NewMergeJoinImpl(physicalMergeJoin)) 516 } 517 return mergeJoinImpls, nil 518 } 519 520 // ImplUnionAll implements LogicalUnionAll to PhysicalUnionAll. 521 type ImplUnionAll struct { 522 } 523 524 // Match implements ImplementationMemrule Match interface. 525 func (r *ImplUnionAll) Match(expr *memo.GroupExpr, prop *property.PhysicalProperty) (matched bool) { 526 return prop.IsEmpty() 527 } 528 529 // OnImplement implements ImplementationMemrule OnImplement interface. 530 func (r *ImplUnionAll) OnImplement(expr *memo.GroupExpr, reqProp *property.PhysicalProperty) ([]memo.Implementation, error) { 531 logicalUnion := expr.ExprNode.(*causetembedded.LogicalUnionAll) 532 chReqProps := make([]*property.PhysicalProperty, len(expr.Children)) 533 for i := range expr.Children { 534 chReqProps[i] = &property.PhysicalProperty{ExpectedCnt: reqProp.ExpectedCnt} 535 } 536 physicalUnion := causetembedded.PhysicalUnionAll{}.Init( 537 logicalUnion.SCtx(), 538 expr.Group.Prop.Stats.ScaleByExpectCnt(reqProp.ExpectedCnt), 539 logicalUnion.SelectBlockOffset(), 540 chReqProps..., 541 ) 542 physicalUnion.SetSchema(expr.Group.Prop.Schema) 543 return []memo.Implementation{impl.NewUnionAllImpl(physicalUnion)}, nil 544 } 545 546 // ImplApply implements LogicalApply to PhysicalApply 547 type ImplApply struct { 548 } 549 550 // Match implements ImplementationMemrule Match interface. 551 func (r *ImplApply) Match(expr *memo.GroupExpr, prop *property.PhysicalProperty) (matched bool) { 552 return prop.AllDefCaussFromSchema(expr.Children[0].Prop.Schema) 553 } 554 555 // OnImplement implements ImplementationMemrule OnImplement interface 556 func (r *ImplApply) OnImplement(expr *memo.GroupExpr, reqProp *property.PhysicalProperty) ([]memo.Implementation, error) { 557 la := expr.ExprNode.(*causetembedded.LogicalApply) 558 join := la.GetHashJoin(reqProp) 559 physicalApply := causetembedded.PhysicalApply{ 560 PhysicalHashJoin: *join, 561 OuterSchema: la.CorDefCauss, 562 }.Init( 563 la.SCtx(), 564 expr.Group.Prop.Stats.ScaleByExpectCnt(reqProp.ExpectedCnt), 565 la.SelectBlockOffset(), 566 &property.PhysicalProperty{ExpectedCnt: math.MaxFloat64, Items: reqProp.Items}, 567 &property.PhysicalProperty{ExpectedCnt: math.MaxFloat64}) 568 physicalApply.SetSchema(expr.Group.Prop.Schema) 569 return []memo.Implementation{impl.NewApplyImpl(physicalApply)}, nil 570 } 571 572 // ImplMaxOneRow implements LogicalMaxOneRow to PhysicalMaxOneRow. 573 type ImplMaxOneRow struct { 574 } 575 576 // Match implements ImplementationMemrule Match interface. 577 func (r *ImplMaxOneRow) Match(expr *memo.GroupExpr, prop *property.PhysicalProperty) (matched bool) { 578 return prop.IsEmpty() 579 } 580 581 // OnImplement implements ImplementationMemrule OnImplement interface 582 func (r *ImplMaxOneRow) OnImplement(expr *memo.GroupExpr, reqProp *property.PhysicalProperty) ([]memo.Implementation, error) { 583 mor := expr.ExprNode.(*causetembedded.LogicalMaxOneRow) 584 physicalMaxOneRow := causetembedded.PhysicalMaxOneRow{}.Init( 585 mor.SCtx(), 586 expr.Group.Prop.Stats, 587 mor.SelectBlockOffset(), 588 &property.PhysicalProperty{ExpectedCnt: 2}) 589 return []memo.Implementation{impl.NewMaxOneRowImpl(physicalMaxOneRow)}, nil 590 } 591 592 // ImplWindow implements LogicalWindow to PhysicalWindow. 593 type ImplWindow struct { 594 } 595 596 // Match implements ImplementationMemrule Match interface. 597 func (w *ImplWindow) Match(expr *memo.GroupExpr, prop *property.PhysicalProperty) (matched bool) { 598 lw := expr.ExprNode.(*causetembedded.LogicalWindow) 599 var byItems []property.Item 600 byItems = append(byItems, lw.PartitionBy...) 601 byItems = append(byItems, lw.OrderBy...) 602 childProperty := &property.PhysicalProperty{ExpectedCnt: math.MaxFloat64, Items: byItems} 603 return prop.IsPrefix(childProperty) 604 } 605 606 // OnImplement implements ImplementationMemrule OnImplement interface. 607 func (w *ImplWindow) OnImplement(expr *memo.GroupExpr, reqProp *property.PhysicalProperty) ([]memo.Implementation, error) { 608 lw := expr.ExprNode.(*causetembedded.LogicalWindow) 609 var byItems []property.Item 610 byItems = append(byItems, lw.PartitionBy...) 611 byItems = append(byItems, lw.OrderBy...) 612 physicalWindow := causetembedded.PhysicalWindow{ 613 WindowFuncDescs: lw.WindowFuncDescs, 614 PartitionBy: lw.PartitionBy, 615 OrderBy: lw.OrderBy, 616 Frame: lw.Frame, 617 }.Init( 618 lw.SCtx(), 619 expr.Group.Prop.Stats.ScaleByExpectCnt(reqProp.ExpectedCnt), 620 lw.SelectBlockOffset(), 621 &property.PhysicalProperty{ExpectedCnt: math.MaxFloat64, Items: byItems}, 622 ) 623 physicalWindow.SetSchema(expr.Group.Prop.Schema) 624 return []memo.Implementation{impl.NewWindowImpl(physicalWindow)}, nil 625 }