github.com/matrixorigin/matrixone@v0.7.0/pkg/sql/plan/query_builder.go (about) 1 // Copyright 2022 Matrix Origin 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 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package plan 16 17 import ( 18 "context" 19 "encoding/json" 20 "fmt" 21 "go/constant" 22 "strconv" 23 "strings" 24 25 "github.com/matrixorigin/matrixone/pkg/sql/util" 26 27 "github.com/matrixorigin/matrixone/pkg/catalog" 28 "github.com/matrixorigin/matrixone/pkg/common/moerr" 29 "github.com/matrixorigin/matrixone/pkg/container/types" 30 "github.com/matrixorigin/matrixone/pkg/pb/plan" 31 "github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect" 32 "github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect/mysql" 33 "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" 34 "github.com/matrixorigin/matrixone/pkg/sql/plan/function" 35 ) 36 37 func NewQueryBuilder(queryType plan.Query_StatementType, ctx CompilerContext) *QueryBuilder { 38 var mysqlCompatible bool 39 40 mode, err := ctx.ResolveVariable("sql_mode", true, false) 41 if err == nil { 42 if modeStr, ok := mode.(string); ok { 43 if !strings.Contains(modeStr, "ONLY_FULL_GROUP_BY") { 44 mysqlCompatible = true 45 } 46 } 47 } 48 49 return &QueryBuilder{ 50 qry: &Query{ 51 StmtType: queryType, 52 }, 53 compCtx: ctx, 54 ctxByNode: []*BindContext{}, 55 nameByColRef: make(map[[2]int32]string), 56 nextTag: 0, 57 mysqlCompatible: mysqlCompatible, 58 } 59 } 60 61 func (builder *QueryBuilder) remapExpr(expr *Expr, colMap map[[2]int32][2]int32) error { 62 switch ne := expr.Expr.(type) { 63 case *plan.Expr_Col: 64 mapId := [2]int32{ne.Col.RelPos, ne.Col.ColPos} 65 if ids, ok := colMap[mapId]; ok { 66 ne.Col.RelPos = ids[0] 67 ne.Col.ColPos = ids[1] 68 ne.Col.Name = builder.nameByColRef[mapId] 69 } else { 70 return moerr.NewParseError(builder.GetContext(), "can't find column %v in context's map %v", mapId, colMap) 71 } 72 73 case *plan.Expr_F: 74 for _, arg := range ne.F.GetArgs() { 75 err := builder.remapExpr(arg, colMap) 76 if err != nil { 77 return err 78 } 79 } 80 } 81 return nil 82 } 83 84 type ColRefRemapping struct { 85 globalToLocal map[[2]int32][2]int32 86 localToGlobal [][2]int32 87 } 88 89 func (m *ColRefRemapping) addColRef(colRef [2]int32) { 90 m.globalToLocal[colRef] = [2]int32{0, int32(len(m.localToGlobal))} 91 m.localToGlobal = append(m.localToGlobal, colRef) 92 } 93 94 func (builder *QueryBuilder) remapAllColRefs(nodeID int32, colRefCnt map[[2]int32]int) (*ColRefRemapping, error) { 95 node := builder.qry.Nodes[nodeID] 96 97 remapping := &ColRefRemapping{ 98 globalToLocal: make(map[[2]int32][2]int32), 99 } 100 101 switch node.NodeType { 102 case plan.Node_TABLE_SCAN, plan.Node_MATERIAL_SCAN, plan.Node_EXTERNAL_SCAN, plan.Node_FUNCTION_SCAN: 103 for _, expr := range node.FilterList { 104 increaseRefCnt(expr, colRefCnt) 105 } 106 107 internalRemapping := &ColRefRemapping{ 108 globalToLocal: make(map[[2]int32][2]int32), 109 } 110 111 tag := node.BindingTags[0] 112 newTableDef := &plan.TableDef{ 113 Name: node.TableDef.Name, 114 Defs: node.TableDef.Defs, 115 Name2ColIndex: node.TableDef.Name2ColIndex, 116 Createsql: node.TableDef.Createsql, 117 TblFunc: node.TableDef.TblFunc, 118 TableType: node.TableDef.TableType, 119 CompositePkey: node.TableDef.CompositePkey, 120 OriginCols: node.TableDef.OriginCols, 121 } 122 123 for i, col := range node.TableDef.Cols { 124 globalRef := [2]int32{tag, int32(i)} 125 if colRefCnt[globalRef] == 0 { 126 continue 127 } 128 129 internalRemapping.addColRef(globalRef) 130 131 newTableDef.Cols = append(newTableDef.Cols, col) 132 } 133 134 if len(newTableDef.Cols) == 0 { 135 internalRemapping.addColRef([2]int32{tag, 0}) 136 newTableDef.Cols = append(newTableDef.Cols, node.TableDef.Cols[0]) 137 } 138 139 node.TableDef = newTableDef 140 141 for _, expr := range node.FilterList { 142 decreaseRefCnt(expr, colRefCnt) 143 err := builder.remapExpr(expr, internalRemapping.globalToLocal) 144 if err != nil { 145 return nil, err 146 } 147 } 148 149 for i, col := range node.TableDef.Cols { 150 if colRefCnt[internalRemapping.localToGlobal[i]] == 0 { 151 continue 152 } 153 154 remapping.addColRef(internalRemapping.localToGlobal[i]) 155 156 node.ProjectList = append(node.ProjectList, &plan.Expr{ 157 Typ: col.Typ, 158 Expr: &plan.Expr_Col{ 159 Col: &plan.ColRef{ 160 RelPos: 0, 161 ColPos: int32(i), 162 Name: builder.nameByColRef[internalRemapping.localToGlobal[i]], 163 }, 164 }, 165 }) 166 } 167 168 if len(node.ProjectList) == 0 { 169 if len(node.TableDef.Cols) == 0 { 170 globalRef := [2]int32{tag, 0} 171 remapping.addColRef(globalRef) 172 173 node.ProjectList = append(node.ProjectList, &plan.Expr{ 174 Typ: node.TableDef.Cols[0].Typ, 175 Expr: &plan.Expr_Col{ 176 Col: &plan.ColRef{ 177 RelPos: 0, 178 ColPos: 0, 179 Name: builder.nameByColRef[globalRef], 180 }, 181 }, 182 }) 183 } else { 184 remapping.addColRef(internalRemapping.localToGlobal[0]) 185 node.ProjectList = append(node.ProjectList, &plan.Expr{ 186 Typ: node.TableDef.Cols[0].Typ, 187 Expr: &plan.Expr_Col{ 188 Col: &plan.ColRef{ 189 RelPos: 0, 190 ColPos: 0, 191 Name: builder.nameByColRef[internalRemapping.localToGlobal[0]], 192 }, 193 }, 194 }) 195 } 196 } 197 198 if node.NodeType == plan.Node_FUNCTION_SCAN { 199 childId := node.Children[0] 200 childNode := builder.qry.Nodes[childId] 201 if childNode.NodeType != plan.Node_PROJECT { 202 break 203 } 204 _, err := builder.remapAllColRefs(childId, colRefCnt) 205 if err != nil { 206 return nil, err 207 } 208 } 209 210 case plan.Node_INTERSECT, plan.Node_INTERSECT_ALL, 211 plan.Node_UNION, plan.Node_UNION_ALL, 212 plan.Node_MINUS, plan.Node_MINUS_ALL: 213 214 thisTag := node.BindingTags[0] 215 leftID := node.Children[0] 216 rightID := node.Children[1] 217 for i, expr := range node.ProjectList { 218 increaseRefCnt(expr, colRefCnt) 219 globalRef := [2]int32{thisTag, int32(i)} 220 remapping.addColRef(globalRef) 221 } 222 223 rightNode := builder.qry.Nodes[rightID] 224 if rightNode.NodeType == plan.Node_PROJECT { 225 projectTag := rightNode.BindingTags[0] 226 for i := range rightNode.ProjectList { 227 increaseRefCnt(&plan.Expr{ 228 Expr: &plan.Expr_Col{ 229 Col: &plan.ColRef{ 230 RelPos: projectTag, 231 ColPos: int32(i), 232 }, 233 }}, colRefCnt) 234 } 235 } 236 237 internalMap := make(map[[2]int32][2]int32) 238 239 leftRemapping, err := builder.remapAllColRefs(leftID, colRefCnt) 240 if err != nil { 241 return nil, err 242 } 243 for k, v := range leftRemapping.globalToLocal { 244 internalMap[k] = v 245 } 246 247 _, err = builder.remapAllColRefs(rightID, colRefCnt) 248 if err != nil { 249 return nil, err 250 } 251 252 for _, expr := range node.ProjectList { 253 decreaseRefCnt(expr, colRefCnt) 254 err := builder.remapExpr(expr, internalMap) 255 if err != nil { 256 return nil, err 257 } 258 } 259 260 case plan.Node_JOIN: 261 for _, expr := range node.OnList { 262 increaseRefCnt(expr, colRefCnt) 263 } 264 265 internalMap := make(map[[2]int32][2]int32) 266 267 leftID := node.Children[0] 268 leftRemapping, err := builder.remapAllColRefs(leftID, colRefCnt) 269 if err != nil { 270 return nil, err 271 } 272 273 for k, v := range leftRemapping.globalToLocal { 274 internalMap[k] = v 275 } 276 277 rightID := node.Children[1] 278 rightRemapping, err := builder.remapAllColRefs(rightID, colRefCnt) 279 if err != nil { 280 return nil, err 281 } 282 283 for k, v := range rightRemapping.globalToLocal { 284 internalMap[k] = [2]int32{1, v[1]} 285 } 286 287 for _, expr := range node.OnList { 288 decreaseRefCnt(expr, colRefCnt) 289 err := builder.remapExpr(expr, internalMap) 290 if err != nil { 291 return nil, err 292 } 293 } 294 295 childProjList := builder.qry.Nodes[leftID].ProjectList 296 for i, globalRef := range leftRemapping.localToGlobal { 297 if colRefCnt[globalRef] == 0 { 298 continue 299 } 300 301 remapping.addColRef(globalRef) 302 303 node.ProjectList = append(node.ProjectList, &plan.Expr{ 304 Typ: childProjList[i].Typ, 305 Expr: &plan.Expr_Col{ 306 Col: &plan.ColRef{ 307 RelPos: 0, 308 ColPos: int32(i), 309 Name: builder.nameByColRef[globalRef], 310 }, 311 }, 312 }) 313 } 314 315 if node.JoinType == plan.Node_MARK { 316 globalRef := [2]int32{node.BindingTags[0], 0} 317 remapping.addColRef(globalRef) 318 319 node.ProjectList = append(node.ProjectList, &plan.Expr{ 320 Typ: &plan.Type{ 321 Id: int32(types.T_bool), 322 NotNullable: false, 323 Size: 1, 324 }, 325 Expr: &plan.Expr_Col{ 326 Col: &plan.ColRef{ 327 RelPos: -1, 328 ColPos: 0, 329 Name: builder.nameByColRef[globalRef], 330 }, 331 }, 332 }) 333 } else if node.JoinType != plan.Node_SEMI && node.JoinType != plan.Node_ANTI { 334 childProjList = builder.qry.Nodes[rightID].ProjectList 335 for i, globalRef := range rightRemapping.localToGlobal { 336 if colRefCnt[globalRef] == 0 { 337 continue 338 } 339 340 remapping.addColRef(globalRef) 341 342 node.ProjectList = append(node.ProjectList, &plan.Expr{ 343 Typ: childProjList[i].Typ, 344 Expr: &plan.Expr_Col{ 345 Col: &plan.ColRef{ 346 RelPos: 1, 347 ColPos: int32(i), 348 Name: builder.nameByColRef[globalRef], 349 }, 350 }, 351 }) 352 } 353 } 354 355 if len(node.ProjectList) == 0 && len(leftRemapping.localToGlobal) > 0 { 356 globalRef := leftRemapping.localToGlobal[0] 357 remapping.addColRef(globalRef) 358 359 node.ProjectList = append(node.ProjectList, &plan.Expr{ 360 Typ: builder.qry.Nodes[leftID].ProjectList[0].Typ, 361 Expr: &plan.Expr_Col{ 362 Col: &plan.ColRef{ 363 RelPos: 0, 364 ColPos: 0, 365 Name: builder.nameByColRef[globalRef], 366 }, 367 }, 368 }) 369 } 370 371 case plan.Node_AGG: 372 for _, expr := range node.GroupBy { 373 increaseRefCnt(expr, colRefCnt) 374 } 375 376 for _, expr := range node.AggList { 377 increaseRefCnt(expr, colRefCnt) 378 } 379 380 childRemapping, err := builder.remapAllColRefs(node.Children[0], colRefCnt) 381 if err != nil { 382 return nil, err 383 } 384 385 groupTag := node.BindingTags[0] 386 aggregateTag := node.BindingTags[1] 387 388 for idx, expr := range node.GroupBy { 389 decreaseRefCnt(expr, colRefCnt) 390 err := builder.remapExpr(expr, childRemapping.globalToLocal) 391 if err != nil { 392 return nil, err 393 } 394 395 globalRef := [2]int32{groupTag, int32(idx)} 396 if colRefCnt[globalRef] == 0 { 397 continue 398 } 399 400 remapping.addColRef(globalRef) 401 402 node.ProjectList = append(node.ProjectList, &plan.Expr{ 403 Typ: expr.Typ, 404 Expr: &plan.Expr_Col{ 405 Col: &ColRef{ 406 RelPos: -1, 407 ColPos: int32(idx), 408 Name: builder.nameByColRef[globalRef], 409 }, 410 }, 411 }) 412 } 413 414 groupSize := int32(len(node.GroupBy)) 415 for idx, expr := range node.AggList { 416 decreaseRefCnt(expr, colRefCnt) 417 err := builder.remapExpr(expr, childRemapping.globalToLocal) 418 if err != nil { 419 return nil, err 420 } 421 422 globalRef := [2]int32{aggregateTag, int32(idx)} 423 if colRefCnt[globalRef] == 0 { 424 continue 425 } 426 427 remapping.addColRef(globalRef) 428 429 node.ProjectList = append(node.ProjectList, &Expr{ 430 Typ: expr.Typ, 431 Expr: &plan.Expr_Col{ 432 Col: &ColRef{ 433 RelPos: -2, 434 ColPos: int32(idx) + groupSize, 435 Name: builder.nameByColRef[globalRef], 436 }, 437 }, 438 }) 439 } 440 441 if len(node.ProjectList) == 0 { 442 if groupSize > 0 { 443 globalRef := [2]int32{groupTag, 0} 444 remapping.addColRef(globalRef) 445 446 node.ProjectList = append(node.ProjectList, &plan.Expr{ 447 Typ: node.GroupBy[0].Typ, 448 Expr: &plan.Expr_Col{ 449 Col: &plan.ColRef{ 450 RelPos: -1, 451 ColPos: 0, 452 Name: builder.nameByColRef[globalRef], 453 }, 454 }, 455 }) 456 } else { 457 globalRef := [2]int32{aggregateTag, 0} 458 remapping.addColRef(globalRef) 459 460 node.ProjectList = append(node.ProjectList, &plan.Expr{ 461 Typ: node.AggList[0].Typ, 462 Expr: &plan.Expr_Col{ 463 Col: &plan.ColRef{ 464 RelPos: -2, 465 ColPos: 0, 466 Name: builder.nameByColRef[globalRef], 467 }, 468 }, 469 }) 470 } 471 } 472 473 case plan.Node_SORT: 474 for _, orderBy := range node.OrderBy { 475 increaseRefCnt(orderBy.Expr, colRefCnt) 476 } 477 478 childRemapping, err := builder.remapAllColRefs(node.Children[0], colRefCnt) 479 if err != nil { 480 return nil, err 481 } 482 483 for _, orderBy := range node.OrderBy { 484 decreaseRefCnt(orderBy.Expr, colRefCnt) 485 err := builder.remapExpr(orderBy.Expr, childRemapping.globalToLocal) 486 if err != nil { 487 return nil, err 488 } 489 } 490 491 childProjList := builder.qry.Nodes[node.Children[0]].ProjectList 492 for i, globalRef := range childRemapping.localToGlobal { 493 if colRefCnt[globalRef] == 0 { 494 continue 495 } 496 497 remapping.addColRef(globalRef) 498 499 node.ProjectList = append(node.ProjectList, &plan.Expr{ 500 Typ: childProjList[i].Typ, 501 Expr: &plan.Expr_Col{ 502 Col: &plan.ColRef{ 503 RelPos: 0, 504 ColPos: int32(i), 505 Name: builder.nameByColRef[globalRef], 506 }, 507 }, 508 }) 509 } 510 511 if len(node.ProjectList) == 0 && len(childRemapping.localToGlobal) > 0 { 512 globalRef := childRemapping.localToGlobal[0] 513 remapping.addColRef(globalRef) 514 515 node.ProjectList = append(node.ProjectList, &plan.Expr{ 516 Typ: childProjList[0].Typ, 517 Expr: &plan.Expr_Col{ 518 Col: &plan.ColRef{ 519 RelPos: 0, 520 ColPos: 0, 521 Name: builder.nameByColRef[globalRef], 522 }, 523 }, 524 }) 525 } 526 527 case plan.Node_FILTER: 528 for _, expr := range node.FilterList { 529 increaseRefCnt(expr, colRefCnt) 530 } 531 532 childRemapping, err := builder.remapAllColRefs(node.Children[0], colRefCnt) 533 if err != nil { 534 return nil, err 535 } 536 537 for _, expr := range node.FilterList { 538 decreaseRefCnt(expr, colRefCnt) 539 err := builder.remapExpr(expr, childRemapping.globalToLocal) 540 if err != nil { 541 return nil, err 542 } 543 } 544 545 childProjList := builder.qry.Nodes[node.Children[0]].ProjectList 546 for i, globalRef := range childRemapping.localToGlobal { 547 if colRefCnt[globalRef] == 0 { 548 continue 549 } 550 551 remapping.addColRef(globalRef) 552 553 node.ProjectList = append(node.ProjectList, &plan.Expr{ 554 Typ: childProjList[i].Typ, 555 Expr: &plan.Expr_Col{ 556 Col: &plan.ColRef{ 557 RelPos: 0, 558 ColPos: int32(i), 559 Name: builder.nameByColRef[globalRef], 560 }, 561 }, 562 }) 563 } 564 565 if len(node.ProjectList) == 0 { 566 if len(childRemapping.localToGlobal) > 0 { 567 remapping.addColRef(childRemapping.localToGlobal[0]) 568 } 569 570 node.ProjectList = append(node.ProjectList, &plan.Expr{ 571 Typ: childProjList[0].Typ, 572 Expr: &plan.Expr_Col{ 573 Col: &plan.ColRef{ 574 RelPos: 0, 575 ColPos: 0, 576 }, 577 }, 578 }) 579 } 580 581 case plan.Node_PROJECT, plan.Node_MATERIAL: 582 projectTag := node.BindingTags[0] 583 584 var neededProj []int32 585 586 for i, expr := range node.ProjectList { 587 globalRef := [2]int32{projectTag, int32(i)} 588 if colRefCnt[globalRef] == 0 { 589 continue 590 } 591 592 neededProj = append(neededProj, int32(i)) 593 increaseRefCnt(expr, colRefCnt) 594 } 595 596 if len(neededProj) == 0 { 597 increaseRefCnt(node.ProjectList[0], colRefCnt) 598 neededProj = append(neededProj, 0) 599 } 600 601 childRemapping, err := builder.remapAllColRefs(node.Children[0], colRefCnt) 602 if err != nil { 603 return nil, err 604 } 605 606 var newProjList []*plan.Expr 607 for _, needed := range neededProj { 608 expr := node.ProjectList[needed] 609 decreaseRefCnt(expr, colRefCnt) 610 err := builder.remapExpr(expr, childRemapping.globalToLocal) 611 if err != nil { 612 return nil, err 613 } 614 615 globalRef := [2]int32{projectTag, needed} 616 remapping.addColRef(globalRef) 617 618 newProjList = append(newProjList, expr) 619 } 620 621 node.ProjectList = newProjList 622 623 case plan.Node_DISTINCT: 624 childRemapping, err := builder.remapAllColRefs(node.Children[0], colRefCnt) 625 if err != nil { 626 return nil, err 627 } 628 629 // Rewrite DISTINCT to AGG 630 node.NodeType = plan.Node_AGG 631 preNode := builder.qry.Nodes[node.Children[0]] 632 node.GroupBy = make([]*Expr, len(preNode.ProjectList)) 633 node.ProjectList = make([]*Expr, len(preNode.ProjectList)) 634 635 for i, prjExpr := range preNode.ProjectList { 636 node.GroupBy[i] = &plan.Expr{ 637 Typ: prjExpr.Typ, 638 Expr: &plan.Expr_Col{ 639 Col: &plan.ColRef{ 640 RelPos: 0, 641 ColPos: int32(i), 642 }, 643 }, 644 } 645 646 node.ProjectList[i] = &plan.Expr{ 647 Typ: prjExpr.Typ, 648 Expr: &plan.Expr_Col{ 649 Col: &plan.ColRef{ 650 RelPos: -1, 651 ColPos: int32(i), 652 }, 653 }, 654 } 655 } 656 657 remapping = childRemapping 658 659 case plan.Node_VALUE_SCAN: 660 // VALUE_SCAN always have one column now 661 if node.TableDef == nil { // like select 1,2 662 node.ProjectList = append(node.ProjectList, &plan.Expr{ 663 Typ: &plan.Type{Id: int32(types.T_int64)}, 664 Expr: &plan.Expr_C{C: &plan.Const{Value: &plan.Const_I64Val{I64Val: 0}}}, 665 }) 666 } else { 667 internalRemapping := &ColRefRemapping{ 668 globalToLocal: make(map[[2]int32][2]int32), 669 } 670 671 tag := node.BindingTags[0] 672 for i := range node.TableDef.Cols { 673 globalRef := [2]int32{tag, int32(i)} 674 if colRefCnt[globalRef] == 0 { 675 continue 676 } 677 internalRemapping.addColRef(globalRef) 678 } 679 680 for i, col := range node.TableDef.Cols { 681 if colRefCnt[internalRemapping.localToGlobal[i]] == 0 { 682 continue 683 } 684 685 remapping.addColRef(internalRemapping.localToGlobal[i]) 686 687 node.ProjectList = append(node.ProjectList, &plan.Expr{ 688 Typ: col.Typ, 689 Expr: &plan.Expr_Col{ 690 Col: &plan.ColRef{ 691 RelPos: 0, 692 ColPos: int32(i), 693 Name: col.Name, 694 }, 695 }, 696 }) 697 } 698 } 699 700 default: 701 return nil, moerr.NewInternalError(builder.GetContext(), "unsupport node type") 702 } 703 704 node.BindingTags = nil 705 706 return remapping, nil 707 } 708 709 func (builder *QueryBuilder) createQuery() (*Query, error) { 710 for i, rootId := range builder.qry.Steps { 711 rootId, _ = builder.pushdownFilters(rootId, nil) 712 ReCalcNodeStats(rootId, builder, true) 713 rootId = builder.determineJoinOrder(rootId) 714 rootId = builder.pushdownSemiAntiJoins(rootId) 715 builder.qry.Steps[i] = rootId 716 717 colRefCnt := make(map[[2]int32]int) 718 rootNode := builder.qry.Nodes[rootId] 719 resultTag := rootNode.BindingTags[0] 720 for i := range rootNode.ProjectList { 721 colRefCnt[[2]int32{resultTag, int32(i)}] = 1 722 } 723 724 _, err := builder.remapAllColRefs(rootId, colRefCnt) 725 if err != nil { 726 return nil, err 727 } 728 } 729 return builder.qry, nil 730 } 731 732 func (builder *QueryBuilder) buildUnion(stmt *tree.UnionClause, astOrderBy tree.OrderBy, astLimit *tree.Limit, ctx *BindContext, isRoot bool) (int32, error) { 733 var selectStmts []tree.Statement 734 var unionTypes []plan.Node_NodeType 735 736 // get Union selectStmts 737 err := getUnionSelects(builder.GetContext(), stmt, &selectStmts, &unionTypes) 738 if err != nil { 739 return 0, err 740 } 741 742 if len(selectStmts) == 1 { 743 switch sltStmt := selectStmts[0].(type) { 744 case *tree.Select: 745 if sltClause, ok := sltStmt.Select.(*tree.SelectClause); ok { 746 sltClause.Distinct = true 747 return builder.buildSelect(sltStmt, ctx, isRoot) 748 } else { 749 // rewrite sltStmt to select distinct * from (sltStmt) a 750 tmpSltStmt := &tree.Select{ 751 Select: &tree.SelectClause{ 752 Distinct: true, 753 754 Exprs: []tree.SelectExpr{ 755 {Expr: tree.StarExpr()}, 756 }, 757 From: &tree.From{ 758 Tables: tree.TableExprs{ 759 &tree.AliasedTableExpr{ 760 Expr: &tree.ParenTableExpr{ 761 Expr: sltStmt, 762 }, 763 As: tree.AliasClause{ 764 Alias: "a", 765 }, 766 }, 767 }, 768 }, 769 }, 770 Limit: astLimit, 771 OrderBy: astOrderBy, 772 } 773 return builder.buildSelect(tmpSltStmt, ctx, isRoot) 774 } 775 776 case *tree.SelectClause: 777 if !sltStmt.Distinct { 778 sltStmt.Distinct = true 779 } 780 return builder.buildSelect(&tree.Select{Select: sltStmt, Limit: astLimit, OrderBy: astOrderBy}, ctx, isRoot) 781 } 782 } 783 784 // build selects 785 var projectTypList [][]types.Type 786 selectStmtLength := len(selectStmts) 787 nodes := make([]int32, selectStmtLength) 788 subCtxList := make([]*BindContext, selectStmtLength) 789 var projectLength int 790 var nodeID int32 791 for idx, sltStmt := range selectStmts { 792 subCtx := NewBindContext(builder, ctx) 793 if slt, ok := sltStmt.(*tree.Select); ok { 794 nodeID, err = builder.buildSelect(slt, subCtx, isRoot) 795 } else { 796 nodeID, err = builder.buildSelect(&tree.Select{Select: sltStmt}, subCtx, isRoot) 797 } 798 if err != nil { 799 return 0, err 800 } 801 802 if idx == 0 { 803 projectLength = len(builder.qry.Nodes[nodeID].ProjectList) 804 projectTypList = make([][]types.Type, projectLength) 805 for i := 0; i < projectLength; i++ { 806 projectTypList[i] = make([]types.Type, selectStmtLength) 807 } 808 } else { 809 if projectLength != len(builder.qry.Nodes[nodeID].ProjectList) { 810 return 0, moerr.NewParseError(builder.GetContext(), "SELECT statements have different number of columns") 811 } 812 } 813 814 for i, expr := range subCtx.results { 815 projectTypList[i][idx] = makeTypeByPlan2Expr(expr) 816 } 817 subCtxList[idx] = subCtx 818 nodes[idx] = nodeID 819 } 820 821 // reset all select's return Projection(type cast up) 822 // we use coalesce function's type check&type cast rule 823 for columnIdx, argsType := range projectTypList { 824 // we don't cast null as any type in function 825 // but we will cast null as some target type in union/intersect/minus 826 var tmpArgsType []types.Type 827 for _, typ := range argsType { 828 if typ.Oid != types.T_any { 829 tmpArgsType = append(tmpArgsType, typ) 830 } 831 } 832 833 if len(tmpArgsType) > 0 { 834 _, _, argsCastType, err := function.GetFunctionByName(builder.GetContext(), "coalesce", tmpArgsType) 835 if err != nil { 836 return 0, moerr.NewParseError(builder.GetContext(), "the %d column cann't cast to a same type", columnIdx) 837 } 838 839 if len(argsCastType) > 0 && int(argsCastType[0].Oid) == int(types.T_datetime) { 840 for i := 0; i < len(argsCastType); i++ { 841 argsCastType[i].Precision = 0 842 } 843 } 844 var targetType *plan.Type 845 var targetArgType types.Type 846 if len(argsCastType) == 0 { 847 targetArgType = tmpArgsType[0] 848 } else { 849 targetArgType = argsCastType[0] 850 } 851 // if string union string, different length may cause error. use text type as the output 852 if targetArgType.Oid == types.T_varchar || targetArgType.Oid == types.T_char { 853 targetArgType = types.T_text.ToType() 854 } 855 targetType = makePlan2Type(&targetArgType) 856 857 for idx, tmpID := range nodes { 858 if !argsType[idx].Eq(targetArgType) { 859 node := builder.qry.Nodes[tmpID] 860 if argsType[idx].Oid == types.T_any { 861 node.ProjectList[columnIdx].Typ = targetType 862 } else { 863 node.ProjectList[columnIdx], err = appendCastBeforeExpr(builder.GetContext(), node.ProjectList[columnIdx], targetType) 864 if err != nil { 865 return 0, err 866 } 867 } 868 } 869 } 870 } 871 } 872 873 firstSelectProjectNode := builder.qry.Nodes[nodes[0]] 874 // set ctx's headings projects results 875 ctx.headings = append(ctx.headings, subCtxList[0].headings...) 876 877 getProjectList := func(tag int32, thisTag int32) []*plan.Expr { 878 projectList := make([]*plan.Expr, len(firstSelectProjectNode.ProjectList)) 879 for i, expr := range firstSelectProjectNode.ProjectList { 880 projectList[i] = &plan.Expr{ 881 Typ: expr.Typ, 882 Expr: &plan.Expr_Col{ 883 Col: &plan.ColRef{ 884 RelPos: tag, 885 ColPos: int32(i), 886 }, 887 }, 888 } 889 builder.nameByColRef[[2]int32{thisTag, int32(i)}] = ctx.headings[i] 890 } 891 return projectList 892 } 893 894 // build intersect node first. because intersect has higher precedence then UNION and MINUS 895 var newNodes []int32 896 var newUnionType []plan.Node_NodeType 897 var lastTag int32 898 newNodes = append(newNodes, nodes[0]) 899 for i := 1; i < len(nodes); i++ { 900 utIdx := i - 1 901 lastNewNodeIdx := len(newNodes) - 1 902 if unionTypes[utIdx] == plan.Node_INTERSECT || unionTypes[utIdx] == plan.Node_INTERSECT_ALL { 903 lastTag = builder.genNewTag() 904 leftNodeTag := builder.qry.Nodes[newNodes[lastNewNodeIdx]].BindingTags[0] 905 newNodeID := builder.appendNode(&plan.Node{ 906 NodeType: unionTypes[utIdx], 907 Children: []int32{newNodes[lastNewNodeIdx], nodes[i]}, 908 BindingTags: []int32{lastTag}, 909 ProjectList: getProjectList(leftNodeTag, lastTag), 910 }, ctx) 911 newNodes[lastNewNodeIdx] = newNodeID 912 } else { 913 newNodes = append(newNodes, nodes[i]) 914 newUnionType = append(newUnionType, unionTypes[utIdx]) 915 } 916 } 917 918 // build UNION/MINUS node one by one 919 lastNodeId := newNodes[0] 920 for i := 1; i < len(newNodes); i++ { 921 utIdx := i - 1 922 lastTag = builder.genNewTag() 923 leftNodeTag := builder.qry.Nodes[lastNodeId].BindingTags[0] 924 925 lastNodeId = builder.appendNode(&plan.Node{ 926 NodeType: newUnionType[utIdx], 927 Children: []int32{lastNodeId, newNodes[i]}, 928 BindingTags: []int32{lastTag}, 929 ProjectList: getProjectList(leftNodeTag, lastTag), 930 }, ctx) 931 } 932 933 // set ctx base on selects[0] and it's ctx 934 ctx.groupTag = builder.genNewTag() 935 ctx.aggregateTag = builder.genNewTag() 936 ctx.projectTag = builder.genNewTag() 937 for i, v := range ctx.headings { 938 ctx.aliasMap[v] = int32(i) 939 builder.nameByColRef[[2]int32{ctx.projectTag, int32(i)}] = v 940 } 941 for i, expr := range firstSelectProjectNode.ProjectList { 942 ctx.projects = append(ctx.projects, &plan.Expr{ 943 Typ: expr.Typ, 944 Expr: &plan.Expr_Col{ 945 Col: &plan.ColRef{ 946 RelPos: lastTag, 947 ColPos: int32(i), 948 }, 949 }, 950 }) 951 } 952 havingBinder := NewHavingBinder(builder, ctx) 953 projectionBinder := NewProjectionBinder(builder, ctx, havingBinder) 954 955 // append a project node 956 lastNodeId = builder.appendNode(&plan.Node{ 957 NodeType: plan.Node_PROJECT, 958 ProjectList: ctx.projects, 959 Children: []int32{lastNodeId}, 960 BindingTags: []int32{ctx.projectTag}, 961 }, ctx) 962 963 // append orderBy 964 if astOrderBy != nil { 965 orderBinder := NewOrderBinder(projectionBinder, nil) 966 orderBys := make([]*plan.OrderBySpec, 0, len(astOrderBy)) 967 968 for _, order := range astOrderBy { 969 expr, err := orderBinder.BindExpr(order.Expr) 970 if err != nil { 971 return 0, err 972 } 973 974 orderBy := &plan.OrderBySpec{ 975 Expr: expr, 976 Flag: plan.OrderBySpec_INTERNAL, 977 } 978 979 switch order.Direction { 980 case tree.Ascending: 981 orderBy.Flag |= plan.OrderBySpec_ASC 982 case tree.Descending: 983 orderBy.Flag |= plan.OrderBySpec_DESC 984 } 985 986 switch order.NullsPosition { 987 case tree.NullsFirst: 988 orderBy.Flag |= plan.OrderBySpec_NULLS_FIRST 989 case tree.NullsLast: 990 orderBy.Flag |= plan.OrderBySpec_NULLS_LAST 991 } 992 993 orderBys = append(orderBys, orderBy) 994 } 995 996 lastNodeId = builder.appendNode(&plan.Node{ 997 NodeType: plan.Node_SORT, 998 Children: []int32{lastNodeId}, 999 OrderBy: orderBys, 1000 }, ctx) 1001 } 1002 1003 // append limit 1004 if astLimit != nil { 1005 node := builder.qry.Nodes[lastNodeId] 1006 1007 limitBinder := NewLimitBinder(builder, ctx) 1008 if astLimit.Offset != nil { 1009 node.Offset, err = limitBinder.BindExpr(astLimit.Offset, 0, true) 1010 if err != nil { 1011 return 0, err 1012 } 1013 } 1014 if astLimit.Count != nil { 1015 node.Limit, err = limitBinder.BindExpr(astLimit.Count, 0, true) 1016 if err != nil { 1017 return 0, err 1018 } 1019 1020 if cExpr, ok := node.Limit.Expr.(*plan.Expr_C); ok { 1021 if c, ok := cExpr.C.Value.(*plan.Const_I64Val); ok { 1022 ctx.hasSingleRow = c.I64Val == 1 1023 } 1024 } 1025 } 1026 } 1027 1028 // append result PROJECT node 1029 if builder.qry.Nodes[lastNodeId].NodeType != plan.Node_PROJECT { 1030 for i := 0; i < len(ctx.projects); i++ { 1031 ctx.results = append(ctx.results, &plan.Expr{ 1032 Typ: ctx.projects[i].Typ, 1033 Expr: &plan.Expr_Col{ 1034 Col: &plan.ColRef{ 1035 RelPos: ctx.projectTag, 1036 ColPos: int32(i), 1037 }, 1038 }, 1039 }) 1040 } 1041 ctx.resultTag = builder.genNewTag() 1042 1043 lastNodeId = builder.appendNode(&plan.Node{ 1044 NodeType: plan.Node_PROJECT, 1045 ProjectList: ctx.results, 1046 Children: []int32{lastNodeId}, 1047 BindingTags: []int32{ctx.resultTag}, 1048 }, ctx) 1049 } else { 1050 ctx.results = ctx.projects 1051 } 1052 1053 // set heading 1054 if isRoot { 1055 builder.qry.Headings = append(builder.qry.Headings, ctx.headings...) 1056 } 1057 1058 return lastNodeId, nil 1059 } 1060 1061 func (builder *QueryBuilder) buildSelect(stmt *tree.Select, ctx *BindContext, isRoot bool) (int32, error) { 1062 // preprocess CTEs 1063 if stmt.With != nil { 1064 ctx.cteByName = make(map[string]*CTERef) 1065 maskedNames := make([]string, len(stmt.With.CTEs)) 1066 1067 for i := range stmt.With.CTEs { 1068 idx := len(stmt.With.CTEs) - i - 1 1069 cte := stmt.With.CTEs[idx] 1070 1071 name := string(cte.Name.Alias) 1072 if _, ok := ctx.cteByName[name]; ok { 1073 return 0, moerr.NewSyntaxError(builder.GetContext(), "WITH query name %q specified more than once", name) 1074 } 1075 1076 var maskedCTEs map[string]any 1077 if len(maskedNames) > 0 { 1078 maskedCTEs = make(map[string]any) 1079 for _, mask := range maskedNames { 1080 maskedCTEs[mask] = nil 1081 } 1082 } 1083 1084 maskedNames = append(maskedNames, name) 1085 1086 ctx.cteByName[name] = &CTERef{ 1087 ast: cte, 1088 maskedCTEs: maskedCTEs, 1089 } 1090 } 1091 1092 // Try to do binding for CTE at declaration 1093 for _, cte := range stmt.With.CTEs { 1094 subCtx := NewBindContext(builder, ctx) 1095 subCtx.maskedCTEs = ctx.cteByName[string(cte.Name.Alias)].maskedCTEs 1096 1097 var err error 1098 switch stmt := cte.Stmt.(type) { 1099 case *tree.Select: 1100 _, err = builder.buildSelect(stmt, subCtx, false) 1101 1102 case *tree.ParenSelect: 1103 _, err = builder.buildSelect(stmt.Select, subCtx, false) 1104 1105 default: 1106 err = moerr.NewParseError(builder.GetContext(), "unexpected statement: '%v'", tree.String(stmt, dialect.MYSQL)) 1107 } 1108 1109 if err != nil { 1110 return 0, err 1111 } 1112 } 1113 } 1114 1115 var clause *tree.SelectClause 1116 var valuesClause *tree.ValuesClause 1117 var nodeID int32 1118 var err error 1119 astOrderBy := stmt.OrderBy 1120 astLimit := stmt.Limit 1121 1122 // strip parentheses 1123 // ((select a from t1)) order by b [ is equal ] select a from t1 order by b 1124 // (((select a from t1)) order by b) [ is equal ] select a from t1 order by b 1125 // 1126 // (select a from t1 union/union all select aa from t2) order by a 1127 // => we will strip parentheses, but order by only can use 'a' column from the union's output projectlist 1128 for { 1129 if selectClause, ok := stmt.Select.(*tree.ParenSelect); ok { 1130 if selectClause.Select.OrderBy != nil { 1131 if astOrderBy != nil { 1132 return 0, moerr.NewSyntaxError(builder.GetContext(), "multiple ORDER BY clauses not allowed") 1133 } 1134 astOrderBy = selectClause.Select.OrderBy 1135 } 1136 if selectClause.Select.Limit != nil { 1137 if astLimit != nil { 1138 return 0, moerr.NewSyntaxError(builder.GetContext(), "multiple LIMIT clauses not allowed") 1139 } 1140 astLimit = selectClause.Select.Limit 1141 } 1142 stmt = selectClause.Select 1143 } else { 1144 break 1145 } 1146 } 1147 1148 switch selectClause := stmt.Select.(type) { 1149 case *tree.SelectClause: 1150 clause = selectClause 1151 case *tree.UnionClause: 1152 return builder.buildUnion(selectClause, astOrderBy, astLimit, ctx, isRoot) 1153 case *tree.ValuesClause: 1154 valuesClause = selectClause 1155 default: 1156 return 0, moerr.NewNYI(builder.GetContext(), "statement '%s'", tree.String(stmt, dialect.MYSQL)) 1157 } 1158 1159 var projectionBinder *ProjectionBinder 1160 var havingList []*plan.Expr 1161 var selectList tree.SelectExprs 1162 var resultLen int 1163 var havingBinder *HavingBinder 1164 1165 if clause == nil { 1166 rowCount := len(valuesClause.Rows) 1167 if len(valuesClause.Rows) == 0 { 1168 return 0, moerr.NewInternalError(builder.GetContext(), "values statement have not rows") 1169 } 1170 colCount := len(valuesClause.Rows[0]) 1171 for j := 1; j < rowCount; j++ { 1172 if len(valuesClause.Rows[j]) != colCount { 1173 return 0, moerr.NewInternalError(builder.GetContext(), fmt.Sprintf("have different column count in row '%v'", j)) 1174 } 1175 } 1176 1177 ctx.hasSingleRow = rowCount == 1 1178 rowSetData := &plan.RowsetData{ 1179 Cols: make([]*plan.ColData, colCount), 1180 } 1181 tableDef := &plan.TableDef{ 1182 TblId: 0, 1183 Name: "", 1184 Cols: make([]*plan.ColDef, colCount), 1185 } 1186 ctx.binder = NewWhereBinder(builder, ctx) 1187 for i := 0; i < colCount; i++ { 1188 rows := make([]*plan.Expr, rowCount) 1189 var colTyp *plan.Type 1190 var tmpArgsType []types.Type 1191 for j := 0; j < rowCount; j++ { 1192 planExpr, err := ctx.binder.BindExpr(valuesClause.Rows[j][i], 0, true) 1193 if err != nil { 1194 return 0, err 1195 } 1196 if planExpr.Typ.Id != int32(types.T_any) { 1197 tmpArgsType = append(tmpArgsType, makeTypeByPlan2Expr(planExpr)) 1198 } 1199 rows[j] = planExpr 1200 } 1201 1202 if len(tmpArgsType) > 0 { 1203 _, _, argsCastType, err := function.GetFunctionByName(builder.GetContext(), "coalesce", tmpArgsType) 1204 if err != nil { 1205 return 0, err 1206 } 1207 if len(argsCastType) > 0 { 1208 colTyp = makePlan2Type(&argsCastType[0]) 1209 for j := 0; j < rowCount; j++ { 1210 if rows[j].Typ.Id != int32(types.T_any) && rows[j].Typ.Id != colTyp.Id { 1211 rows[j], err = appendCastBeforeExpr(builder.GetContext(), rows[j], colTyp) 1212 if err != nil { 1213 return 0, err 1214 } 1215 } 1216 } 1217 } 1218 } 1219 if colTyp == nil { 1220 colTyp = rows[0].Typ 1221 } 1222 1223 colName := fmt.Sprintf("column_%d", i) // like MySQL 1224 selectList = append(selectList, tree.SelectExpr{ 1225 Expr: &tree.UnresolvedName{ 1226 NumParts: 1, 1227 Star: false, 1228 Parts: [4]string{colName, "", "", ""}, 1229 }, 1230 As: tree.UnrestrictedIdentifier(colName), 1231 }) 1232 ctx.headings = append(ctx.headings, colName) 1233 tableDef.Cols[i] = &plan.ColDef{ 1234 ColId: 0, 1235 Name: colName, 1236 Typ: colTyp, 1237 } 1238 rowSetData.Cols[i] = &plan.ColData{ 1239 Data: rows, 1240 } 1241 } 1242 nodeID = builder.appendNode(&plan.Node{ 1243 NodeType: plan.Node_VALUE_SCAN, 1244 RowsetData: rowSetData, 1245 TableDef: tableDef, 1246 BindingTags: []int32{builder.genNewTag()}, 1247 }, ctx) 1248 1249 err = builder.addBinding(nodeID, tree.AliasClause{ 1250 Alias: "_ValueScan", 1251 }, ctx) 1252 if err != nil { 1253 return 0, err 1254 } 1255 } else { 1256 // build FROM clause 1257 nodeID, err = builder.buildFrom(clause.From.Tables, ctx) 1258 if err != nil { 1259 return 0, err 1260 } 1261 1262 ctx.binder = NewWhereBinder(builder, ctx) 1263 // unfold stars and generate headings 1264 for _, selectExpr := range clause.Exprs { 1265 switch expr := selectExpr.Expr.(type) { 1266 case tree.UnqualifiedStar: 1267 cols, names, err := ctx.unfoldStar(builder.GetContext(), "", builder.compCtx.GetAccountId() == catalog.System_Account) 1268 if err != nil { 1269 return 0, err 1270 } 1271 selectList = append(selectList, cols...) 1272 ctx.headings = append(ctx.headings, names...) 1273 1274 case *tree.UnresolvedName: 1275 if expr.Star { 1276 cols, names, err := ctx.unfoldStar(builder.GetContext(), expr.Parts[0], builder.compCtx.GetAccountId() == catalog.System_Account) 1277 if err != nil { 1278 return 0, err 1279 } 1280 selectList = append(selectList, cols...) 1281 ctx.headings = append(ctx.headings, names...) 1282 } else { 1283 if len(selectExpr.As) > 0 { 1284 ctx.headings = append(ctx.headings, string(selectExpr.As)) 1285 } else { 1286 ctx.headings = append(ctx.headings, expr.Parts[0]) 1287 } 1288 1289 newExpr, err := ctx.qualifyColumnNames(expr, nil, false) 1290 if err != nil { 1291 return 0, err 1292 } 1293 1294 selectList = append(selectList, tree.SelectExpr{ 1295 Expr: newExpr, 1296 As: selectExpr.As, 1297 }) 1298 } 1299 case *tree.NumVal: 1300 if expr.ValType == tree.P_null { 1301 expr.ValType = tree.P_nulltext 1302 } 1303 1304 if len(selectExpr.As) > 0 { 1305 ctx.headings = append(ctx.headings, string(selectExpr.As)) 1306 } else { 1307 ctx.headings = append(ctx.headings, tree.String(expr, dialect.MYSQL)) 1308 } 1309 newExpr, err := ctx.qualifyColumnNames(expr, nil, false) 1310 if err != nil { 1311 return 0, err 1312 } 1313 selectList = append(selectList, tree.SelectExpr{ 1314 Expr: newExpr, 1315 As: selectExpr.As, 1316 }) 1317 default: 1318 if len(selectExpr.As) > 0 { 1319 ctx.headings = append(ctx.headings, string(selectExpr.As)) 1320 } else { 1321 for { 1322 if parenExpr, ok := expr.(*tree.ParenExpr); ok { 1323 expr = parenExpr.Expr 1324 } else { 1325 break 1326 } 1327 } 1328 ctx.headings = append(ctx.headings, tree.String(expr, dialect.MYSQL)) 1329 } 1330 1331 newExpr, err := ctx.qualifyColumnNames(expr, nil, false) 1332 if err != nil { 1333 return 0, err 1334 } 1335 1336 selectList = append(selectList, tree.SelectExpr{ 1337 Expr: newExpr, 1338 As: selectExpr.As, 1339 }) 1340 } 1341 } 1342 1343 if len(selectList) == 0 { 1344 return 0, moerr.NewParseError(builder.GetContext(), "No tables used") 1345 } 1346 1347 // rewrite right join to left join 1348 builder.rewriteRightJoinToLeftJoin(nodeID) 1349 1350 if clause.Where != nil { 1351 whereList, err := splitAndBindCondition(clause.Where.Expr, ctx) 1352 if err != nil { 1353 return 0, err 1354 } 1355 1356 var newFilterList []*plan.Expr 1357 var expr *plan.Expr 1358 1359 for _, cond := range whereList { 1360 nodeID, expr, err = builder.flattenSubqueries(nodeID, cond, ctx) 1361 if err != nil { 1362 return 0, err 1363 } 1364 1365 newFilterList = append(newFilterList, expr) 1366 } 1367 1368 nodeID = builder.appendNode(&plan.Node{ 1369 NodeType: plan.Node_FILTER, 1370 Children: []int32{nodeID}, 1371 FilterList: newFilterList, 1372 }, ctx) 1373 } 1374 1375 ctx.groupTag = builder.genNewTag() 1376 ctx.aggregateTag = builder.genNewTag() 1377 ctx.projectTag = builder.genNewTag() 1378 1379 // bind GROUP BY clause 1380 if clause.GroupBy != nil { 1381 groupBinder := NewGroupBinder(builder, ctx) 1382 for _, group := range clause.GroupBy { 1383 group, err = ctx.qualifyColumnNames(group, nil, false) 1384 if err != nil { 1385 return 0, err 1386 } 1387 1388 _, err = groupBinder.BindExpr(group, 0, true) 1389 if err != nil { 1390 return 0, err 1391 } 1392 } 1393 } 1394 1395 // bind HAVING clause 1396 havingBinder = NewHavingBinder(builder, ctx) 1397 if clause.Having != nil { 1398 ctx.binder = havingBinder 1399 havingList, err = splitAndBindCondition(clause.Having.Expr, ctx) 1400 if err != nil { 1401 return 0, err 1402 } 1403 } 1404 1405 ctx.isDistinct = clause.Distinct 1406 } 1407 1408 // bind SELECT clause (Projection List) 1409 projectionBinder = NewProjectionBinder(builder, ctx, havingBinder) 1410 ctx.binder = projectionBinder 1411 for i, selectExpr := range selectList { 1412 astExpr, err := ctx.qualifyColumnNames(selectExpr.Expr, nil, false) 1413 if err != nil { 1414 return 0, err 1415 } 1416 1417 expr, err := projectionBinder.BindExpr(astExpr, 0, true) 1418 if err != nil { 1419 return 0, err 1420 } 1421 1422 builder.nameByColRef[[2]int32{ctx.projectTag, int32(i)}] = tree.String(astExpr, dialect.MYSQL) 1423 1424 alias := string(selectExpr.As) 1425 if len(alias) > 0 { 1426 ctx.aliasMap[alias] = int32(len(ctx.projects)) 1427 } 1428 ctx.projects = append(ctx.projects, expr) 1429 } 1430 1431 resultLen = len(ctx.projects) 1432 for i, proj := range ctx.projects { 1433 exprStr := proj.String() 1434 if _, ok := ctx.projectByExpr[exprStr]; !ok { 1435 ctx.projectByExpr[exprStr] = int32(i) 1436 } 1437 } 1438 1439 // bind ORDER BY clause 1440 var orderBys []*plan.OrderBySpec 1441 if astOrderBy != nil { 1442 orderBinder := NewOrderBinder(projectionBinder, selectList) 1443 orderBys = make([]*plan.OrderBySpec, 0, len(astOrderBy)) 1444 1445 for _, order := range astOrderBy { 1446 expr, err := orderBinder.BindExpr(order.Expr) 1447 if err != nil { 1448 return 0, err 1449 } 1450 1451 orderBy := &plan.OrderBySpec{ 1452 Expr: expr, 1453 Flag: plan.OrderBySpec_INTERNAL, 1454 } 1455 1456 switch order.Direction { 1457 case tree.Ascending: 1458 orderBy.Flag |= plan.OrderBySpec_ASC 1459 case tree.Descending: 1460 orderBy.Flag |= plan.OrderBySpec_DESC 1461 } 1462 1463 switch order.NullsPosition { 1464 case tree.NullsFirst: 1465 orderBy.Flag |= plan.OrderBySpec_NULLS_FIRST 1466 case tree.NullsLast: 1467 orderBy.Flag |= plan.OrderBySpec_NULLS_LAST 1468 } 1469 1470 orderBys = append(orderBys, orderBy) 1471 } 1472 } 1473 1474 // bind limit/offset clause 1475 var limitExpr *Expr 1476 var offsetExpr *Expr 1477 if astLimit != nil { 1478 limitBinder := NewLimitBinder(builder, ctx) 1479 if astLimit.Offset != nil { 1480 offsetExpr, err = limitBinder.BindExpr(astLimit.Offset, 0, true) 1481 if err != nil { 1482 return 0, err 1483 } 1484 } 1485 if astLimit.Count != nil { 1486 limitExpr, err = limitBinder.BindExpr(astLimit.Count, 0, true) 1487 if err != nil { 1488 return 0, err 1489 } 1490 1491 if cExpr, ok := limitExpr.Expr.(*plan.Expr_C); ok { 1492 if c, ok := cExpr.C.Value.(*plan.Const_I64Val); ok { 1493 ctx.hasSingleRow = c.I64Val == 1 1494 } 1495 } 1496 } 1497 } 1498 1499 if (len(ctx.groups) > 0 || len(ctx.aggregates) > 0) && len(projectionBinder.boundCols) > 0 { 1500 if !builder.mysqlCompatible { 1501 return 0, moerr.NewSyntaxError(builder.GetContext(), "column %q must appear in the GROUP BY clause or be used in an aggregate function", projectionBinder.boundCols[0]) 1502 } 1503 1504 // For MySQL compatibility, wrap bare ColRefs in any_value() 1505 for i, proj := range ctx.projects { 1506 ctx.projects[i] = builder.wrapBareColRefsInAnyValue(proj, ctx) 1507 } 1508 } 1509 1510 // FIXME: delete this when SINGLE join is ready 1511 if len(ctx.groups) == 0 && len(ctx.aggregates) > 0 { 1512 ctx.hasSingleRow = true 1513 } 1514 1515 // append AGG node 1516 if len(ctx.groups) > 0 || len(ctx.aggregates) > 0 { 1517 nodeID = builder.appendNode(&plan.Node{ 1518 NodeType: plan.Node_AGG, 1519 Children: []int32{nodeID}, 1520 GroupBy: ctx.groups, 1521 AggList: ctx.aggregates, 1522 BindingTags: []int32{ctx.groupTag, ctx.aggregateTag}, 1523 }, ctx) 1524 1525 if len(havingList) > 0 { 1526 var newFilterList []*plan.Expr 1527 var expr *plan.Expr 1528 1529 for _, cond := range havingList { 1530 nodeID, expr, err = builder.flattenSubqueries(nodeID, cond, ctx) 1531 if err != nil { 1532 return 0, err 1533 } 1534 1535 newFilterList = append(newFilterList, expr) 1536 } 1537 1538 nodeID = builder.appendNode(&plan.Node{ 1539 NodeType: plan.Node_FILTER, 1540 Children: []int32{nodeID}, 1541 FilterList: newFilterList, 1542 }, ctx) 1543 } 1544 1545 for name, id := range ctx.groupByAst { 1546 builder.nameByColRef[[2]int32{ctx.groupTag, id}] = name 1547 } 1548 1549 for name, id := range ctx.aggregateByAst { 1550 builder.nameByColRef[[2]int32{ctx.aggregateTag, id}] = name 1551 } 1552 } 1553 1554 // append PROJECT node 1555 for i, proj := range ctx.projects { 1556 nodeID, proj, err = builder.flattenSubqueries(nodeID, proj, ctx) 1557 if err != nil { 1558 return 0, err 1559 } 1560 1561 ctx.projects[i] = proj 1562 } 1563 1564 nodeID = builder.appendNode(&plan.Node{ 1565 NodeType: plan.Node_PROJECT, 1566 ProjectList: ctx.projects, 1567 Children: []int32{nodeID}, 1568 BindingTags: []int32{ctx.projectTag}, 1569 }, ctx) 1570 1571 // append DISTINCT node 1572 if ctx.isDistinct { 1573 nodeID = builder.appendNode(&plan.Node{ 1574 NodeType: plan.Node_DISTINCT, 1575 Children: []int32{nodeID}, 1576 }, ctx) 1577 } 1578 1579 // append SORT node (include limit, offset) 1580 if len(orderBys) > 0 { 1581 nodeID = builder.appendNode(&plan.Node{ 1582 NodeType: plan.Node_SORT, 1583 Children: []int32{nodeID}, 1584 OrderBy: orderBys, 1585 }, ctx) 1586 } 1587 1588 if limitExpr != nil || offsetExpr != nil { 1589 node := builder.qry.Nodes[nodeID] 1590 1591 node.Limit = limitExpr 1592 node.Offset = offsetExpr 1593 } 1594 1595 // append result PROJECT node 1596 if builder.qry.Nodes[nodeID].NodeType != plan.Node_PROJECT { 1597 for i := 0; i < resultLen; i++ { 1598 ctx.results = append(ctx.results, &plan.Expr{ 1599 Typ: ctx.projects[i].Typ, 1600 Expr: &plan.Expr_Col{ 1601 Col: &plan.ColRef{ 1602 RelPos: ctx.projectTag, 1603 ColPos: int32(i), 1604 }, 1605 }, 1606 }) 1607 } 1608 1609 ctx.resultTag = builder.genNewTag() 1610 1611 nodeID = builder.appendNode(&plan.Node{ 1612 NodeType: plan.Node_PROJECT, 1613 ProjectList: ctx.results, 1614 Children: []int32{nodeID}, 1615 BindingTags: []int32{ctx.resultTag}, 1616 }, ctx) 1617 } else { 1618 ctx.results = ctx.projects 1619 } 1620 1621 if isRoot { 1622 builder.qry.Headings = append(builder.qry.Headings, ctx.headings...) 1623 } 1624 1625 return nodeID, nil 1626 } 1627 1628 func (builder *QueryBuilder) appendNode(node *plan.Node, ctx *BindContext) int32 { 1629 nodeID := int32(len(builder.qry.Nodes)) 1630 node.NodeId = nodeID 1631 builder.qry.Nodes = append(builder.qry.Nodes, node) 1632 builder.ctxByNode = append(builder.ctxByNode, ctx) 1633 ReCalcNodeStats(nodeID, builder, false) 1634 return nodeID 1635 } 1636 1637 func (builder *QueryBuilder) rewriteRightJoinToLeftJoin(nodeID int32) { 1638 node := builder.qry.Nodes[nodeID] 1639 if node.NodeType == plan.Node_JOIN { 1640 builder.rewriteRightJoinToLeftJoin(node.Children[0]) 1641 builder.rewriteRightJoinToLeftJoin(node.Children[1]) 1642 1643 if node.JoinType == plan.Node_RIGHT { 1644 node.JoinType = plan.Node_LEFT 1645 node.Children = []int32{node.Children[1], node.Children[0]} 1646 } 1647 } else if len(node.Children) > 0 { 1648 builder.rewriteRightJoinToLeftJoin(node.Children[0]) 1649 } 1650 } 1651 1652 func (builder *QueryBuilder) buildFrom(stmt tree.TableExprs, ctx *BindContext) (int32, error) { 1653 if len(stmt) == 1 { 1654 return builder.buildTable(stmt[0], ctx) 1655 } 1656 return 0, moerr.NewInternalError(ctx.binder.GetContext(), "stmt's length should be zero") 1657 // for now, stmt'length always be zero. if someday that change in parser, you should uncomment these codes 1658 // leftCtx := NewBindContext(builder, ctx) 1659 // leftChildID, err := builder.buildTable(stmt[0], leftCtx) 1660 // if err != nil { 1661 // return 0, err 1662 // } 1663 1664 // for i := 1; i < len(stmt); i++ { 1665 // rightCtx := NewBindContext(builder, ctx) 1666 // rightChildID, err := builder.buildTable(stmt[i], rightCtx) 1667 // if err != nil { 1668 // return 0, err 1669 // } 1670 1671 // leftChildID = builder.appendNode(&plan.Node{ 1672 // NodeType: plan.Node_JOIN, 1673 // Children: []int32{leftChildID, rightChildID}, 1674 // JoinType: plan.Node_INNER, 1675 // }, nil) 1676 1677 // if i == len(stmt)-1 { 1678 // builder.ctxByNode[leftChildID] = ctx 1679 // err = ctx.mergeContexts(leftCtx, rightCtx) 1680 // if err != nil { 1681 // return 0, err 1682 // } 1683 // } else { 1684 // newCtx := NewBindContext(builder, ctx) 1685 // builder.ctxByNode[leftChildID] = newCtx 1686 // err = newCtx.mergeContexts(leftCtx, rightCtx) 1687 // if err != nil { 1688 // return 0, err 1689 // } 1690 // leftCtx = newCtx 1691 // } 1692 // } 1693 1694 // return leftChildID, err 1695 } 1696 1697 func (builder *QueryBuilder) buildTable(stmt tree.TableExpr, ctx *BindContext) (nodeID int32, err error) { 1698 switch tbl := stmt.(type) { 1699 case *tree.Select: 1700 subCtx := NewBindContext(builder, ctx) 1701 nodeID, err = builder.buildSelect(tbl, subCtx, false) 1702 if subCtx.isCorrelated { 1703 return 0, moerr.NewNYI(builder.GetContext(), "correlated subquery in FROM clause") 1704 } 1705 1706 if subCtx.hasSingleRow { 1707 ctx.hasSingleRow = true 1708 } 1709 1710 case *tree.TableName: 1711 schema := string(tbl.SchemaName) 1712 table := string(tbl.ObjectName) 1713 if len(table) == 0 || table == "dual" { //special table name 1714 nodeID = builder.appendNode(&plan.Node{ 1715 NodeType: plan.Node_VALUE_SCAN, 1716 }, ctx) 1717 1718 ctx.hasSingleRow = true 1719 1720 break 1721 } 1722 1723 if len(schema) == 0 { 1724 cteRef := ctx.findCTE(table) 1725 if cteRef != nil { 1726 subCtx := NewBindContext(builder, ctx) 1727 subCtx.maskedCTEs = cteRef.maskedCTEs 1728 subCtx.cteName = table 1729 //reset defaultDatabase 1730 if len(cteRef.defaultDatabase) > 0 { 1731 subCtx.defaultDatabase = cteRef.defaultDatabase 1732 } 1733 1734 switch stmt := cteRef.ast.Stmt.(type) { 1735 case *tree.Select: 1736 nodeID, err = builder.buildSelect(stmt, subCtx, false) 1737 1738 case *tree.ParenSelect: 1739 nodeID, err = builder.buildSelect(stmt.Select, subCtx, false) 1740 1741 default: 1742 err = moerr.NewParseError(builder.GetContext(), "unexpected statement: '%v'", tree.String(stmt, dialect.MYSQL)) 1743 } 1744 1745 if err != nil { 1746 return 1747 } 1748 1749 if subCtx.hasSingleRow { 1750 ctx.hasSingleRow = true 1751 } 1752 1753 cols := cteRef.ast.Name.Cols 1754 1755 if len(cols) > len(subCtx.headings) { 1756 return 0, moerr.NewSyntaxError(builder.GetContext(), "table %q has %d columns available but %d columns specified", table, len(subCtx.headings), len(cols)) 1757 } 1758 1759 for i, col := range cols { 1760 subCtx.headings[i] = string(col) 1761 } 1762 1763 break 1764 } 1765 schema = ctx.defaultDatabase 1766 } 1767 1768 obj, tableDef := builder.compCtx.Resolve(schema, table) 1769 if tableDef == nil { 1770 return 0, moerr.NewParseError(builder.GetContext(), "table %q does not exist", table) 1771 } 1772 1773 tableDef.Name2ColIndex = map[string]int32{} 1774 for i := 0; i < len(tableDef.Cols); i++ { 1775 tableDef.Name2ColIndex[tableDef.Cols[i].Name] = int32(i) 1776 } 1777 nodeType := plan.Node_TABLE_SCAN 1778 if tableDef.TableType == catalog.SystemExternalRel { 1779 nodeType = plan.Node_EXTERNAL_SCAN 1780 col := &ColDef{ 1781 Name: catalog.ExternalFilePath, 1782 Typ: &plan.Type{ 1783 Id: int32(types.T_varchar), 1784 Width: types.MaxVarcharLen, 1785 Table: table, 1786 }, 1787 } 1788 tableDef.Cols = append(tableDef.Cols, col) 1789 } else if tableDef.TableType == catalog.SystemViewRel { 1790 if yes, dbOfView, nameOfView := builder.compCtx.GetBuildingAlterView(); yes { 1791 currentDB := schema 1792 if currentDB == "" { 1793 currentDB = builder.compCtx.DefaultDatabase() 1794 } 1795 if dbOfView == currentDB && nameOfView == table { 1796 return 0, moerr.NewInternalError(builder.GetContext(), "there is a recursive reference to the view %s", nameOfView) 1797 } 1798 } 1799 // set view statment to CTE 1800 viewDefString := tableDef.ViewSql.View 1801 1802 if viewDefString != "" { 1803 if ctx.cteByName == nil { 1804 ctx.cteByName = make(map[string]*CTERef) 1805 } 1806 1807 viewData := ViewData{} 1808 err := json.Unmarshal([]byte(viewDefString), &viewData) 1809 if err != nil { 1810 return 0, err 1811 } 1812 1813 originStmts, err := mysql.Parse(builder.GetContext(), viewData.Stmt) 1814 if err != nil { 1815 return 0, err 1816 } 1817 viewStmt, ok := originStmts[0].(*tree.CreateView) 1818 1819 // No createview stmt, check alterview stmt. 1820 if !ok { 1821 alterstmt, ok := originStmts[0].(*tree.AlterView) 1822 viewStmt = &tree.CreateView{} 1823 if !ok { 1824 return 0, moerr.NewParseError(builder.GetContext(), "can not get view statement") 1825 } 1826 viewStmt.Name = alterstmt.Name 1827 viewStmt.ColNames = alterstmt.ColNames 1828 viewStmt.AsSource = alterstmt.AsSource 1829 } 1830 1831 viewName := viewStmt.Name.ObjectName 1832 var maskedCTEs map[string]any 1833 if len(ctx.cteByName) > 0 { 1834 maskedCTEs = make(map[string]any) 1835 for name := range ctx.cteByName { 1836 maskedCTEs[name] = nil 1837 } 1838 } 1839 1840 ctx.cteByName[string(viewName)] = &CTERef{ 1841 ast: &tree.CTE{ 1842 Name: &tree.AliasClause{ 1843 Alias: viewName, 1844 Cols: viewStmt.ColNames, 1845 }, 1846 Stmt: viewStmt.AsSource, 1847 }, 1848 defaultDatabase: viewData.DefaultDatabase, 1849 maskedCTEs: maskedCTEs, 1850 } 1851 1852 newTableName := tree.NewTableName(viewName, tree.ObjectNamePrefix{ 1853 CatalogName: tbl.CatalogName, // TODO unused now, if used in some code, that will be save in view 1854 SchemaName: tree.Identifier(""), 1855 ExplicitCatalog: false, 1856 ExplicitSchema: false, 1857 }) 1858 return builder.buildTable(newTableName, ctx) 1859 } 1860 } 1861 1862 nodeID = builder.appendNode(&plan.Node{ 1863 NodeType: nodeType, 1864 Stats: nil, 1865 ObjRef: obj, 1866 TableDef: tableDef, 1867 BindingTags: []int32{builder.genNewTag()}, 1868 }, ctx) 1869 1870 case *tree.JoinTableExpr: 1871 if tbl.Right == nil { 1872 return builder.buildTable(tbl.Left, ctx) 1873 } 1874 return builder.buildJoinTable(tbl, ctx) 1875 1876 case *tree.TableFunction: 1877 if tbl.Id() == "result_scan" { 1878 return builder.buildResultScan(tbl, ctx) 1879 } 1880 return builder.buildTableFunction(tbl, ctx) 1881 1882 case *tree.ParenTableExpr: 1883 return builder.buildTable(tbl.Expr, ctx) 1884 1885 case *tree.AliasedTableExpr: //allways AliasedTableExpr first 1886 if _, ok := tbl.Expr.(*tree.Select); ok { 1887 if tbl.As.Alias == "" { 1888 return 0, moerr.NewSyntaxError(builder.GetContext(), "subquery in FROM must have an alias: %T", stmt) 1889 } 1890 } 1891 1892 nodeID, err = builder.buildTable(tbl.Expr, ctx) 1893 if err != nil { 1894 return 1895 } 1896 1897 err = builder.addBinding(nodeID, tbl.As, ctx) 1898 1899 //tableDef := builder.qry.Nodes[nodeID].GetTableDef() 1900 midNode := builder.qry.Nodes[nodeID] 1901 //if it is the non-sys account and reads the cluster table, 1902 //we add an account_id filter to make sure that the non-sys account 1903 //can only read its own data. 1904 if midNode.NodeType == plan.Node_TABLE_SCAN && builder.compCtx.GetAccountId() != catalog.System_Account { 1905 // add account filter for system table scan 1906 dbName := midNode.ObjRef.SchemaName 1907 tableName := midNode.TableDef.Name 1908 currentAccountId := builder.compCtx.GetAccountId() 1909 if dbName == catalog.MO_CATALOG && tableName == catalog.MO_DATABASE { 1910 modatabaseFilter := util.BuildMoDataBaseFilter(uint64(currentAccountId)) 1911 ctx.binder = NewWhereBinder(builder, ctx) 1912 accountFilterExprs, err := splitAndBindCondition(modatabaseFilter, ctx) 1913 if err != nil { 1914 return 0, err 1915 } 1916 builder.qry.Nodes[nodeID].FilterList = accountFilterExprs 1917 } else if dbName == catalog.MO_CATALOG && tableName == catalog.MO_TABLES { 1918 motablesFilter := util.BuildMoTablesFilter(uint64(currentAccountId)) 1919 ctx.binder = NewWhereBinder(builder, ctx) 1920 accountFilterExprs, err := splitAndBindCondition(motablesFilter, ctx) 1921 if err != nil { 1922 return 0, err 1923 } 1924 builder.qry.Nodes[nodeID].FilterList = accountFilterExprs 1925 } else if dbName == catalog.MO_CATALOG && tableName == catalog.MO_COLUMNS { 1926 moColumnsFilter := util.BuildMoColumnsFilter(uint64(currentAccountId)) 1927 ctx.binder = NewWhereBinder(builder, ctx) 1928 accountFilterExprs, err := splitAndBindCondition(moColumnsFilter, ctx) 1929 if err != nil { 1930 return 0, err 1931 } 1932 builder.qry.Nodes[nodeID].FilterList = accountFilterExprs 1933 } else if util.TableIsClusterTable(midNode.GetTableDef().GetTableType()) { 1934 ctx.binder = NewWhereBinder(builder, ctx) 1935 left := &tree.UnresolvedName{ 1936 NumParts: 1, 1937 Parts: tree.NameParts{util.GetClusterTableAttributeName()}, 1938 } 1939 currentAccountId := builder.compCtx.GetAccountId() 1940 right := tree.NewNumVal(constant.MakeUint64(uint64(currentAccountId)), strconv.Itoa(int(currentAccountId)), false) 1941 right.ValType = tree.P_uint64 1942 //account_id = the accountId of the non-sys account 1943 accountFilter := &tree.ComparisonExpr{ 1944 Op: tree.EQUAL, 1945 Left: left, 1946 Right: right, 1947 } 1948 accountFilterExprs, err := splitAndBindCondition(accountFilter, ctx) 1949 if err != nil { 1950 return 0, err 1951 } 1952 builder.qry.Nodes[nodeID].FilterList = accountFilterExprs 1953 } 1954 } 1955 return 1956 case *tree.StatementSource: 1957 return 0, moerr.NewParseError(builder.GetContext(), "unsupport table expr: %T", stmt) 1958 1959 default: 1960 // Values table not support 1961 return 0, moerr.NewParseError(builder.GetContext(), "unsupport table expr: %T", stmt) 1962 } 1963 1964 return 1965 } 1966 1967 func (builder *QueryBuilder) genNewTag() int32 { 1968 builder.nextTag++ 1969 return builder.nextTag 1970 } 1971 1972 func (builder *QueryBuilder) addBinding(nodeID int32, alias tree.AliasClause, ctx *BindContext) error { 1973 node := builder.qry.Nodes[nodeID] 1974 1975 var cols []string 1976 var types []*plan.Type 1977 var binding *Binding 1978 var table string 1979 1980 if node.NodeType == plan.Node_TABLE_SCAN || node.NodeType == plan.Node_MATERIAL_SCAN || node.NodeType == plan.Node_EXTERNAL_SCAN || node.NodeType == plan.Node_FUNCTION_SCAN || node.NodeType == plan.Node_VALUE_SCAN { 1981 if node.NodeType == plan.Node_VALUE_SCAN && node.TableDef == nil { 1982 return nil 1983 } 1984 if len(alias.Cols) > len(node.TableDef.Cols) { 1985 return moerr.NewSyntaxError(builder.GetContext(), "table %q has %d columns available but %d columns specified", alias.Alias, len(node.TableDef.Cols), len(alias.Cols)) 1986 } 1987 1988 if alias.Alias != "" { 1989 table = string(alias.Alias) 1990 } else { 1991 if node.NodeType == plan.Node_FUNCTION_SCAN { 1992 return moerr.NewSyntaxError(builder.GetContext(), "Every table function must have an alias") 1993 } 1994 1995 table = node.TableDef.Name 1996 } 1997 1998 if _, ok := ctx.bindingByTable[table]; ok { 1999 return moerr.NewSyntaxError(builder.GetContext(), "table name %q specified more than once", table) 2000 } 2001 2002 cols = make([]string, len(node.TableDef.Cols)) 2003 types = make([]*plan.Type, len(node.TableDef.Cols)) 2004 2005 tag := node.BindingTags[0] 2006 2007 for i, col := range node.TableDef.Cols { 2008 if i < len(alias.Cols) { 2009 cols[i] = string(alias.Cols[i]) 2010 } else { 2011 cols[i] = col.Name 2012 } 2013 types[i] = col.Typ 2014 name := table + "." + cols[i] 2015 builder.nameByColRef[[2]int32{tag, int32(i)}] = name 2016 } 2017 2018 binding = NewBinding(tag, nodeID, table, cols, types, util.TableIsClusterTable(node.TableDef.TableType)) 2019 } else { 2020 // Subquery 2021 subCtx := builder.ctxByNode[nodeID] 2022 tag := subCtx.rootTag() 2023 headings := subCtx.headings 2024 projects := subCtx.projects 2025 2026 if len(alias.Cols) > len(headings) { 2027 return moerr.NewSyntaxError(builder.GetContext(), "11111 table %q has %d columns available but %d columns specified", alias.Alias, len(headings), len(alias.Cols)) 2028 } 2029 2030 table = subCtx.cteName 2031 if len(alias.Alias) > 0 { 2032 table = string(alias.Alias) 2033 } 2034 if len(table) == 0 { 2035 table = fmt.Sprintf("mo_table_subquery_alias_%d", tag) 2036 } 2037 if _, ok := ctx.bindingByTable[table]; ok { 2038 return moerr.NewSyntaxError(builder.GetContext(), "table name %q specified more than once", table) 2039 } 2040 2041 cols = make([]string, len(headings)) 2042 types = make([]*plan.Type, len(headings)) 2043 2044 for i, col := range headings { 2045 if i < len(alias.Cols) { 2046 cols[i] = string(alias.Cols[i]) 2047 } else { 2048 cols[i] = col 2049 } 2050 types[i] = projects[i].Typ 2051 2052 name := table + "." + cols[i] 2053 builder.nameByColRef[[2]int32{tag, int32(i)}] = name 2054 } 2055 2056 binding = NewBinding(tag, nodeID, table, cols, types, false) 2057 } 2058 2059 ctx.bindings = append(ctx.bindings, binding) 2060 ctx.bindingByTag[binding.tag] = binding 2061 ctx.bindingByTable[binding.table] = binding 2062 2063 for _, col := range binding.cols { 2064 if _, ok := ctx.bindingByCol[col]; ok { 2065 ctx.bindingByCol[col] = nil 2066 } else { 2067 ctx.bindingByCol[col] = binding 2068 } 2069 } 2070 2071 ctx.bindingTree = &BindingTreeNode{ 2072 binding: binding, 2073 } 2074 2075 return nil 2076 } 2077 2078 func (builder *QueryBuilder) buildJoinTable(tbl *tree.JoinTableExpr, ctx *BindContext) (int32, error) { 2079 var joinType plan.Node_JoinFlag 2080 2081 switch tbl.JoinType { 2082 case tree.JOIN_TYPE_CROSS, tree.JOIN_TYPE_INNER, tree.JOIN_TYPE_NATURAL: 2083 joinType = plan.Node_INNER 2084 case tree.JOIN_TYPE_LEFT, tree.JOIN_TYPE_NATURAL_LEFT: 2085 joinType = plan.Node_LEFT 2086 case tree.JOIN_TYPE_RIGHT, tree.JOIN_TYPE_NATURAL_RIGHT: 2087 joinType = plan.Node_RIGHT 2088 case tree.JOIN_TYPE_FULL: 2089 joinType = plan.Node_OUTER 2090 } 2091 2092 leftCtx := NewBindContext(builder, ctx) 2093 rightCtx := NewBindContext(builder, ctx) 2094 2095 leftChildID, err := builder.buildTable(tbl.Left, leftCtx) 2096 if err != nil { 2097 return 0, err 2098 } 2099 if _, ok := tbl.Right.(*tree.TableFunction); ok { 2100 return 0, moerr.NewSyntaxError(builder.GetContext(), "Every table function must have an alias") 2101 } 2102 if aliasedTblExpr, ok := tbl.Right.(*tree.AliasedTableExpr); ok { 2103 if tblFn, ok2 := aliasedTblExpr.Expr.(*tree.TableFunction); ok2 { 2104 err = buildTableFunctionStmt(tblFn, tbl.Left, leftCtx) 2105 if err != nil { 2106 return 0, err 2107 } 2108 } 2109 } 2110 2111 rightChildID, err := builder.buildTable(tbl.Right, rightCtx) 2112 if err != nil { 2113 return 0, err 2114 } 2115 2116 err = ctx.mergeContexts(builder.GetContext(), leftCtx, rightCtx) 2117 if err != nil { 2118 return 0, err 2119 } 2120 2121 nodeID := builder.appendNode(&plan.Node{ 2122 NodeType: plan.Node_JOIN, 2123 Children: []int32{leftChildID, rightChildID}, 2124 JoinType: joinType, 2125 }, ctx) 2126 node := builder.qry.Nodes[nodeID] 2127 2128 ctx.binder = NewTableBinder(builder, ctx) 2129 2130 switch cond := tbl.Cond.(type) { 2131 case *tree.OnJoinCond: 2132 joinConds, err := splitAndBindCondition(cond.Expr, ctx) 2133 if err != nil { 2134 return 0, err 2135 } 2136 2137 node.OnList = joinConds 2138 2139 case *tree.UsingJoinCond: 2140 for _, col := range cond.Cols { 2141 expr, err := ctx.addUsingCol(string(col), joinType, leftCtx, rightCtx) 2142 if err != nil { 2143 return 0, err 2144 } 2145 2146 node.OnList = append(node.OnList, expr) 2147 } 2148 2149 default: 2150 if tbl.JoinType == tree.JOIN_TYPE_NATURAL || tbl.JoinType == tree.JOIN_TYPE_NATURAL_LEFT || tbl.JoinType == tree.JOIN_TYPE_NATURAL_RIGHT { 2151 leftCols := make(map[string]any) 2152 for _, binding := range leftCtx.bindings { 2153 for _, col := range binding.cols { 2154 leftCols[col] = nil 2155 } 2156 } 2157 2158 var usingCols []string 2159 for _, binding := range rightCtx.bindings { 2160 for _, col := range binding.cols { 2161 if _, ok := leftCols[col]; ok { 2162 usingCols = append(usingCols, col) 2163 } 2164 } 2165 } 2166 2167 for _, col := range usingCols { 2168 expr, err := ctx.addUsingCol(col, joinType, leftCtx, rightCtx) 2169 if err != nil { 2170 return 0, err 2171 } 2172 2173 node.OnList = append(node.OnList, expr) 2174 } 2175 } 2176 } 2177 2178 return nodeID, nil 2179 } 2180 2181 func (builder *QueryBuilder) pushdownFilters(nodeID int32, filters []*plan.Expr) (int32, []*plan.Expr) { 2182 node := builder.qry.Nodes[nodeID] 2183 2184 var canPushdown, cantPushdown []*plan.Expr 2185 2186 switch node.NodeType { 2187 case plan.Node_AGG: 2188 groupTag := node.BindingTags[0] 2189 aggregateTag := node.BindingTags[1] 2190 2191 for _, filter := range filters { 2192 if !containsTag(filter, aggregateTag) { 2193 canPushdown = append(canPushdown, replaceColRefs(filter, groupTag, node.GroupBy)) 2194 } else { 2195 cantPushdown = append(cantPushdown, filter) 2196 } 2197 } 2198 2199 childID, cantPushdownChild := builder.pushdownFilters(node.Children[0], canPushdown) 2200 2201 if len(cantPushdownChild) > 0 { 2202 childID = builder.appendNode(&plan.Node{ 2203 NodeType: plan.Node_FILTER, 2204 Children: []int32{node.Children[0]}, 2205 FilterList: cantPushdownChild, 2206 }, nil) 2207 } 2208 2209 node.Children[0] = childID 2210 2211 case plan.Node_FILTER: 2212 canPushdown = filters 2213 for _, filter := range node.FilterList { 2214 canPushdown = append(canPushdown, splitPlanConjunction(applyDistributivity(builder.GetContext(), filter))...) 2215 } 2216 2217 childID, cantPushdownChild := builder.pushdownFilters(node.Children[0], canPushdown) 2218 2219 var extraFilters []*plan.Expr 2220 for _, filter := range cantPushdownChild { 2221 switch exprImpl := filter.Expr.(type) { 2222 case *plan.Expr_F: 2223 if exprImpl.F.Func.ObjName == "or" { 2224 keys := checkDNF(filter) 2225 for _, key := range keys { 2226 extraFilter := walkThroughDNF(builder.GetContext(), filter, key) 2227 if extraFilter != nil { 2228 extraFilters = append(extraFilters, DeepCopyExpr(extraFilter)) 2229 } 2230 } 2231 } 2232 } 2233 } 2234 builder.pushdownFilters(node.Children[0], extraFilters) 2235 2236 if len(cantPushdownChild) > 0 { 2237 node.Children[0] = childID 2238 node.FilterList = cantPushdownChild 2239 } else { 2240 nodeID = childID 2241 } 2242 2243 case plan.Node_JOIN: 2244 leftTags := make(map[int32]*Binding) 2245 for _, tag := range builder.enumerateTags(node.Children[0]) { 2246 leftTags[tag] = nil 2247 } 2248 2249 rightTags := make(map[int32]*Binding) 2250 for _, tag := range builder.enumerateTags(node.Children[1]) { 2251 rightTags[tag] = nil 2252 } 2253 2254 var markTag int32 2255 if node.JoinType == plan.Node_MARK { 2256 markTag = node.BindingTags[0] 2257 } 2258 2259 if node.JoinType == plan.Node_INNER { 2260 for _, cond := range node.OnList { 2261 filters = append(filters, splitPlanConjunction(applyDistributivity(builder.GetContext(), cond))...) 2262 } 2263 2264 node.OnList = nil 2265 } 2266 2267 var leftPushdown, rightPushdown []*plan.Expr 2268 var turnInner bool 2269 2270 joinSides := make([]int8, len(filters)) 2271 2272 for i, filter := range filters { 2273 canTurnInner := true 2274 2275 joinSides[i] = getJoinSide(filter, leftTags, rightTags, markTag) 2276 if f, ok := filter.Expr.(*plan.Expr_F); ok { 2277 for _, arg := range f.F.Args { 2278 if getJoinSide(arg, leftTags, rightTags, markTag) == JoinSideBoth { 2279 canTurnInner = false 2280 break 2281 } 2282 } 2283 } 2284 2285 if canTurnInner && node.JoinType == plan.Node_LEFT && joinSides[i]&JoinSideRight != 0 && rejectsNull(filter, builder.compCtx.GetProcess()) { 2286 for _, cond := range node.OnList { 2287 filters = append(filters, splitPlanConjunction(applyDistributivity(builder.GetContext(), cond))...) 2288 } 2289 2290 node.JoinType = plan.Node_INNER 2291 node.OnList = nil 2292 turnInner = true 2293 2294 break 2295 } 2296 2297 // TODO: FULL OUTER join should be handled here. However we don't have FULL OUTER join now. 2298 } 2299 2300 if turnInner { 2301 joinSides = make([]int8, len(filters)) 2302 2303 for i, filter := range filters { 2304 joinSides[i] = getJoinSide(filter, leftTags, rightTags, markTag) 2305 } 2306 } else if node.JoinType == plan.Node_LEFT { 2307 var newOnList []*plan.Expr 2308 for _, cond := range node.OnList { 2309 conj := splitPlanConjunction(applyDistributivity(builder.GetContext(), cond)) 2310 for _, conjElem := range conj { 2311 side := getJoinSide(conjElem, leftTags, rightTags, markTag) 2312 if side&JoinSideLeft == 0 { 2313 rightPushdown = append(rightPushdown, conjElem) 2314 } else { 2315 newOnList = append(newOnList, conjElem) 2316 } 2317 } 2318 } 2319 2320 node.OnList = newOnList 2321 } 2322 2323 for i, filter := range filters { 2324 switch joinSides[i] { 2325 case JoinSideNone: 2326 if c, ok := filter.Expr.(*plan.Expr_C); ok { 2327 if c, ok := c.C.Value.(*plan.Const_Bval); ok { 2328 if c.Bval { 2329 break 2330 } 2331 } 2332 } 2333 2334 switch node.JoinType { 2335 case plan.Node_INNER: 2336 leftPushdown = append(leftPushdown, DeepCopyExpr(filter)) 2337 rightPushdown = append(rightPushdown, filter) 2338 2339 case plan.Node_LEFT, plan.Node_SEMI, plan.Node_ANTI, plan.Node_SINGLE, plan.Node_MARK: 2340 leftPushdown = append(leftPushdown, filter) 2341 2342 default: 2343 cantPushdown = append(cantPushdown, filter) 2344 } 2345 2346 case JoinSideLeft: 2347 if node.JoinType != plan.Node_OUTER { 2348 leftPushdown = append(leftPushdown, filter) 2349 } else { 2350 cantPushdown = append(cantPushdown, filter) 2351 } 2352 2353 case JoinSideRight: 2354 if node.JoinType == plan.Node_INNER { 2355 rightPushdown = append(rightPushdown, filter) 2356 } else { 2357 cantPushdown = append(cantPushdown, filter) 2358 } 2359 2360 case JoinSideBoth: 2361 if node.JoinType == plan.Node_INNER { 2362 if f, ok := filter.Expr.(*plan.Expr_F); ok { 2363 if f.F.Func.ObjName == "=" { 2364 if getJoinSide(f.F.Args[0], leftTags, rightTags, markTag) != JoinSideBoth { 2365 if getJoinSide(f.F.Args[1], leftTags, rightTags, markTag) != JoinSideBoth { 2366 node.OnList = append(node.OnList, filter) 2367 break 2368 } 2369 } 2370 } 2371 } 2372 } 2373 2374 cantPushdown = append(cantPushdown, filter) 2375 2376 case JoinSideMark: 2377 if tryMark, ok := filter.Expr.(*plan.Expr_Col); ok { 2378 if tryMark.Col.RelPos == node.BindingTags[0] { 2379 node.JoinType = plan.Node_SEMI 2380 node.BindingTags = nil 2381 break 2382 } 2383 } else if fExpr, ok := filter.Expr.(*plan.Expr_F); ok { 2384 if filter.Typ.NotNullable && fExpr.F.Func.ObjName == "not" { 2385 arg := fExpr.F.Args[0] 2386 if tryMark, ok := arg.Expr.(*plan.Expr_Col); ok { 2387 if tryMark.Col.RelPos == node.BindingTags[0] { 2388 node.JoinType = plan.Node_ANTI 2389 node.BindingTags = nil 2390 break 2391 } 2392 } 2393 } 2394 } 2395 2396 cantPushdown = append(cantPushdown, filter) 2397 2398 default: 2399 cantPushdown = append(cantPushdown, filter) 2400 } 2401 } 2402 2403 if node.JoinType == plan.Node_INNER { 2404 //only inner join can deduce new predicate 2405 builder.pushdownFilters(node.Children[0], predsDeduction(rightPushdown, node.OnList)) 2406 builder.pushdownFilters(node.Children[1], predsDeduction(leftPushdown, node.OnList)) 2407 } 2408 2409 childID, cantPushdownChild := builder.pushdownFilters(node.Children[0], leftPushdown) 2410 2411 if len(cantPushdownChild) > 0 { 2412 childID = builder.appendNode(&plan.Node{ 2413 NodeType: plan.Node_FILTER, 2414 Children: []int32{node.Children[0]}, 2415 FilterList: cantPushdownChild, 2416 }, nil) 2417 } 2418 2419 node.Children[0] = childID 2420 2421 childID, cantPushdownChild = builder.pushdownFilters(node.Children[1], rightPushdown) 2422 2423 if len(cantPushdownChild) > 0 { 2424 childID = builder.appendNode(&plan.Node{ 2425 NodeType: plan.Node_FILTER, 2426 Children: []int32{node.Children[1]}, 2427 FilterList: cantPushdownChild, 2428 }, nil) 2429 } 2430 2431 node.Children[1] = childID 2432 2433 case plan.Node_UNION, plan.Node_UNION_ALL, plan.Node_MINUS, plan.Node_MINUS_ALL, plan.Node_INTERSECT, plan.Node_INTERSECT_ALL: 2434 leftChild := builder.qry.Nodes[node.Children[0]] 2435 rightChild := builder.qry.Nodes[node.Children[1]] 2436 var canPushDownRight []*plan.Expr 2437 2438 for _, filter := range filters { 2439 canPushdown = append(canPushdown, replaceColRefsForSet(DeepCopyExpr(filter), leftChild.ProjectList)) 2440 canPushDownRight = append(canPushDownRight, replaceColRefsForSet(filter, rightChild.ProjectList)) 2441 } 2442 2443 childID, cantPushdownChild := builder.pushdownFilters(node.Children[0], canPushdown) 2444 if len(cantPushdownChild) > 0 { 2445 childID = builder.appendNode(&plan.Node{ 2446 NodeType: plan.Node_FILTER, 2447 Children: []int32{node.Children[0]}, 2448 FilterList: cantPushdownChild, 2449 }, nil) 2450 } 2451 node.Children[0] = childID 2452 2453 childID, cantPushdownChild = builder.pushdownFilters(node.Children[1], canPushDownRight) 2454 if len(cantPushdownChild) > 0 { 2455 childID = builder.appendNode(&plan.Node{ 2456 NodeType: plan.Node_FILTER, 2457 Children: []int32{node.Children[1]}, 2458 FilterList: cantPushdownChild, 2459 }, nil) 2460 } 2461 node.Children[1] = childID 2462 2463 case plan.Node_PROJECT: 2464 child := builder.qry.Nodes[node.Children[0]] 2465 if (child.NodeType == plan.Node_VALUE_SCAN || child.NodeType == plan.Node_EXTERNAL_SCAN) && child.RowsetData == nil { 2466 cantPushdown = filters 2467 break 2468 } 2469 2470 projectTag := node.BindingTags[0] 2471 2472 for _, filter := range filters { 2473 canPushdown = append(canPushdown, replaceColRefs(filter, projectTag, node.ProjectList)) 2474 } 2475 2476 childID, cantPushdownChild := builder.pushdownFilters(node.Children[0], canPushdown) 2477 2478 if len(cantPushdownChild) > 0 { 2479 childID = builder.appendNode(&plan.Node{ 2480 NodeType: plan.Node_FILTER, 2481 Children: []int32{node.Children[0]}, 2482 FilterList: cantPushdownChild, 2483 }, nil) 2484 } 2485 2486 node.Children[0] = childID 2487 2488 case plan.Node_TABLE_SCAN, plan.Node_EXTERNAL_SCAN: 2489 node.FilterList = append(node.FilterList, filters...) 2490 case plan.Node_FUNCTION_SCAN: 2491 node.FilterList = append(node.FilterList, filters...) 2492 childId := node.Children[0] 2493 childId, err := builder.pushdownFilters(childId, nil) 2494 if err != nil { 2495 return 0, err 2496 } 2497 node.Children[0] = childId 2498 2499 default: 2500 if len(node.Children) > 0 { 2501 childID, cantPushdownChild := builder.pushdownFilters(node.Children[0], filters) 2502 2503 if len(cantPushdownChild) > 0 { 2504 childID = builder.appendNode(&plan.Node{ 2505 NodeType: plan.Node_FILTER, 2506 Children: []int32{node.Children[0]}, 2507 FilterList: cantPushdownChild, 2508 }, nil) 2509 } 2510 2511 node.Children[0] = childID 2512 } else { 2513 cantPushdown = filters 2514 } 2515 } 2516 2517 return nodeID, cantPushdown 2518 } 2519 2520 func (builder *QueryBuilder) buildTableFunction(tbl *tree.TableFunction, ctx *BindContext) (int32, error) { 2521 var ( 2522 childId int32 = -1 2523 err error 2524 nodeId int32 2525 ) 2526 if tbl.SelectStmt != nil { 2527 childId, err = builder.buildSelect(tbl.SelectStmt, ctx, false) 2528 if err != nil { 2529 return 0, err 2530 } 2531 } 2532 if childId == -1 { 2533 scanNode := &plan.Node{ 2534 NodeType: plan.Node_VALUE_SCAN, 2535 } 2536 childId = builder.appendNode(scanNode, ctx) 2537 } 2538 ctx.binder = NewTableBinder(builder, ctx) 2539 exprs := make([]*plan.Expr, 0, len(tbl.Func.Exprs)) 2540 for _, v := range tbl.Func.Exprs { 2541 curExpr, err := ctx.binder.BindExpr(v, 0, false) 2542 if err != nil { 2543 return 0, err 2544 } 2545 exprs = append(exprs, curExpr) 2546 } 2547 id := tbl.Id() 2548 switch id { 2549 case "unnest": 2550 nodeId, err = builder.buildUnnest(tbl, ctx, exprs, childId) 2551 case "generate_series": 2552 nodeId = builder.buildGenerateSeries(tbl, ctx, exprs, childId) 2553 case "meta_scan": 2554 nodeId, err = builder.buildMetaScan(tbl, ctx, exprs, childId) 2555 case "current_account": 2556 nodeId, err = builder.buildCurrentAccount(tbl, ctx, exprs, childId) 2557 default: 2558 err = moerr.NewNotSupported(builder.GetContext(), "table function '%s' not supported", id) 2559 } 2560 clearBinding(ctx) 2561 return nodeId, err 2562 } 2563 2564 func (builder *QueryBuilder) GetContext() context.Context { 2565 if builder == nil { 2566 return context.TODO() 2567 } 2568 return builder.compCtx.GetContext() 2569 }