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  }