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  }