vitess.io/vitess@v0.16.2/go/vt/vtgate/planbuilder/pullout_subquery.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  	"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 = (*pulloutSubquery)(nil)
    28  
    29  // pulloutSubquery is the logicalPlan for engine.PulloutSubquery.
    30  // This gets built if a subquery is not correlated and can
    31  // therefore can be pulled out and executed upfront.
    32  type pulloutSubquery struct {
    33  	order      int
    34  	subquery   logicalPlan
    35  	underlying logicalPlan
    36  	eSubquery  *engine.PulloutSubquery
    37  }
    38  
    39  // newPulloutSubquery builds a new pulloutSubquery.
    40  func newPulloutSubquery(opcode engine.PulloutOpcode, sqName, hasValues string, subquery logicalPlan) *pulloutSubquery {
    41  	return &pulloutSubquery{
    42  		subquery: subquery,
    43  		eSubquery: &engine.PulloutSubquery{
    44  			Opcode:         opcode,
    45  			SubqueryResult: sqName,
    46  			HasValues:      hasValues,
    47  		},
    48  	}
    49  }
    50  
    51  // setUnderlying sets the underlying primitive.
    52  func (ps *pulloutSubquery) setUnderlying(underlying logicalPlan) {
    53  	ps.underlying = underlying
    54  	ps.underlying.Reorder(ps.subquery.Order())
    55  	ps.order = ps.underlying.Order() + 1
    56  }
    57  
    58  // Order implements the logicalPlan interface
    59  func (ps *pulloutSubquery) Order() int {
    60  	return ps.order
    61  }
    62  
    63  // Reorder implements the logicalPlan interface
    64  func (ps *pulloutSubquery) Reorder(order int) {
    65  	ps.subquery.Reorder(order)
    66  	ps.underlying.Reorder(ps.subquery.Order())
    67  	ps.order = ps.underlying.Order() + 1
    68  }
    69  
    70  // Primitive implements the logicalPlan interface
    71  func (ps *pulloutSubquery) Primitive() engine.Primitive {
    72  	ps.eSubquery.Subquery = ps.subquery.Primitive()
    73  	ps.eSubquery.Underlying = ps.underlying.Primitive()
    74  	return ps.eSubquery
    75  }
    76  
    77  // ResultColumns implements the logicalPlan interface
    78  func (ps *pulloutSubquery) ResultColumns() []*resultColumn {
    79  	return ps.underlying.ResultColumns()
    80  }
    81  
    82  // Wireup implements the logicalPlan interface
    83  func (ps *pulloutSubquery) Wireup(plan logicalPlan, jt *jointab) error {
    84  	if err := ps.underlying.Wireup(plan, jt); err != nil {
    85  		return err
    86  	}
    87  	return ps.subquery.Wireup(plan, jt)
    88  }
    89  
    90  // Wireup2 implements the logicalPlan interface
    91  func (ps *pulloutSubquery) WireupGen4(ctx *plancontext.PlanningContext) error {
    92  	if err := ps.underlying.WireupGen4(ctx); err != nil {
    93  		return err
    94  	}
    95  	return ps.subquery.WireupGen4(ctx)
    96  }
    97  
    98  // SupplyVar implements the logicalPlan interface
    99  func (ps *pulloutSubquery) SupplyVar(from, to int, col *sqlparser.ColName, varname string) {
   100  	if from <= ps.subquery.Order() {
   101  		ps.subquery.SupplyVar(from, to, col, varname)
   102  		return
   103  	}
   104  	ps.underlying.SupplyVar(from, to, col, varname)
   105  }
   106  
   107  // SupplyCol implements the logicalPlan interface
   108  func (ps *pulloutSubquery) SupplyCol(col *sqlparser.ColName) (rc *resultColumn, colNumber int) {
   109  	return ps.underlying.SupplyCol(col)
   110  }
   111  
   112  // SupplyWeightString implements the logicalPlan interface
   113  func (ps *pulloutSubquery) SupplyWeightString(colNumber int, alsoAddToGroupBy bool) (weightcolNumber int, err error) {
   114  	return ps.underlying.SupplyWeightString(colNumber, alsoAddToGroupBy)
   115  }
   116  
   117  // Rewrite implements the logicalPlan interface
   118  func (ps *pulloutSubquery) Rewrite(inputs ...logicalPlan) error {
   119  	if len(inputs) != 2 {
   120  		return vterrors.VT13001("pulloutSubquery: wrong number of inputs")
   121  	}
   122  	ps.underlying = inputs[0]
   123  	ps.subquery = inputs[1]
   124  	return nil
   125  }
   126  
   127  // ContainsTables implements the logicalPlan interface
   128  func (ps *pulloutSubquery) ContainsTables() semantics.TableSet {
   129  	return ps.underlying.ContainsTables().Merge(ps.subquery.ContainsTables())
   130  }
   131  
   132  // Inputs implements the logicalPlan interface
   133  func (ps *pulloutSubquery) Inputs() []logicalPlan {
   134  	return []logicalPlan{ps.underlying, ps.subquery}
   135  }
   136  
   137  // OutputColumns implements the logicalPlan interface
   138  func (ps *pulloutSubquery) OutputColumns() []sqlparser.SelectExpr {
   139  	return ps.underlying.OutputColumns()
   140  }