github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/tidb/executor/builder.go (about) 1 // Copyright 2015 PingCAP, 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 executor 15 16 import ( 17 "math" 18 19 "github.com/insionng/yougam/libraries/juju/errors" 20 "github.com/insionng/yougam/libraries/ngaut/log" 21 "github.com/insionng/yougam/libraries/pingcap/tidb/ast" 22 "github.com/insionng/yougam/libraries/pingcap/tidb/column" 23 "github.com/insionng/yougam/libraries/pingcap/tidb/context" 24 "github.com/insionng/yougam/libraries/pingcap/tidb/infoschema" 25 "github.com/insionng/yougam/libraries/pingcap/tidb/kv" 26 "github.com/insionng/yougam/libraries/pingcap/tidb/model" 27 "github.com/insionng/yougam/libraries/pingcap/tidb/optimizer/plan" 28 "github.com/insionng/yougam/libraries/pingcap/tidb/parser/opcode" 29 "github.com/insionng/yougam/libraries/pingcap/tidb/sessionctx/autocommit" 30 "github.com/insionng/yougam/libraries/pingcap/tidb/sessionctx/variable" 31 "github.com/insionng/yougam/libraries/pingcap/tidb/util/types" 32 ) 33 34 // executorBuilder builds an Executor from a Plan. 35 // The InfoSchema must be the same one used in InfoBinder. 36 type executorBuilder struct { 37 ctx context.Context 38 is infoschema.InfoSchema 39 err error 40 } 41 42 func newExecutorBuilder(ctx context.Context, is infoschema.InfoSchema) *executorBuilder { 43 return &executorBuilder{ 44 ctx: ctx, 45 is: is, 46 } 47 } 48 49 func (b *executorBuilder) build(p plan.Plan) Executor { 50 switch v := p.(type) { 51 case nil: 52 return nil 53 case *plan.Aggregate: 54 return b.buildAggregate(v) 55 case *plan.CheckTable: 56 return b.buildCheckTable(v) 57 case *plan.DDL: 58 return b.buildDDL(v) 59 case *plan.Deallocate: 60 return b.buildDeallocate(v) 61 case *plan.Delete: 62 return b.buildDelete(v) 63 case *plan.Distinct: 64 return b.buildDistinct(v) 65 case *plan.Execute: 66 return b.buildExecute(v) 67 case *plan.Explain: 68 return b.buildExplain(v) 69 case *plan.Filter: 70 src := b.build(v.GetChildByIndex(0)) 71 return b.buildFilter(src, v.Conditions) 72 case *plan.Having: 73 return b.buildHaving(v) 74 case *plan.IndexScan: 75 return b.buildIndexScan(v) 76 case *plan.Insert: 77 return b.buildInsert(v) 78 case *plan.JoinInner: 79 return b.buildJoinInner(v) 80 case *plan.JoinOuter: 81 return b.buildJoinOuter(v) 82 case *plan.Limit: 83 return b.buildLimit(v) 84 case *plan.Prepare: 85 return b.buildPrepare(v) 86 case *plan.SelectFields: 87 return b.buildSelectFields(v) 88 case *plan.SelectLock: 89 return b.buildSelectLock(v) 90 case *plan.ShowDDL: 91 return b.buildShowDDL(v) 92 case *plan.Show: 93 return b.buildShow(v) 94 case *plan.Simple: 95 return b.buildSimple(v) 96 case *plan.Sort: 97 return b.buildSort(v) 98 case *plan.TableDual: 99 return b.buildTableDual(v) 100 case *plan.TableScan: 101 return b.buildTableScan(v) 102 case *plan.Union: 103 return b.buildUnion(v) 104 case *plan.Update: 105 return b.buildUpdate(v) 106 case *plan.Join: 107 return b.buildJoin(v) 108 default: 109 b.err = ErrUnknownPlan.Gen("Unknown Plan %T", p) 110 return nil 111 } 112 } 113 114 // compose CNF items into a balance deep CNF tree, which benefits a lot for pb decoder/encoder. 115 func composeCondition(conditions []ast.ExprNode) ast.ExprNode { 116 length := len(conditions) 117 if length == 0 { 118 return nil 119 } else if length == 1 { 120 return conditions[0] 121 } else { 122 return &ast.BinaryOperationExpr{Op: opcode.AndAnd, L: composeCondition(conditions[:length/2]), R: composeCondition(conditions[length/2:])} 123 } 124 } 125 126 //TODO: select join algorithm during cbo phase. 127 func (b *executorBuilder) buildJoin(v *plan.Join) Executor { 128 e := &HashJoinExec{ 129 otherFilter: composeCondition(v.OtherConditions), 130 prepared: false, 131 fields: v.Fields(), 132 ctx: b.ctx, 133 } 134 var leftHashKey, rightHashKey []ast.ExprNode 135 for _, eqCond := range v.EqualConditions { 136 binop, ok := eqCond.(*ast.BinaryOperationExpr) 137 if ok && binop.Op == opcode.EQ { 138 ln, lOK := binop.L.(*ast.ColumnNameExpr) 139 rn, rOK := binop.R.(*ast.ColumnNameExpr) 140 if lOK && rOK { 141 leftHashKey = append(leftHashKey, ln) 142 rightHashKey = append(rightHashKey, rn) 143 continue 144 } 145 } 146 b.err = ErrUnknownPlan.Gen("Invalid Join Equal Condition !!") 147 } 148 switch v.JoinType { 149 case plan.LeftOuterJoin: 150 e.outter = true 151 e.leftSmall = false 152 e.smallFilter = composeCondition(v.RightConditions) 153 e.bigFilter = composeCondition(v.LeftConditions) 154 e.smallHashKey = rightHashKey 155 e.bigHashKey = leftHashKey 156 case plan.RightOuterJoin: 157 e.outter = true 158 e.leftSmall = true 159 e.smallFilter = composeCondition(v.LeftConditions) 160 e.bigFilter = composeCondition(v.RightConditions) 161 e.smallHashKey = leftHashKey 162 e.bigHashKey = rightHashKey 163 case plan.InnerJoin: 164 //TODO: assume right table is the small one before cbo is realized. 165 e.outter = false 166 e.leftSmall = false 167 e.smallFilter = composeCondition(v.RightConditions) 168 e.bigFilter = composeCondition(v.LeftConditions) 169 e.smallHashKey = rightHashKey 170 e.bigHashKey = leftHashKey 171 default: 172 b.err = ErrUnknownPlan.Gen("Unknown Join Type !!") 173 return nil 174 } 175 if e.leftSmall { 176 e.smallExec = b.build(v.GetChildByIndex(0)) 177 e.bigExec = b.build(v.GetChildByIndex(1)) 178 } else { 179 e.smallExec = b.build(v.GetChildByIndex(1)) 180 e.bigExec = b.build(v.GetChildByIndex(0)) 181 } 182 return e 183 } 184 185 func (b *executorBuilder) buildFilter(src Executor, conditions []ast.ExprNode) Executor { 186 if len(conditions) == 0 { 187 return src 188 } 189 return &FilterExec{ 190 Src: src, 191 Condition: b.joinConditions(conditions), 192 ctx: b.ctx, 193 } 194 } 195 196 func (b *executorBuilder) buildTableDual(v *plan.TableDual) Executor { 197 e := &TableDualExec{fields: v.Fields()} 198 return b.buildFilter(e, v.FilterConditions) 199 } 200 201 func (b *executorBuilder) buildTableScan(v *plan.TableScan) Executor { 202 txn, err := b.ctx.GetTxn(false) 203 if err != nil { 204 b.err = err 205 return nil 206 } 207 table, _ := b.is.TableByID(v.Table.ID) 208 client := txn.GetClient() 209 var memDB bool 210 switch v.Fields()[0].DBName.L { 211 case "information_schema", "performance_schema": 212 memDB = true 213 } 214 supportDesc := client.SupportRequestType(kv.ReqTypeSelect, kv.ReqSubTypeDesc) 215 if !memDB && client.SupportRequestType(kv.ReqTypeSelect, 0) && txn.IsReadOnly() { 216 log.Debug("xapi select table") 217 e := &XSelectTableExec{ 218 table: table, 219 ctx: b.ctx, 220 tablePlan: v, 221 supportDesc: supportDesc, 222 } 223 where, remained := b.conditionsToPBExpr(client, v.FilterConditions, v.TableName) 224 if where != nil { 225 e.where = where 226 } 227 if len(remained) == 0 { 228 e.allFiltersPushed = true 229 return e 230 } 231 return b.buildFilter(e, remained) 232 } 233 234 e := &TableScanExec{ 235 t: table, 236 tableAsName: v.TableAsName, 237 fields: v.Fields(), 238 ctx: b.ctx, 239 ranges: v.Ranges, 240 seekHandle: math.MinInt64, 241 } 242 x := b.buildFilter(e, v.FilterConditions) 243 if v.Desc { 244 x = &ReverseExec{Src: x} 245 } 246 return x 247 } 248 249 func (b *executorBuilder) buildShowDDL(v *plan.ShowDDL) Executor { 250 return &ShowDDLExec{ 251 fields: v.Fields(), 252 ctx: b.ctx, 253 } 254 } 255 256 func (b *executorBuilder) buildCheckTable(v *plan.CheckTable) Executor { 257 return &CheckTableExec{ 258 tables: v.Tables, 259 ctx: b.ctx, 260 } 261 } 262 263 func (b *executorBuilder) buildDeallocate(v *plan.Deallocate) Executor { 264 return &DeallocateExec{ 265 ctx: b.ctx, 266 Name: v.Name, 267 } 268 } 269 270 func (b *executorBuilder) buildIndexScan(v *plan.IndexScan) Executor { 271 txn, err := b.ctx.GetTxn(false) 272 if err != nil { 273 b.err = err 274 return nil 275 } 276 tbl, _ := b.is.TableByID(v.Table.ID) 277 client := txn.GetClient() 278 supportDesc := client.SupportRequestType(kv.ReqTypeIndex, kv.ReqSubTypeDesc) 279 var memDB bool 280 switch v.Fields()[0].DBName.L { 281 case "information_schema", "performance_schema": 282 memDB = true 283 } 284 if !memDB && client.SupportRequestType(kv.ReqTypeIndex, 0) && txn.IsReadOnly() { 285 log.Debug("xapi select index") 286 e := &XSelectIndexExec{ 287 table: tbl, 288 ctx: b.ctx, 289 indexPlan: v, 290 supportDesc: supportDesc, 291 } 292 where, remained := b.conditionsToPBExpr(client, v.FilterConditions, v.TableName) 293 if where != nil { 294 e.where = where 295 } 296 return b.buildFilter(e, remained) 297 } 298 299 var idx *column.IndexedCol 300 for _, val := range tbl.Indices() { 301 if val.IndexInfo.Name.L == v.Index.Name.L { 302 idx = val 303 break 304 } 305 } 306 e := &IndexScanExec{ 307 tbl: tbl, 308 tableAsName: v.TableAsName, 309 idx: idx, 310 fields: v.Fields(), 311 ctx: b.ctx, 312 Desc: v.Desc, 313 valueTypes: make([]*types.FieldType, len(idx.Columns)), 314 } 315 316 for i, ic := range idx.Columns { 317 col := tbl.Cols()[ic.Offset] 318 e.valueTypes[i] = &col.FieldType 319 } 320 321 e.Ranges = make([]*IndexRangeExec, len(v.Ranges)) 322 for i, val := range v.Ranges { 323 e.Ranges[i] = b.buildIndexRange(e, val) 324 } 325 x := b.buildFilter(e, v.FilterConditions) 326 if v.Desc { 327 x = &ReverseExec{Src: x} 328 } 329 return x 330 } 331 332 func (b *executorBuilder) buildIndexRange(scan *IndexScanExec, v *plan.IndexRange) *IndexRangeExec { 333 ran := &IndexRangeExec{ 334 scan: scan, 335 lowVals: v.LowVal, 336 lowExclude: v.LowExclude, 337 highVals: v.HighVal, 338 highExclude: v.HighExclude, 339 } 340 return ran 341 } 342 343 func (b *executorBuilder) buildJoinOuter(v *plan.JoinOuter) *JoinOuterExec { 344 e := &JoinOuterExec{ 345 OuterExec: b.build(v.Outer), 346 InnerPlan: v.Inner, 347 fields: v.Fields(), 348 builder: b, 349 } 350 return e 351 } 352 353 func (b *executorBuilder) buildJoinInner(v *plan.JoinInner) *JoinInnerExec { 354 e := &JoinInnerExec{ 355 InnerPlans: v.Inners, 356 innerExecs: make([]Executor, len(v.Inners)), 357 Condition: b.joinConditions(v.Conditions), 358 fields: v.Fields(), 359 ctx: b.ctx, 360 builder: b, 361 } 362 return e 363 } 364 365 func (b *executorBuilder) joinConditions(conditions []ast.ExprNode) ast.ExprNode { 366 if len(conditions) == 0 { 367 return nil 368 } 369 if len(conditions) == 1 { 370 return conditions[0] 371 } 372 condition := &ast.BinaryOperationExpr{ 373 Op: opcode.AndAnd, 374 L: conditions[0], 375 R: b.joinConditions(conditions[1:]), 376 } 377 ast.MergeChildrenFlags(condition, condition.L, condition.R) 378 return condition 379 } 380 381 func (b *executorBuilder) buildSelectLock(v *plan.SelectLock) Executor { 382 src := b.build(v.GetChildByIndex(0)) 383 if autocommit.ShouldAutocommit(b.ctx) { 384 // Locking of rows for update using SELECT FOR UPDATE only applies when autocommit 385 // is disabled (either by beginning transaction with START TRANSACTION or by setting 386 // autocommit to 0. If autocommit is enabled, the rows matching the specification are not locked. 387 // See: https://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html 388 return src 389 } 390 e := &SelectLockExec{ 391 Src: src, 392 Lock: v.Lock, 393 ctx: b.ctx, 394 } 395 return e 396 } 397 398 func (b *executorBuilder) buildSelectFields(v *plan.SelectFields) Executor { 399 src := b.build(v.GetChildByIndex(0)) 400 e := &SelectFieldsExec{ 401 Src: src, 402 ResultFields: v.Fields(), 403 ctx: b.ctx, 404 } 405 return e 406 } 407 408 func (b *executorBuilder) buildAggregate(v *plan.Aggregate) Executor { 409 src := b.build(v.GetChildByIndex(0)) 410 e := &AggregateExec{ 411 Src: src, 412 ResultFields: v.Fields(), 413 ctx: b.ctx, 414 AggFuncs: v.AggFuncs, 415 GroupByItems: v.GroupByItems, 416 } 417 return e 418 } 419 420 func (b *executorBuilder) buildHaving(v *plan.Having) Executor { 421 src := b.build(v.GetChildByIndex(0)) 422 return b.buildFilter(src, v.Conditions) 423 } 424 425 func (b *executorBuilder) buildSort(v *plan.Sort) Executor { 426 src := b.build(v.GetChildByIndex(0)) 427 e := &SortExec{ 428 Src: src, 429 ByItems: v.ByItems, 430 ctx: b.ctx, 431 Limit: v.ExecLimit, 432 } 433 return e 434 } 435 436 func (b *executorBuilder) buildLimit(v *plan.Limit) Executor { 437 src := b.build(v.GetChildByIndex(0)) 438 e := &LimitExec{ 439 Src: src, 440 Offset: v.Offset, 441 Count: v.Count, 442 } 443 return e 444 } 445 446 func (b *executorBuilder) buildUnion(v *plan.Union) Executor { 447 e := &UnionExec{ 448 fields: v.Fields(), 449 Sels: make([]Executor, len(v.Selects)), 450 } 451 for i, sel := range v.Selects { 452 selExec := b.build(sel) 453 e.Sels[i] = selExec 454 } 455 return e 456 } 457 458 func (b *executorBuilder) buildDistinct(v *plan.Distinct) Executor { 459 return &DistinctExec{Src: b.build(v.GetChildByIndex(0))} 460 } 461 462 func (b *executorBuilder) buildPrepare(v *plan.Prepare) Executor { 463 return &PrepareExec{ 464 Ctx: b.ctx, 465 IS: b.is, 466 Name: v.Name, 467 SQLText: v.SQLText, 468 } 469 } 470 471 func (b *executorBuilder) buildExecute(v *plan.Execute) Executor { 472 return &ExecuteExec{ 473 Ctx: b.ctx, 474 IS: b.is, 475 Name: v.Name, 476 UsingVars: v.UsingVars, 477 ID: v.ID, 478 } 479 } 480 481 func (b *executorBuilder) buildUpdate(v *plan.Update) Executor { 482 selExec := b.build(v.SelectPlan) 483 return &UpdateExec{ctx: b.ctx, SelectExec: selExec, OrderedList: v.OrderedList} 484 } 485 486 func (b *executorBuilder) buildDelete(v *plan.Delete) Executor { 487 selExec := b.build(v.SelectPlan) 488 return &DeleteExec{ 489 ctx: b.ctx, 490 SelectExec: selExec, 491 Tables: v.Tables, 492 IsMultiTable: v.IsMultiTable, 493 } 494 } 495 496 func (b *executorBuilder) buildShow(v *plan.Show) Executor { 497 e := &ShowExec{ 498 Tp: v.Tp, 499 DBName: model.NewCIStr(v.DBName), 500 Table: v.Table, 501 Column: v.Column, 502 User: v.User, 503 Flag: v.Flag, 504 Full: v.Full, 505 GlobalScope: v.GlobalScope, 506 ctx: b.ctx, 507 is: b.is, 508 fields: v.Fields(), 509 } 510 if e.Tp == ast.ShowGrants && len(e.User) == 0 { 511 e.User = variable.GetSessionVars(e.ctx).User 512 } 513 return e 514 } 515 516 func (b *executorBuilder) buildSimple(v *plan.Simple) Executor { 517 switch s := v.Statement.(type) { 518 case *ast.GrantStmt: 519 return b.buildGrant(s) 520 } 521 return &SimpleExec{Statement: v.Statement, ctx: b.ctx} 522 } 523 524 func (b *executorBuilder) buildInsert(v *plan.Insert) Executor { 525 ivs := &InsertValues{ 526 ctx: b.ctx, 527 Columns: v.Columns, 528 Lists: v.Lists, 529 Setlist: v.Setlist, 530 } 531 if v.SelectPlan != nil { 532 ivs.SelectExec = b.build(v.SelectPlan) 533 } 534 // Get Table 535 ts, ok := v.Table.TableRefs.Left.(*ast.TableSource) 536 if !ok { 537 b.err = errors.New("Can not get table") 538 return nil 539 } 540 tn, ok := ts.Source.(*ast.TableName) 541 if !ok { 542 b.err = errors.New("Can not get table") 543 return nil 544 } 545 tableInfo := tn.TableInfo 546 tbl, ok := b.is.TableByID(tableInfo.ID) 547 if !ok { 548 b.err = errors.Errorf("Can not get table %d", tableInfo.ID) 549 return nil 550 } 551 ivs.Table = tbl 552 if v.IsReplace { 553 return b.buildReplace(ivs) 554 } 555 insert := &InsertExec{ 556 InsertValues: ivs, 557 OnDuplicate: v.OnDuplicate, 558 Priority: v.Priority, 559 } 560 // fields is used to evaluate values expr. 561 insert.fields = ts.GetResultFields() 562 return insert 563 } 564 565 func (b *executorBuilder) buildReplace(vals *InsertValues) Executor { 566 return &ReplaceExec{ 567 InsertValues: vals, 568 } 569 } 570 571 func (b *executorBuilder) buildGrant(grant *ast.GrantStmt) Executor { 572 return &GrantExec{ 573 ctx: b.ctx, 574 Privs: grant.Privs, 575 ObjectType: grant.ObjectType, 576 Level: grant.Level, 577 Users: grant.Users, 578 } 579 } 580 581 func (b *executorBuilder) buildDDL(v *plan.DDL) Executor { 582 return &DDLExec{Statement: v.Statement, ctx: b.ctx, is: b.is} 583 } 584 585 func (b *executorBuilder) buildExplain(v *plan.Explain) Executor { 586 return &ExplainExec{ 587 StmtPlan: v.StmtPlan, 588 fields: v.Fields(), 589 } 590 }