github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/plan/visit_plan.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 20 "github.com/matrixorigin/matrixone/pkg/container/types" 21 "github.com/matrixorigin/matrixone/pkg/pb/plan" 22 ) 23 24 type VisitPlanRule interface { 25 MatchNode(*Node) bool 26 IsApplyExpr() bool 27 ApplyNode(*Node) error 28 ApplyExpr(*Expr) (*Expr, error) 29 } 30 31 type VisitPlan struct { 32 plan *Plan 33 isUpdatePlan bool 34 rules []VisitPlanRule 35 } 36 37 func NewVisitPlan(pl *Plan, rules []VisitPlanRule) *VisitPlan { 38 return &VisitPlan{ 39 plan: pl, 40 isUpdatePlan: false, 41 rules: rules, 42 } 43 } 44 45 func (vq *VisitPlan) visitNode(ctx context.Context, qry *Query, node *Node, idx int32) error { 46 for i := range node.Children { 47 if err := vq.visitNode(ctx, qry, qry.Nodes[node.Children[i]], node.Children[i]); err != nil { 48 return err 49 } 50 } 51 52 for _, rule := range vq.rules { 53 if rule.MatchNode(node) { 54 err := rule.ApplyNode(node) 55 if err != nil { 56 return err 57 } 58 } else if rule.IsApplyExpr() { 59 err := vq.exploreNode(ctx, rule, node, idx) 60 if err != nil { 61 return err 62 } 63 } 64 } 65 66 return nil 67 } 68 69 func (vq *VisitPlan) exploreNode(ctx context.Context, rule VisitPlanRule, node *Node, idx int32) error { 70 var err error 71 if node.Limit != nil { 72 node.Limit, err = rule.ApplyExpr(node.Limit) 73 if err != nil { 74 return err 75 } 76 } 77 78 if node.Offset != nil { 79 node.Offset, err = rule.ApplyExpr(node.Offset) 80 if err != nil { 81 return err 82 } 83 } 84 85 for i := range node.OnList { 86 node.OnList[i], err = rule.ApplyExpr(node.OnList[i]) 87 if err != nil { 88 return err 89 } 90 } 91 92 for i := range node.FilterList { 93 node.FilterList[i], err = rule.ApplyExpr(node.FilterList[i]) 94 if err != nil { 95 return err 96 } 97 } 98 99 for i := range node.OrderBy { 100 node.OrderBy[i].Expr, err = rule.ApplyExpr(node.OrderBy[i].Expr) 101 if err != nil { 102 return err 103 } 104 } 105 106 for i := range node.BlockFilterList { 107 node.BlockFilterList[i], err = rule.ApplyExpr(node.BlockFilterList[i]) 108 if err != nil { 109 return err 110 } 111 } 112 113 if node.OnUpdateExprs != nil { 114 for i := range node.OnUpdateExprs { 115 node.OnUpdateExprs[i], err = rule.ApplyExpr(node.OnUpdateExprs[i]) 116 if err != nil { 117 return err 118 } 119 } 120 } 121 122 typ := types.New(types.T_varchar, 65000, 0) 123 toTyp := makePlan2Type(&typ) 124 targetTyp := &plan.Expr{ 125 Typ: toTyp, 126 Expr: &plan.Expr_T{ 127 T: &plan.TargetType{}, 128 }, 129 } 130 131 applyAndResetType := func(e *Expr) (*Expr, error) { 132 oldType := e.Typ 133 e, err = rule.ApplyExpr(e) 134 if err != nil { 135 return nil, err 136 } 137 if (oldType.Id == int32(types.T_float32) || oldType.Id == int32(types.T_float64)) && (e.Typ.Id == int32(types.T_decimal64) || e.Typ.Id == int32(types.T_decimal128)) { 138 e, err = forceCastExpr2(ctx, e, typ, targetTyp) 139 if err != nil { 140 return nil, err 141 } 142 } 143 return forceCastExpr(ctx, e, oldType) 144 } 145 146 if node.RowsetData != nil { 147 for i := range node.RowsetData.Cols { 148 for j := range node.RowsetData.Cols[i].Data { 149 node.RowsetData.Cols[i].Data[j].Expr, err = applyAndResetType(node.RowsetData.Cols[i].Data[j].Expr) 150 if err != nil { 151 return err 152 } 153 } 154 } 155 } 156 157 for i := range node.ProjectList { 158 if vq.isUpdatePlan { 159 node.ProjectList[i], err = applyAndResetType(node.ProjectList[i]) 160 161 } else { 162 node.ProjectList[i], err = rule.ApplyExpr(node.ProjectList[i]) 163 164 } 165 if err != nil { 166 return err 167 } 168 } 169 170 return nil 171 } 172 173 func (vq *VisitPlan) Visit(ctx context.Context) error { 174 switch pl := vq.plan.Plan.(type) { 175 case *Plan_Query: 176 qry := pl.Query 177 vq.isUpdatePlan = (pl.Query.StmtType == plan.Query_UPDATE) 178 179 if len(qry.Steps) == 0 { 180 return nil 181 } 182 183 for _, step := range qry.Steps { 184 err := vq.visitNode(ctx, qry, qry.Nodes[step], step) 185 if err != nil { 186 return err 187 } 188 } 189 190 default: 191 // do nothing 192 193 } 194 195 return nil 196 }