vitess.io/vitess@v0.16.2/go/vt/vtgate/planbuilder/operators/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 operators
    18  
    19  import (
    20  	"vitess.io/vitess/go/vt/sqlparser"
    21  	"vitess.io/vitess/go/vt/vtgate/planbuilder/operators/ops"
    22  	"vitess.io/vitess/go/vt/vtgate/planbuilder/operators/rewrite"
    23  	"vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext"
    24  )
    25  
    26  // Join represents a join. If we have a predicate, this is an inner join. If no predicate exists, it is a cross join
    27  type Join struct {
    28  	LHS, RHS  ops.Operator
    29  	Predicate sqlparser.Expr
    30  	LeftJoin  bool
    31  
    32  	noColumns
    33  }
    34  
    35  var _ ops.Operator = (*Join)(nil)
    36  
    37  // Clone implements the Operator interface
    38  func (j *Join) Clone(inputs []ops.Operator) ops.Operator {
    39  	clone := *j
    40  	clone.LHS = inputs[0]
    41  	clone.RHS = inputs[1]
    42  	return &Join{
    43  		LHS:       inputs[0],
    44  		RHS:       inputs[1],
    45  		Predicate: j.Predicate,
    46  		LeftJoin:  j.LeftJoin,
    47  	}
    48  }
    49  
    50  // Inputs implements the Operator interface
    51  func (j *Join) Inputs() []ops.Operator {
    52  	return []ops.Operator{j.LHS, j.RHS}
    53  }
    54  
    55  func (j *Join) Compact(ctx *plancontext.PlanningContext) (ops.Operator, rewrite.TreeIdentity, error) {
    56  	if j.LeftJoin {
    57  		// we can't merge outer joins into a single QG
    58  		return j, rewrite.SameTree, nil
    59  	}
    60  
    61  	lqg, lok := j.LHS.(*QueryGraph)
    62  	rqg, rok := j.RHS.(*QueryGraph)
    63  	if !lok || !rok {
    64  		return j, rewrite.SameTree, nil
    65  	}
    66  
    67  	newOp := &QueryGraph{
    68  		Tables:     append(lqg.Tables, rqg.Tables...),
    69  		innerJoins: append(lqg.innerJoins, rqg.innerJoins...),
    70  		NoDeps:     ctx.SemTable.AndExpressions(lqg.NoDeps, rqg.NoDeps),
    71  	}
    72  	if j.Predicate != nil {
    73  		err := newOp.collectPredicate(ctx, j.Predicate)
    74  		if err != nil {
    75  			return nil, rewrite.SameTree, err
    76  		}
    77  	}
    78  	return newOp, rewrite.NewTree, nil
    79  }
    80  
    81  func createOuterJoin(tableExpr *sqlparser.JoinTableExpr, lhs, rhs ops.Operator) (ops.Operator, error) {
    82  	if tableExpr.Join == sqlparser.RightJoinType {
    83  		lhs, rhs = rhs, lhs
    84  	}
    85  	predicate := tableExpr.Condition.On
    86  	sqlparser.RemoveKeyspaceFromColName(predicate)
    87  	return &Join{LHS: lhs, RHS: rhs, LeftJoin: true, Predicate: predicate}, nil
    88  }
    89  
    90  func createJoin(ctx *plancontext.PlanningContext, LHS, RHS ops.Operator) ops.Operator {
    91  	lqg, lok := LHS.(*QueryGraph)
    92  	rqg, rok := RHS.(*QueryGraph)
    93  	if lok && rok {
    94  		op := &QueryGraph{
    95  			Tables:     append(lqg.Tables, rqg.Tables...),
    96  			innerJoins: append(lqg.innerJoins, rqg.innerJoins...),
    97  			NoDeps:     ctx.SemTable.AndExpressions(lqg.NoDeps, rqg.NoDeps),
    98  		}
    99  		return op
   100  	}
   101  	return &Join{LHS: LHS, RHS: RHS}
   102  }
   103  
   104  func createInnerJoin(ctx *plancontext.PlanningContext, tableExpr *sqlparser.JoinTableExpr, lhs, rhs ops.Operator) (ops.Operator, error) {
   105  	op := createJoin(ctx, lhs, rhs)
   106  	pred := tableExpr.Condition.On
   107  	if pred != nil {
   108  		var err error
   109  		sqlparser.RemoveKeyspaceFromColName(pred)
   110  		op, err = op.AddPredicate(ctx, pred)
   111  		if err != nil {
   112  			return nil, err
   113  		}
   114  	}
   115  	return op, nil
   116  }
   117  
   118  func (j *Join) AddPredicate(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (ops.Operator, error) {
   119  	return AddPredicate(j, ctx, expr, false, newFilter)
   120  }
   121  
   122  var _ JoinOp = (*Join)(nil)
   123  
   124  func (j *Join) GetLHS() ops.Operator {
   125  	return j.LHS
   126  }
   127  
   128  func (j *Join) GetRHS() ops.Operator {
   129  	return j.RHS
   130  }
   131  
   132  func (j *Join) SetLHS(operator ops.Operator) {
   133  	j.LHS = operator
   134  }
   135  
   136  func (j *Join) SetRHS(operator ops.Operator) {
   137  	j.RHS = operator
   138  }
   139  
   140  func (j *Join) MakeInner() {
   141  	j.LeftJoin = false
   142  }
   143  
   144  func (j *Join) IsInner() bool {
   145  	return !j.LeftJoin
   146  }
   147  
   148  func (j *Join) AddJoinPredicate(ctx *plancontext.PlanningContext, expr sqlparser.Expr) error {
   149  	j.Predicate = ctx.SemTable.AndExpressions(j.Predicate, expr)
   150  	return nil
   151  }