github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/norm/project_builder.go (about)

     1  // Copyright 2018 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package norm
    12  
    13  import (
    14  	"github.com/cockroachdb/cockroach/pkg/sql/opt"
    15  	"github.com/cockroachdb/cockroach/pkg/sql/opt/memo"
    16  )
    17  
    18  // projectBuilder is a helper for constructing a ProjectOp that augments an
    19  // input with new synthesized and passthrough columns. Sample usage:
    20  //
    21  //   var pb projectBuilder
    22  //   pb.init(c)
    23  //   e1 := pb.add(some expression)
    24  //   e2 := pb.add(some other expression)
    25  //   augmentedInput := pb.buildProject(input, passthrough)
    26  //   // e1 and e2 are VariableOp expressions, with input columns
    27  //   // produced by augmentedInput.
    28  //
    29  type projectBuilder struct {
    30  	f           *Factory
    31  	projections memo.ProjectionsExpr
    32  }
    33  
    34  func (pb *projectBuilder) init(f *Factory) {
    35  	pb.f = f
    36  }
    37  
    38  // empty returns true if there are no synthesized columns (and hence a
    39  // projection is not necessary).
    40  func (pb *projectBuilder) empty() bool {
    41  	return len(pb.projections) == 0
    42  }
    43  
    44  // add incorporates the given expression as a projection, unless the expression
    45  // is already a "bare" variable. Returns a bare variable expression referring to
    46  // the synthesized column.
    47  func (pb *projectBuilder) add(e opt.ScalarExpr) opt.ScalarExpr {
    48  	if v, ok := e.(*memo.VariableExpr); ok {
    49  		// The expression is a bare variable; we don't need to synthesize a column.
    50  		return v
    51  	}
    52  
    53  	newCol := pb.f.Metadata().AddColumn("", e.DataType())
    54  	pb.projections = append(pb.projections, pb.f.ConstructProjectionsItem(e, newCol))
    55  	return pb.f.ConstructVariable(newCol)
    56  }
    57  
    58  // buildProject creates the ProjectOp (if needed). The ProjectOp passes through
    59  // the given passthrough columns and adds any synthesized columns.
    60  func (pb *projectBuilder) buildProject(input memo.RelExpr, passthrough opt.ColSet) memo.RelExpr {
    61  	if pb.empty() {
    62  		// Avoid creating a Project that does nothing and just gets elided.
    63  		return input
    64  	}
    65  	return pb.f.ConstructProject(input, pb.projections, passthrough)
    66  }