github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/sem/tree/constant_eval.go (about) 1 // Copyright 2018 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 tree 12 13 // ConstantEvalVisitor replaces constant TypedExprs with the result of Eval. 14 type ConstantEvalVisitor struct { 15 ctx *EvalContext 16 err error 17 18 fastIsConstVisitor fastIsConstVisitor 19 } 20 21 var _ Visitor = &ConstantEvalVisitor{} 22 23 // MakeConstantEvalVisitor creates a ConstantEvalVisitor instance. 24 func MakeConstantEvalVisitor(ctx *EvalContext) ConstantEvalVisitor { 25 return ConstantEvalVisitor{ctx: ctx, fastIsConstVisitor: fastIsConstVisitor{ctx: ctx}} 26 } 27 28 // Err retrieves the error field in the ConstantEvalVisitor. 29 func (v *ConstantEvalVisitor) Err() error { return v.err } 30 31 // VisitPre implements the Visitor interface. 32 func (v *ConstantEvalVisitor) VisitPre(expr Expr) (recurse bool, newExpr Expr) { 33 if v.err != nil { 34 return false, expr 35 } 36 return true, expr 37 } 38 39 // VisitPost implements the Visitor interface. 40 func (v *ConstantEvalVisitor) VisitPost(expr Expr) Expr { 41 if v.err != nil { 42 return expr 43 } 44 45 typedExpr, ok := expr.(TypedExpr) 46 if !ok || !v.isConst(expr) { 47 return expr 48 } 49 50 value, err := typedExpr.Eval(v.ctx) 51 if err != nil { 52 // Ignore any errors here (e.g. division by zero), so they can happen 53 // during execution where they are correctly handled. Note that in some 54 // cases we might not even get an error (if this particular expression 55 // does not get evaluated when the query runs, e.g. it's inside a CASE). 56 return expr 57 } 58 if value == DNull { 59 // We don't want to return an expression that has a different type; cast 60 // the NULL if necessary. 61 return ReType(DNull, typedExpr.ResolvedType()) 62 } 63 return value 64 } 65 66 func (v *ConstantEvalVisitor) isConst(expr Expr) bool { 67 return v.fastIsConstVisitor.run(expr) 68 }