vitess.io/vitess@v0.16.2/go/vt/vtgate/planbuilder/hash_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  	"fmt"
    21  
    22  	"vitess.io/vitess/go/mysql/collations"
    23  	querypb "vitess.io/vitess/go/vt/proto/query"
    24  	"vitess.io/vitess/go/vt/sqlparser"
    25  	"vitess.io/vitess/go/vt/vterrors"
    26  	"vitess.io/vitess/go/vt/vtgate/engine"
    27  	"vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext"
    28  	"vitess.io/vitess/go/vt/vtgate/semantics"
    29  )
    30  
    31  var _ logicalPlan = (*hashJoin)(nil)
    32  
    33  // hashJoin is used to build a HashJoin primitive.
    34  type hashJoin struct {
    35  	gen4Plan
    36  
    37  	// Left and Right are the nodes for the join.
    38  	Left, Right logicalPlan
    39  
    40  	Opcode engine.JoinOpcode
    41  
    42  	Cols []int
    43  
    44  	// The keys correspond to the column offset in the inputs where
    45  	// the join columns can be found
    46  	LHSKey, RHSKey int
    47  
    48  	ComparisonType querypb.Type
    49  
    50  	Collation collations.ID
    51  }
    52  
    53  // WireupGen4 implements the logicalPlan interface
    54  func (hj *hashJoin) WireupGen4(ctx *plancontext.PlanningContext) error {
    55  	err := hj.Left.WireupGen4(ctx)
    56  	if err != nil {
    57  		return err
    58  	}
    59  	return hj.Right.WireupGen4(ctx)
    60  }
    61  
    62  // Primitive implements the logicalPlan interface
    63  func (hj *hashJoin) Primitive() engine.Primitive {
    64  	return &engine.HashJoin{
    65  		Left:           hj.Left.Primitive(),
    66  		Right:          hj.Right.Primitive(),
    67  		Cols:           hj.Cols,
    68  		Opcode:         hj.Opcode,
    69  		LHSKey:         hj.LHSKey,
    70  		RHSKey:         hj.RHSKey,
    71  		ComparisonType: hj.ComparisonType,
    72  		Collation:      hj.Collation,
    73  	}
    74  }
    75  
    76  // Inputs implements the logicalPlan interface
    77  func (hj *hashJoin) Inputs() []logicalPlan {
    78  	return []logicalPlan{hj.Left, hj.Right}
    79  }
    80  
    81  // Rewrite implements the logicalPlan interface
    82  func (hj *hashJoin) Rewrite(inputs ...logicalPlan) error {
    83  	if len(inputs) != 2 {
    84  		return vterrors.VT13001(fmt.Sprintf("wrong number of children in hashJoin rewrite: %d; should be exactly 2", len(inputs)))
    85  	}
    86  	hj.Left = inputs[0]
    87  	hj.Right = inputs[1]
    88  	return nil
    89  }
    90  
    91  // ContainsTables implements the logicalPlan interface
    92  func (hj *hashJoin) ContainsTables() semantics.TableSet {
    93  	return hj.Left.ContainsTables().Merge(hj.Right.ContainsTables())
    94  }
    95  
    96  // OutputColumns implements the logicalPlan interface
    97  func (hj *hashJoin) OutputColumns() []sqlparser.SelectExpr {
    98  	return getOutputColumnsFromJoin(hj.Cols, hj.Left.OutputColumns(), hj.Right.OutputColumns())
    99  }
   100  
   101  func getOutputColumnsFromJoin(ints []int, lhs []sqlparser.SelectExpr, rhs []sqlparser.SelectExpr) (cols []sqlparser.SelectExpr) {
   102  	for _, col := range ints {
   103  		if col < 0 {
   104  			col *= -1
   105  			cols = append(cols, lhs[col-1])
   106  		} else {
   107  			cols = append(cols, rhs[col-1])
   108  		}
   109  	}
   110  	return
   111  }