github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/tidb/ast/flag.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 ast
    15  
    16  const preEvaluable = FlagHasParamMarker | FlagHasFunc | FlagHasVariable | FlagHasDefault | FlagPreEvaluated
    17  
    18  // IsPreEvaluable checks if the expression can be evaluated before execution.
    19  func IsPreEvaluable(expr ExprNode) bool {
    20  	return expr.GetFlag()|preEvaluable == preEvaluable
    21  }
    22  
    23  // ResetEvaluatedFlag resets the evaluated flag.
    24  func ResetEvaluatedFlag(n Node) {
    25  	var reseter preEvaluatedReseter
    26  	n.Accept(&reseter)
    27  }
    28  
    29  func resetEvaluatedExpr(expr ExprNode) {
    30  	expr.SetFlag(expr.GetFlag() &^ FlagPreEvaluated)
    31  }
    32  
    33  // IsEvaluated checks if the expression are evaluated and needn't be evaluated any more.
    34  func IsEvaluated(expr ExprNode) bool {
    35  	return expr.GetFlag()&FlagPreEvaluated == FlagPreEvaluated
    36  }
    37  
    38  // IsConstant checks if the expression is constant.
    39  // A constant expression is safe to be rewritten to value expression.
    40  func IsConstant(expr ExprNode) bool {
    41  	return (expr.GetFlag() &^ FlagPreEvaluated) == FlagConstant
    42  }
    43  
    44  // HasAggFlag checks if the expr contains FlagHasAggregateFunc.
    45  func HasAggFlag(expr ExprNode) bool {
    46  	return expr.GetFlag()&FlagHasAggregateFunc > 0
    47  }
    48  
    49  type preEvaluatedReseter struct {
    50  }
    51  
    52  func (r *preEvaluatedReseter) Enter(in Node) (Node, bool) {
    53  	return in, false
    54  }
    55  
    56  func (r *preEvaluatedReseter) Leave(in Node) (Node, bool) {
    57  	if expr, ok := in.(ExprNode); ok {
    58  		resetEvaluatedExpr(expr)
    59  	}
    60  	return in, true
    61  }
    62  
    63  // SetFlag sets flag for expression.
    64  func SetFlag(n Node) {
    65  	var setter flagSetter
    66  	n.Accept(&setter)
    67  }
    68  
    69  type flagSetter struct {
    70  }
    71  
    72  func (f *flagSetter) Enter(in Node) (Node, bool) {
    73  	return in, false
    74  }
    75  
    76  func (f *flagSetter) Leave(in Node) (Node, bool) {
    77  	switch x := in.(type) {
    78  	case *AggregateFuncExpr:
    79  		f.aggregateFunc(x)
    80  	case *BetweenExpr:
    81  		x.SetFlag(x.Expr.GetFlag() | x.Left.GetFlag() | x.Right.GetFlag())
    82  	case *BinaryOperationExpr:
    83  		x.SetFlag(x.L.GetFlag() | x.R.GetFlag())
    84  	case *CaseExpr:
    85  		f.caseExpr(x)
    86  	case *ColumnNameExpr:
    87  		x.SetFlag(FlagHasReference)
    88  	case *CompareSubqueryExpr:
    89  		x.SetFlag(x.L.GetFlag() | x.R.GetFlag())
    90  	case *DefaultExpr:
    91  		x.SetFlag(FlagHasDefault)
    92  	case *ExistsSubqueryExpr:
    93  		x.SetFlag(x.Sel.GetFlag())
    94  	case *FuncCallExpr:
    95  		f.funcCall(x)
    96  	case *FuncCastExpr:
    97  		x.SetFlag(FlagHasFunc | x.Expr.GetFlag())
    98  	case *IsNullExpr:
    99  		x.SetFlag(x.Expr.GetFlag())
   100  	case *IsTruthExpr:
   101  		x.SetFlag(x.Expr.GetFlag())
   102  	case *ParamMarkerExpr:
   103  		x.SetFlag(FlagHasParamMarker)
   104  	case *ParenthesesExpr:
   105  		x.SetFlag(x.Expr.GetFlag())
   106  	case *PatternInExpr:
   107  		f.patternIn(x)
   108  	case *PatternLikeExpr:
   109  		f.patternLike(x)
   110  	case *PatternRegexpExpr:
   111  		f.patternRegexp(x)
   112  	case *PositionExpr:
   113  		x.SetFlag(FlagHasReference)
   114  	case *RowExpr:
   115  		f.row(x)
   116  	case *SubqueryExpr:
   117  		x.SetFlag(FlagHasSubquery)
   118  	case *UnaryOperationExpr:
   119  		x.SetFlag(x.V.GetFlag())
   120  	case *ValueExpr:
   121  	case *ValuesExpr:
   122  		x.SetFlag(FlagHasReference)
   123  	case *VariableExpr:
   124  		if x.Value == nil {
   125  			x.SetFlag(FlagHasVariable)
   126  		} else {
   127  			x.SetFlag(FlagHasVariable | x.Value.GetFlag())
   128  		}
   129  	}
   130  
   131  	return in, true
   132  }
   133  
   134  func (f *flagSetter) caseExpr(x *CaseExpr) {
   135  	var flag uint64
   136  	if x.Value != nil {
   137  		flag |= x.Value.GetFlag()
   138  	}
   139  	for _, val := range x.WhenClauses {
   140  		flag |= val.Expr.GetFlag()
   141  		flag |= val.Result.GetFlag()
   142  	}
   143  	if x.ElseClause != nil {
   144  		flag |= x.ElseClause.GetFlag()
   145  	}
   146  	x.SetFlag(flag)
   147  }
   148  
   149  func (f *flagSetter) patternIn(x *PatternInExpr) {
   150  	flag := x.Expr.GetFlag()
   151  	for _, val := range x.List {
   152  		flag |= val.GetFlag()
   153  	}
   154  	if x.Sel != nil {
   155  		flag |= x.Sel.GetFlag()
   156  	}
   157  	x.SetFlag(flag)
   158  }
   159  
   160  func (f *flagSetter) patternLike(x *PatternLikeExpr) {
   161  	flag := x.Pattern.GetFlag()
   162  	if x.Expr != nil {
   163  		flag |= x.Expr.GetFlag()
   164  	}
   165  	x.SetFlag(flag)
   166  }
   167  
   168  func (f *flagSetter) patternRegexp(x *PatternRegexpExpr) {
   169  	flag := x.Pattern.GetFlag()
   170  	if x.Expr != nil {
   171  		flag |= x.Expr.GetFlag()
   172  	}
   173  	x.SetFlag(flag)
   174  }
   175  
   176  func (f *flagSetter) row(x *RowExpr) {
   177  	var flag uint64
   178  	for _, val := range x.Values {
   179  		flag |= val.GetFlag()
   180  	}
   181  	x.SetFlag(flag)
   182  }
   183  
   184  func (f *flagSetter) funcCall(x *FuncCallExpr) {
   185  	flag := FlagHasFunc
   186  	for _, val := range x.Args {
   187  		flag |= val.GetFlag()
   188  	}
   189  	x.SetFlag(flag)
   190  }
   191  
   192  func (f *flagSetter) aggregateFunc(x *AggregateFuncExpr) {
   193  	flag := FlagHasAggregateFunc
   194  	for _, val := range x.Args {
   195  		flag |= val.GetFlag()
   196  	}
   197  	x.SetFlag(flag)
   198  }
   199  
   200  // MergeChildrenFlags sets flag to parent by children.
   201  func MergeChildrenFlags(parent ExprNode, children ...ExprNode) {
   202  	var flag uint64
   203  	for _, child := range children {
   204  		flag |= child.GetFlag()
   205  	}
   206  	parent.SetFlag(flag &^ FlagPreEvaluated)
   207  }