github.com/dolthub/go-mysql-server@v0.18.0/sql/walk.go (about)

     1  // Copyright 2020-2021 Dolthub, 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  // 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 sql
    16  
    17  // Visitor visits expressions in an expression tree.
    18  type Visitor interface {
    19  	// Visit method is invoked for each expr encountered by Walk.
    20  	// If the result Visitor is not nil, Walk visits each of the children
    21  	// of the expr with that visitor, followed by a call of Visit(nil)
    22  	// to the returned visitor.
    23  	Visit(expr Expression) Visitor
    24  }
    25  
    26  // Walk traverses the expression tree in depth-first order. It starts by calling
    27  // v.Visit(expr); expr must not be nil. If the visitor returned by
    28  // v.Visit(expr) is not nil, Walk is invoked recursively with the returned
    29  // visitor for each children of the expr, followed by a call of v.Visit(nil)
    30  // to the returned visitor.
    31  func Walk(v Visitor, expr Expression) {
    32  	if v = v.Visit(expr); v == nil {
    33  		return
    34  	}
    35  
    36  	for _, child := range expr.Children() {
    37  		Walk(v, child)
    38  	}
    39  }
    40  
    41  // NodeVisitor visits expressions in an expression tree. Like Visitor, but with the added context of the node in which
    42  // an expression is embedded. See WalkExpressionsWithNode in the plan package.
    43  type NodeVisitor interface {
    44  	// Visit method is invoked for each expr encountered by Walk. If the result Visitor is not nil, Walk visits each of
    45  	// the children of the expr with that visitor, followed by a call of Visit(nil, nil) to the returned visitor.
    46  	Visit(node Node, expression Expression) NodeVisitor
    47  }
    48  
    49  // WalkWithNode traverses the expression tree in depth-first order. It starts by calling v.Visit(node, expr); expr must
    50  // not be nil. If the visitor returned by v.Visit(node, expr) is not nil, Walk is invoked recursively with the returned
    51  // visitor for each children of the expr, followed by a call of v.Visit(nil, nil) to the returned visitor.
    52  func WalkWithNode(v NodeVisitor, n Node, expr Expression) {
    53  	if v = v.Visit(n, expr); v == nil {
    54  		return
    55  	}
    56  
    57  	for _, child := range expr.Children() {
    58  		WalkWithNode(v, n, child)
    59  	}
    60  
    61  	v.Visit(nil, nil)
    62  }
    63  
    64  type inspector func(Expression) bool
    65  
    66  func (f inspector) Visit(expr Expression) Visitor {
    67  	if f(expr) {
    68  		return f
    69  	}
    70  	return nil
    71  }
    72  
    73  // Inspect traverses the plan in depth-first order: It starts by calling
    74  // f(expr); expr must not be nil. If f returns true, Inspect invokes f
    75  // recursively for each of the children of expr, followed by a call of
    76  // f(nil).
    77  func Inspect(expr Expression, f func(expr Expression) bool) {
    78  	Walk(inspector(f), expr)
    79  }
    80  
    81  // NillaryWithChildren is a common implementation of expression.WithChildren for expressions with no children.
    82  func NillaryWithChildren(expr Expression, children ...Expression) (Expression, error) {
    83  	if len(children) > 0 {
    84  		return nil, ErrInvalidChildrenNumber.New(expr, len(children), 0)
    85  	}
    86  	return expr, nil
    87  }