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 }