vitess.io/vitess@v0.16.2/go/vt/vtgate/planbuilder/semi_join.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 planbuilder
    18  
    19  import (
    20  	"vitess.io/vitess/go/vt/sqlparser"
    21  	"vitess.io/vitess/go/vt/vterrors"
    22  	"vitess.io/vitess/go/vt/vtgate/engine"
    23  	"vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext"
    24  	"vitess.io/vitess/go/vt/vtgate/semantics"
    25  )
    26  
    27  var _ logicalPlan = (*semiJoin)(nil)
    28  
    29  // semiJoin is the logicalPlan for engine.SemiJoin.
    30  // This gets built if a rhs is correlated and can
    31  // be pulled out but requires some variables to be supplied from outside.
    32  type semiJoin struct {
    33  	gen4Plan
    34  	rhs  logicalPlan
    35  	lhs  logicalPlan
    36  	cols []int
    37  
    38  	vars map[string]int
    39  
    40  	// LHSColumns are the columns from the LHS used for the join.
    41  	// These are the same columns pushed on the LHS that are now used in the vars field
    42  	LHSColumns []*sqlparser.ColName
    43  }
    44  
    45  // newSemiJoin builds a new semiJoin.
    46  func newSemiJoin(lhs, rhs logicalPlan, vars map[string]int, lhsCols []*sqlparser.ColName) *semiJoin {
    47  	return &semiJoin{
    48  		rhs:        rhs,
    49  		lhs:        lhs,
    50  		vars:       vars,
    51  		LHSColumns: lhsCols,
    52  	}
    53  }
    54  
    55  // Primitive implements the logicalPlan interface
    56  func (ps *semiJoin) Primitive() engine.Primitive {
    57  	return &engine.SemiJoin{
    58  		Left:  ps.lhs.Primitive(),
    59  		Right: ps.rhs.Primitive(),
    60  		Vars:  ps.vars,
    61  		Cols:  ps.cols,
    62  	}
    63  }
    64  
    65  // WireupGen4 implements the logicalPlan interface
    66  func (ps *semiJoin) WireupGen4(ctx *plancontext.PlanningContext) error {
    67  	if err := ps.lhs.WireupGen4(ctx); err != nil {
    68  		return err
    69  	}
    70  	return ps.rhs.WireupGen4(ctx)
    71  }
    72  
    73  // Rewrite implements the logicalPlan interface
    74  func (ps *semiJoin) Rewrite(inputs ...logicalPlan) error {
    75  	if len(inputs) != 2 {
    76  		return vterrors.VT13001("semiJoin: wrong number of inputs")
    77  	}
    78  	ps.lhs = inputs[0]
    79  	ps.rhs = inputs[1]
    80  	return nil
    81  }
    82  
    83  // ContainsTables implements the logicalPlan interface
    84  func (ps *semiJoin) ContainsTables() semantics.TableSet {
    85  	return ps.lhs.ContainsTables().Merge(ps.rhs.ContainsTables())
    86  }
    87  
    88  // Inputs implements the logicalPlan interface
    89  func (ps *semiJoin) Inputs() []logicalPlan {
    90  	return []logicalPlan{ps.lhs, ps.rhs}
    91  }
    92  
    93  // OutputColumns implements the logicalPlan interface
    94  func (ps *semiJoin) OutputColumns() []sqlparser.SelectExpr {
    95  	return ps.lhs.OutputColumns()
    96  }