github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/plan/message.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 "github.com/matrixorigin/matrixone/pkg/pb/plan" 19 "github.com/matrixorigin/matrixone/pkg/vm/process" 20 ) 21 22 func (builder *QueryBuilder) gatherLeavesForMessageFromTopToScan(nodeID int32) int32 { 23 node := builder.qry.Nodes[nodeID] 24 switch node.NodeType { 25 case plan.Node_JOIN: 26 if node.JoinType == plan.Node_INNER || node.JoinType == plan.Node_SEMI { 27 // for now, only support inner join and semi join. 28 // for left join, top operator can directly push down over this 29 return builder.gatherLeavesForMessageFromTopToScan(node.Children[0]) 30 } 31 case plan.Node_FILTER: 32 return builder.gatherLeavesForMessageFromTopToScan(node.Children[0]) 33 case plan.Node_TABLE_SCAN: 34 return nodeID 35 } 36 return -1 37 } 38 39 // send message from top to scan. if block node(like group or window), no need to send this message 40 func (builder *QueryBuilder) handleMessgaeFromTopToScan(nodeID int32) { 41 if builder.optimizerHints != nil && builder.optimizerHints.sendMessageFromTopToScan != 0 { 42 return 43 } 44 node := builder.qry.Nodes[nodeID] 45 if len(node.Children) > 0 { 46 for _, child := range node.Children { 47 builder.handleMessgaeFromTopToScan(child) 48 } 49 } 50 if node.NodeType != plan.Node_SORT { 51 return 52 } 53 if node.Limit == nil { 54 return 55 } 56 if len(node.OrderBy) > 1 { 57 // for now ,only support order by one column 58 return 59 } 60 scanID := builder.gatherLeavesForMessageFromTopToScan(node.Children[0]) 61 if scanID == -1 { 62 return 63 } 64 orderByCol, ok := node.OrderBy[0].Expr.Expr.(*plan.Expr_Col) 65 if !ok { 66 return 67 } 68 scanNode := builder.qry.Nodes[scanID] 69 if len(scanNode.OrderBy) != 0 { 70 panic("orderby in scannode should be nil!") 71 } 72 if orderByCol.Col.RelPos != scanNode.BindingTags[0] { 73 return 74 } 75 if scanNode.Stats.BlockNum < 64 { 76 return 77 } 78 if GetSortOrder(scanNode.TableDef, orderByCol.Col.ColPos) != 0 { 79 return 80 } 81 82 msgTag := builder.genNewMsgTag() 83 msgHeader := &plan.MsgHeader{MsgTag: msgTag, MsgType: int32(process.MsgTopValue)} 84 node.SendMsgList = append(node.SendMsgList, msgHeader) 85 scanNode.RecvMsgList = append(scanNode.RecvMsgList, msgHeader) 86 scanNode.OrderBy = append(scanNode.OrderBy, DeepCopyOrderBy(node.OrderBy[0])) 87 } 88 89 func (builder *QueryBuilder) handleMessgaes(nodeID int32) { 90 builder.handleMessgaeFromTopToScan(nodeID) 91 }