github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/optgen/exprgen/expr_gen.go (about) 1 // Copyright 2019 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package exprgen 12 13 import ( 14 "fmt" 15 "io" 16 "reflect" 17 "strings" 18 19 "github.com/cockroachdb/cockroach/pkg/sql/opt" 20 "github.com/cockroachdb/cockroach/pkg/sql/opt/cat" 21 "github.com/cockroachdb/cockroach/pkg/sql/opt/memo" 22 "github.com/cockroachdb/cockroach/pkg/sql/opt/norm" 23 "github.com/cockroachdb/cockroach/pkg/sql/opt/optgen/lang" 24 "github.com/cockroachdb/cockroach/pkg/sql/opt/ordering" 25 "github.com/cockroachdb/cockroach/pkg/sql/opt/props/physical" 26 "github.com/cockroachdb/cockroach/pkg/sql/opt/xform" 27 "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" 28 "github.com/cockroachdb/cockroach/pkg/sql/types" 29 "github.com/cockroachdb/errors" 30 ) 31 32 // Build generates an expression from an optgen string (the kind of expression 33 // that would show up in the replace side of a rule). 34 // 35 // For example, if the input is "(Eq (Const 1) (Const 2))", the output is the 36 // corresponding expression tree: 37 // eq [type=bool] 38 // ├── const: 1 [type=int] 39 // └── const: 2 [type=int] 40 // 41 // There are some peculiarities compared to the usual opt-gen replace syntax: 42 // 43 // - Filters are specified as simply [ <condition> ... ]; no FiltersItem is 44 // necessary. 45 // 46 // - Various implicit conversions are allowed for convenience, e.g. list of 47 // columns to ColList/ColSet. 48 // 49 // - Operation privates (e.g. ScanPrivate) are specified as lists of fields 50 // of the form [ (FiledName <value>) ]. For example: 51 // [ (Table "abc") (Index "abc@ab") (Cols "a,b") ] 52 // Implicit conversions are allowed here for column lists, orderings, etc. 53 // 54 // - A Root custom function is used to set the physical properties of the root. 55 // Setting the physical properties (in particular the presentation) is always 56 // necessary for the plan to be run via PREPARE .. AS OPT PLAN '..'. 57 // 58 // Some examples of valid inputs: 59 // (Tuple [ (True) (False) ] "tuple{bool, bool}" ) 60 // 61 // (Root 62 // (Scan [ (Table "abc") (Index "abc@ab") (Cols "a,b") ]) 63 // (Presentation "a,b") 64 // (OrderingChoice "+a,+b") 65 // ) 66 // 67 // (Select 68 // (Scan [ (Table "abc") (Cols "a,b,c") ]) 69 // [ (Eq (Var "a") (Const 1)) ] 70 // ) 71 // 72 // For more examples, see the various testdata/ files. 73 // 74 func Build(catalog cat.Catalog, factory *norm.Factory, input string) (_ opt.Expr, err error) { 75 defer func() { 76 if r := recover(); r != nil { 77 if e, ok := r.(exprGenErr); ok { 78 err = e.error 79 } else { 80 panic(r) 81 } 82 } 83 }() 84 85 eg := exprGen{ 86 customFuncs: customFuncs{ 87 f: factory, 88 mem: factory.Memo(), 89 cat: catalog, 90 }, 91 coster: xform.MakeDefaultCoster(factory.Memo()), 92 } 93 94 // To create a valid optgen "file", we create a rule with a bogus match. 95 contents := "[FakeRule] (True) => " + input 96 parsed := eg.parse(contents) 97 result := eg.eval(parsed.Rules[0].Replace) 98 99 var expr opt.Expr 100 required := physical.MinRequired 101 if root, ok := result.(*rootSentinel); ok { 102 expr = root.expr 103 required = root.required 104 } else { 105 expr = result.(opt.Expr) 106 } 107 eg.populateBestProps(expr, required) 108 if rel, ok := expr.(memo.RelExpr); ok { 109 eg.mem.SetRoot(rel, required) 110 } 111 return expr, nil 112 } 113 114 type exprGen struct { 115 customFuncs 116 117 coster xform.Coster 118 } 119 120 type exprGenErr struct { 121 error 122 } 123 124 func errorf(format string, a ...interface{}) error { 125 return exprGenErr{fmt.Errorf(format, a...)} 126 } 127 128 func wrapf(err error, format string, a ...interface{}) error { 129 return exprGenErr{errors.WrapWithDepthf(1, err, format, a...)} 130 } 131 132 // Parses the input (with replace-side rule syntax) into an optgen expression 133 // tree. 134 func (eg *exprGen) parse(contents string) *lang.RootExpr { 135 p := lang.NewParser("fake.opt") 136 p.SetFileResolver(func(name string) (io.Reader, error) { 137 if name == "fake.opt" { 138 return strings.NewReader(contents), nil 139 } 140 return nil, fmt.Errorf("unknown file '%s'", name) 141 }) 142 parsed := p.Parse() 143 if parsed == nil { 144 errStr := "Errors during parsing:\n" 145 for _, err := range p.Errors() { 146 errStr = fmt.Sprintf("%s%s\n", errStr, err.Error()) 147 } 148 panic(errorf("%s", errStr)) 149 } 150 return parsed 151 } 152 153 // Evaluates the corresponding expression. 154 func (eg *exprGen) eval(expr lang.Expr) interface{} { 155 switch expr := expr.(type) { 156 case *lang.FuncExpr: 157 if expr.HasDynamicName() { 158 panic(errorf("dynamic functions not supported: %s", expr)) 159 } 160 161 name := expr.SingleName() 162 // Search for a factory function. 163 method := reflect.ValueOf(eg.f).MethodByName("Construct" + name) 164 if !method.IsValid() { 165 // Search for a custom function. 166 method = reflect.ValueOf(&eg.customFuncs).MethodByName(name) 167 if !method.IsValid() { 168 panic(errorf("unknown operator or function %s", name)) 169 } 170 } 171 return eg.call(name, method, expr.Args) 172 173 case *lang.ListExpr: 174 // Return a list expression as []interface{}. 175 list := make([]interface{}, len(expr.Items)) 176 for i, e := range expr.Items { 177 list[i] = eg.eval(e) 178 } 179 return list 180 181 case *lang.NumberExpr: 182 return tree.NewDInt(tree.DInt(*expr)) 183 184 case *lang.StringExpr: 185 return string(*expr) 186 187 default: 188 panic(errorf("unsupported expression %s: %v", expr.Op(), expr)) 189 } 190 } 191 192 // Calls a function (custom function or factory method) with the given 193 // arguments. Various implicit conversions are allowed. 194 func (eg *exprGen) call(name string, method reflect.Value, args lang.SliceExpr) interface{} { 195 fnTyp := method.Type() 196 if fnTyp.NumIn() != len(args) { 197 panic(errorf("%s expects %d arguments", name, fnTyp.NumIn())) 198 } 199 argVals := make([]reflect.Value, len(args)) 200 for i := range args { 201 desiredType := fnTyp.In(i) 202 203 // Special case for privates. 204 if desiredType.Kind() == reflect.Ptr && desiredType.Elem().Kind() == reflect.Struct && 205 strings.HasSuffix(desiredType.Elem().Name(), "Private") { 206 argVals[i] = reflect.ValueOf(eg.evalPrivate(desiredType.Elem(), args[i])) 207 continue 208 } 209 210 arg := eg.eval(args[i]) 211 converted := eg.castToDesiredType(arg, desiredType) 212 if converted == nil { 213 panic(errorf("%s: using %T as type %s", name, arg, desiredType)) 214 } 215 argVals[i] = reflect.ValueOf(converted) 216 } 217 return method.Call(argVals)[0].Interface() 218 } 219 220 // castToDesiredType tries to convert the given argument to a value of the given 221 // type. Returns nil if conversion was not possible. 222 func (eg *exprGen) castToDesiredType(arg interface{}, desiredType reflect.Type) interface{} { 223 actualType := reflect.TypeOf(arg) 224 if actualType.AssignableTo(desiredType) { 225 return arg 226 } 227 228 if slice, ok := arg.([]interface{}); ok { 229 // Special case for converting slice of ColumnIDs to a ColSet. 230 if desiredType == reflect.TypeOf(opt.ColSet{}) { 231 var set opt.ColSet 232 for i := range slice { 233 col, ok := slice[i].(opt.ColumnID) 234 if !ok { 235 return nil 236 } 237 set.Add(col) 238 } 239 return set 240 } 241 242 if desiredType.Kind() != reflect.Slice { 243 return nil 244 } 245 246 // See if we can convert all elements to the desired slice element type. 247 converted := convertSlice(slice, desiredType, func(v interface{}) interface{} { 248 if val := reflect.ValueOf(v); val.Type().AssignableTo(desiredType.Elem()) { 249 return val.Convert(desiredType.Elem()).Interface() 250 } 251 return nil 252 }) 253 if converted != nil { 254 return converted 255 } 256 257 // Special case for converting slice of values implementing ScalarExpr to a 258 // FiltersExpr. 259 if desiredType == reflect.TypeOf(memo.FiltersExpr{}) { 260 converted := convertSlice(slice, desiredType, func(v interface{}) interface{} { 261 expr, ok := v.(opt.ScalarExpr) 262 if !ok { 263 return nil 264 } 265 return eg.f.ConstructFiltersItem(expr) 266 }) 267 if converted != nil { 268 return converted 269 } 270 } 271 } 272 273 if i, ok := arg.(*tree.DInt); ok { 274 if desiredType == reflect.TypeOf(memo.ScanLimit(0)) { 275 return memo.MakeScanLimit(int64(*i), false) 276 } 277 } 278 279 if str, ok := arg.(string); ok { 280 // String to type. 281 if desiredType == reflect.TypeOf((*types.T)(nil)) { 282 typ, err := ParseType(str) 283 if err != nil { 284 panic(exprGenErr{err}) 285 } 286 return typ 287 } 288 289 // String to Ordering. 290 if desiredType == reflect.TypeOf(opt.Ordering{}) { 291 return eg.Ordering(str) 292 } 293 294 // String to OrderingChoice. 295 if desiredType == reflect.TypeOf(physical.OrderingChoice{}) { 296 return eg.OrderingChoice(str) 297 } 298 299 // String to ColList. 300 if desiredType == reflect.TypeOf(opt.ColList{}) { 301 return eg.ColList(str) 302 } 303 304 // String to ColSet. 305 if desiredType == reflect.TypeOf(opt.ColSet{}) { 306 return eg.ColSet(str) 307 } 308 309 // String to ExplainOptions. 310 if desiredType == reflect.TypeOf(tree.ExplainOptions{}) { 311 return eg.ExplainOptions(str) 312 } 313 314 // String to bool. 315 if desiredType == reflect.TypeOf(true) { 316 switch str { 317 case "true": 318 return true 319 case "false": 320 return false 321 default: 322 panic(errorf("invalid boolean value \"%s\" (expected \"true\" or \"false\")", str)) 323 } 324 } 325 } 326 return nil 327 } 328 329 // convertSlice tries to create a slice of the given type; each element is the 330 // result of calling mapFn on the input slice element. 331 // 332 // If mapFn returns nil for any element, convertSlice also returns nil. 333 func convertSlice( 334 slice []interface{}, toType reflect.Type, mapFn func(v interface{}) interface{}, 335 ) interface{} { 336 res := reflect.MakeSlice(toType, len(slice), len(slice)) 337 338 for i, v := range slice { 339 val := mapFn(v) 340 if val == nil { 341 return nil 342 } 343 res.Index(i).Set(reflect.ValueOf(val)) 344 } 345 return res.Interface() 346 } 347 348 // populateBestProps sets the physical properties and costs of the expressions 349 // in the tree. Returns the cost of the expression tree. 350 func (eg *exprGen) populateBestProps(expr opt.Expr, required *physical.Required) memo.Cost { 351 rel, _ := expr.(memo.RelExpr) 352 if rel != nil { 353 if !xform.CanProvidePhysicalProps(rel, required) { 354 panic(errorf("operator %s cannot provide required props %s", rel.Op(), required)) 355 } 356 } 357 358 var cost memo.Cost 359 for i, n := 0, expr.ChildCount(); i < n; i++ { 360 var childProps *physical.Required 361 if rel != nil { 362 childProps = xform.BuildChildPhysicalProps(eg.mem, rel, i, required) 363 } else { 364 childProps = xform.BuildChildPhysicalPropsScalar(eg.mem, expr, i) 365 } 366 cost += eg.populateBestProps(expr.Child(i), childProps) 367 } 368 369 if rel != nil { 370 provided := &physical.Provided{} 371 // BuildProvided relies on ProvidedPhysical() being set in the children, so 372 // it must run after the recursive calls on the children. 373 provided.Ordering = ordering.BuildProvided(rel, &required.Ordering) 374 375 cost += eg.coster.ComputeCost(rel, required) 376 eg.mem.SetBestProps(rel, required, provided, cost) 377 } 378 return cost 379 }