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

     1  /*
     2  Copyright 2019 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/vt/sqlparser"
    23  )
    24  
    25  // jointab manages procurement and naming of join
    26  // variables across primitives.
    27  type jointab struct {
    28  	refs     map[*column]string
    29  	reserved *sqlparser.ReservedVars
    30  	varIndex int
    31  }
    32  
    33  // newJointab creates a new jointab for the current plan
    34  // being built. It also needs the current list of bind vars
    35  // used in the original query to make sure that the names
    36  // it generates don't collide with those already in use.
    37  func newJointab(reserved *sqlparser.ReservedVars) *jointab {
    38  	return &jointab{
    39  		refs:     make(map[*column]string),
    40  		reserved: reserved,
    41  	}
    42  }
    43  
    44  // Procure requests for the specified column from the plan
    45  // and returns the join var name for it.
    46  func (jt *jointab) Procure(plan logicalPlan, col *sqlparser.ColName, to int) string {
    47  	from, joinVar := jt.Lookup(col)
    48  	// If joinVar is empty, generate a unique name.
    49  	if joinVar == "" {
    50  		joinVar = jt.reserved.ReserveColName(col)
    51  		jt.refs[col.Metadata.(*column)] = joinVar
    52  	}
    53  	plan.SupplyVar(from, to, col, joinVar)
    54  	return joinVar
    55  }
    56  
    57  // GenerateSubqueryVars generates substitution variable names for
    58  // a subquery. It returns two names based on: __sq, __sq_has_values.
    59  // The appropriate names can be used for substitution
    60  // depending on the scenario.
    61  func (jt *jointab) GenerateSubqueryVars() (sq, hasValues string) {
    62  	for {
    63  		jt.varIndex++
    64  		var1 := fmt.Sprintf("__sq%d", jt.varIndex)
    65  		var2 := fmt.Sprintf("__sq_has_values%d", jt.varIndex)
    66  		if !jt.reserved.ReserveAll(var1, var2) {
    67  			continue
    68  		}
    69  		return var1, var2
    70  	}
    71  }
    72  
    73  // Lookup returns the order of the route that supplies the column and
    74  // the join var name if one has already been assigned for it.
    75  func (jt *jointab) Lookup(col *sqlparser.ColName) (order int, joinVar string) {
    76  	c := col.Metadata.(*column)
    77  	return c.Origin().Order(), jt.refs[c]
    78  }