github.com/matrixorigin/matrixone@v0.7.0/pkg/sql/plan/explain/explain_expr.go (about) 1 // Copyright 2021 - 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 explain 16 17 import ( 18 "context" 19 "fmt" 20 "strconv" 21 22 "github.com/matrixorigin/matrixone/pkg/common/moerr" 23 "github.com/matrixorigin/matrixone/pkg/container/types" 24 "github.com/matrixorigin/matrixone/pkg/pb/plan" 25 "github.com/matrixorigin/matrixone/pkg/sql/plan/function" 26 ) 27 28 func describeExpr(ctx context.Context, expr *plan.Expr, options *ExplainOptions) (string, error) { 29 var result string 30 31 switch exprImpl := expr.Expr.(type) { 32 case *plan.Expr_Col: 33 if len(exprImpl.Col.Name) > 0 { 34 result += exprImpl.Col.Name 35 } else { 36 result += "#[" 37 result += strconv.FormatInt(int64(exprImpl.Col.RelPos), 10) 38 result += "," 39 result += strconv.FormatInt(int64(exprImpl.Col.ColPos), 10) 40 result += "]" 41 } 42 case *plan.Expr_C: 43 if exprImpl.C.Isnull { 44 result += "(null)" 45 break 46 } 47 48 switch val := exprImpl.C.Value.(type) { 49 case *plan.Const_I8Val: 50 result += strconv.FormatInt(int64(val.I8Val), 10) 51 case *plan.Const_I16Val: 52 result += strconv.FormatInt(int64(val.I16Val), 10) 53 case *plan.Const_I32Val: 54 result += strconv.FormatInt(int64(val.I32Val), 10) 55 case *plan.Const_I64Val: 56 result += strconv.FormatInt(val.I64Val, 10) 57 case *plan.Const_U8Val: 58 result += strconv.FormatUint(uint64(val.U8Val), 10) 59 case *plan.Const_U16Val: 60 result += strconv.FormatUint(uint64(val.U16Val), 10) 61 case *plan.Const_U32Val: 62 result += strconv.FormatUint(uint64(val.U32Val), 10) 63 case *plan.Const_U64Val: 64 result += strconv.FormatUint(val.U64Val, 10) 65 66 case *plan.Const_Fval: 67 result += strconv.FormatFloat(float64(val.Fval), 'f', -1, 32) 68 69 case *plan.Const_Dval: 70 result += strconv.FormatFloat(val.Dval, 'f', -1, 64) 71 72 case *plan.Const_Sval: 73 result += "'" + val.Sval + "'" 74 75 case *plan.Const_Bval: 76 result += strconv.FormatBool(val.Bval) 77 } 78 79 case *plan.Expr_F: 80 funcExpr := expr.Expr.(*plan.Expr_F) 81 funcDesc, err := funcExprExplain(ctx, funcExpr, expr.Typ, options) 82 if err != nil { 83 return result, err 84 } 85 result += funcDesc 86 case *plan.Expr_Sub: 87 subqryExpr := expr.Expr.(*plan.Expr_Sub) 88 result += "subquery nodeId = " + strconv.FormatInt(int64(subqryExpr.Sub.NodeId), 10) 89 case *plan.Expr_Corr: 90 result += "#[" 91 result += strconv.FormatInt(int64(exprImpl.Corr.RelPos), 10) 92 result += "," 93 result += strconv.FormatInt(int64(exprImpl.Corr.ColPos), 10) 94 result += ":" 95 result += strconv.FormatInt(int64(exprImpl.Corr.Depth), 10) 96 result += "]" 97 case *plan.Expr_V: 98 if exprImpl.V.System { 99 if exprImpl.V.Global { 100 result += "@@global." + exprImpl.V.Name 101 } else { 102 result += "@@session." + exprImpl.V.Name 103 } 104 } else { 105 result += "@" + exprImpl.V.Name 106 } 107 case *plan.Expr_P: 108 panic("unimplement Expr_P") 109 case *plan.Expr_List: 110 exprlist := expr.Expr.(*plan.Expr_List) 111 if exprlist.List.List != nil { 112 exprListDescImpl := NewExprListDescribeImpl(exprlist.List.List) 113 desclist, err := exprListDescImpl.GetDescription(ctx, options) 114 if err != nil { 115 return result, err 116 } 117 result += desclist 118 } 119 default: 120 panic("error Expr") 121 } 122 123 return result, nil 124 } 125 126 // generator function expression(Expr_F) explain information 127 func funcExprExplain(ctx context.Context, funcExpr *plan.Expr_F, Typ *plan.Type, options *ExplainOptions) (string, error) { 128 // SysFunsAndOperatorsMap 129 var result string 130 funcName := funcExpr.F.GetFunc().GetObjName() 131 funcDef := funcExpr.F.GetFunc() 132 133 funcProtoType, err := function.GetFunctionByID(ctx, funcDef.Obj&function.DistinctMask) 134 if err != nil { 135 return result, moerr.NewInvalidInput(ctx, "invalid function or opreator '%s'", funcName) 136 } 137 138 switch funcProtoType.GetLayout() { 139 case function.STANDARD_FUNCTION: 140 result += funcExpr.F.Func.GetObjName() + "(" 141 if len(funcExpr.F.Args) > 0 { 142 var first = true 143 for _, v := range funcExpr.F.Args { 144 if !first { 145 result += ", " 146 } 147 first = false 148 exprDesc, err := describeExpr(ctx, v, options) 149 if err != nil { 150 return result, err 151 } 152 result += exprDesc 153 } 154 } 155 result += ")" 156 case function.UNARY_ARITHMETIC_OPERATOR: 157 var opertator string 158 if funcExpr.F.Func.GetObjName() == "UNARY_PLUS" { 159 opertator = "+" 160 } else { 161 opertator = "-" 162 } 163 describeExpr, err := describeExpr(ctx, funcExpr.F.Args[0], options) 164 if err != nil { 165 return result, err 166 } 167 result += "(" + opertator + describeExpr + ")" 168 case function.UNARY_LOGICAL_OPERATOR: 169 describeExpr, err := describeExpr(ctx, funcExpr.F.Args[0], options) 170 if err != nil { 171 return result, err 172 } 173 result += "(" + funcExpr.F.Func.GetObjName() + " " + describeExpr + ")" 174 case function.BINARY_ARITHMETIC_OPERATOR: 175 fallthrough 176 case function.BINARY_LOGICAL_OPERATOR: 177 fallthrough 178 case function.COMPARISON_OPERATOR: 179 left, err := describeExpr(ctx, funcExpr.F.Args[0], options) 180 if err != nil { 181 return result, err 182 } 183 right, err := describeExpr(ctx, funcExpr.F.Args[1], options) 184 if err != nil { 185 return result, err 186 } 187 result += "(" + left + " " + funcExpr.F.Func.GetObjName() + " " + right + ")" 188 case function.CAST_EXPRESSION: 189 describeExpr, err := describeExpr(ctx, funcExpr.F.Args[0], options) 190 if err != nil { 191 return result, err 192 } 193 tt := types.T(Typ.Id) 194 if tt == types.T_decimal64 || tt == types.T_decimal128 { 195 result += fmt.Sprintf("CAST(%s AS %s(%d, %d))", describeExpr, tt.String(), Typ.Precision, Typ.Scale) 196 } else { 197 result += "CAST(" + describeExpr + " AS " + tt.String() + ")" 198 } 199 case function.CASE_WHEN_EXPRESSION: 200 // TODO need rewrite to deal with case is nil 201 result += "CASE" 202 // case when expression has two part(case when condition and else exression) 203 condSize := len(funcExpr.F.Args) / 2 204 for i := 0; i < condSize; i++ { 205 whenExpr := funcExpr.F.Args[i] 206 thenExpr := funcExpr.F.Args[i+1] 207 whenExprDesc, err := describeExpr(ctx, whenExpr, options) 208 if err != nil { 209 return result, err 210 } 211 thenExprDesc, err := describeExpr(ctx, thenExpr, options) 212 if err != nil { 213 return result, err 214 } 215 result += " WHEN " + whenExprDesc + " THEN " + thenExprDesc 216 } 217 218 if len(funcExpr.F.Args)%2 == 1 { 219 lastIndex := len(funcExpr.F.Args) - 1 220 elseExpr := funcExpr.F.Args[lastIndex] 221 // get else expression 222 elseExprDesc, err := describeExpr(ctx, elseExpr, options) 223 if err != nil { 224 return result, err 225 } 226 result += " ELSE " + elseExprDesc 227 } 228 result += " END" 229 case function.IN_PREDICATE: 230 if len(funcExpr.F.Args) != 2 { 231 panic("Nested query predicate,such as in,exist,all,any parameter number error!") 232 } 233 descExpr, err := describeExpr(ctx, funcExpr.F.Args[0], options) 234 if err != nil { 235 return result, err 236 } 237 descExprlist, err := describeExpr(ctx, funcExpr.F.Args[1], options) 238 if err != nil { 239 return result, err 240 } 241 result += descExpr + " " + funcExpr.F.Func.GetObjName() + "(" + descExprlist + ")" 242 case function.EXISTS_ANY_PREDICATE: 243 describeExpr, err := describeExpr(ctx, funcExpr.F.Args[0], options) 244 if err != nil { 245 return result, err 246 } 247 result += funcExpr.F.Func.GetObjName() + "(" + describeExpr + ")" 248 case function.IS_NULL_EXPRESSION: 249 describeExpr, err := describeExpr(ctx, funcExpr.F.Args[0], options) 250 if err != nil { 251 return result, err 252 } 253 result += "(" + describeExpr + " IS NULL)" 254 case function.NOPARAMETER_FUNCTION: 255 result += funcExpr.F.Func.GetObjName() 256 case function.DATE_INTERVAL_EXPRESSION: 257 describeExpr, err := describeExpr(ctx, funcExpr.F.Args[0], options) 258 if err != nil { 259 return result, err 260 } 261 result += funcExpr.F.Func.GetObjName() + " " + describeExpr + "" 262 case function.EXTRACT_FUNCTION: 263 first, err := describeExpr(ctx, funcExpr.F.Args[0], options) 264 if err != nil { 265 return result, err 266 } 267 second, err := describeExpr(ctx, funcExpr.F.Args[1], options) 268 if err != nil { 269 return result, err 270 } 271 272 result += funcExpr.F.Func.GetObjName() + "(" + first + " from " + second + ")" 273 case function.UNKNOW_KIND_FUNCTION: 274 return result, moerr.NewInvalidInput(ctx, "explain contains UNKNOW_KIND_FUNCTION") 275 } 276 return result, nil 277 }