vitess.io/vitess@v0.16.2/go/vt/vtgate/planbuilder/operators/operator_funcs.go (about)

     1  /*
     2  Copyright 2021 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package operators
    18  
    19  import (
    20  	"fmt"
    21  
    22  	"vitess.io/vitess/go/vt/sqlparser"
    23  	"vitess.io/vitess/go/vt/vterrors"
    24  	"vitess.io/vitess/go/vt/vtgate/planbuilder/operators/ops"
    25  	"vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext"
    26  )
    27  
    28  // RemovePredicate is used when we turn a predicate into a plan operator,
    29  // and the predicate needs to be removed as an AST construct
    30  func RemovePredicate(ctx *plancontext.PlanningContext, expr sqlparser.Expr, op ops.Operator) (ops.Operator, error) {
    31  	switch op := op.(type) {
    32  	case *Route:
    33  		newSrc, err := RemovePredicate(ctx, expr, op.Source)
    34  		if err != nil {
    35  			return nil, err
    36  		}
    37  		op.Source = newSrc
    38  		return op, err
    39  	case *ApplyJoin:
    40  		isRemoved := false
    41  		deps := ctx.SemTable.RecursiveDeps(expr)
    42  		if deps.IsSolvedBy(TableID(op.LHS)) {
    43  			newSrc, err := RemovePredicate(ctx, expr, op.LHS)
    44  			if err != nil {
    45  				return nil, err
    46  			}
    47  			op.LHS = newSrc
    48  			isRemoved = true
    49  		}
    50  
    51  		if deps.IsSolvedBy(TableID(op.RHS)) {
    52  			newSrc, err := RemovePredicate(ctx, expr, op.RHS)
    53  			if err != nil {
    54  				return nil, err
    55  			}
    56  			op.RHS = newSrc
    57  			isRemoved = true
    58  		}
    59  
    60  		var keep []sqlparser.Expr
    61  		for _, e := range sqlparser.SplitAndExpression(nil, op.Predicate) {
    62  			if ctx.SemTable.EqualsExpr(expr, e) {
    63  				isRemoved = true
    64  			} else {
    65  				keep = append(keep, e)
    66  			}
    67  		}
    68  
    69  		if !isRemoved {
    70  			return nil, vterrors.VT12001(fmt.Sprintf("remove '%s' predicate on cross-shard join query", sqlparser.String(expr)))
    71  		}
    72  
    73  		op.Predicate = ctx.SemTable.AndExpressions(keep...)
    74  		return op, nil
    75  	case *Filter:
    76  		idx := -1
    77  		for i, predicate := range op.Predicates {
    78  			if ctx.SemTable.EqualsExpr(predicate, expr) {
    79  				idx = i
    80  			}
    81  		}
    82  		if idx == -1 {
    83  			// the predicate is not here. let's remove it from our source
    84  			newSrc, err := RemovePredicate(ctx, expr, op.Source)
    85  			if err != nil {
    86  				return nil, err
    87  			}
    88  			op.Source = newSrc
    89  			return op, nil
    90  		}
    91  		if len(op.Predicates) == 1 {
    92  			// no predicates left on this operator, so we just remove it
    93  			return op.Source, nil
    94  		}
    95  
    96  		// remove the predicate from this filter
    97  		op.Predicates = append(op.Predicates[:idx], op.Predicates[idx+1:]...)
    98  		return op, nil
    99  
   100  	default:
   101  		return nil, vterrors.VT13001("this should not happen - tried to remove predicate from the operator table")
   102  	}
   103  }