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

     1  // Copyright 2019 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 opbench
    12  
    13  import (
    14  	"regexp"
    15  	"sort"
    16  	"strings"
    17  )
    18  
    19  // Spec defines a single parameterized Plan which we would like to
    20  // benchmark.
    21  // A Spec has "parameters", which are values that get substituted into
    22  // the Plan, and "inputs", which are the values from which the parameters
    23  // are derived. These might differ in cases like where a Spec
    24  // must scan tables of different widths, and the "input" is the width
    25  // of the table, and the "parameter" is the name of the table that is
    26  // scanned.
    27  type Spec struct {
    28  	// Name is the title of spec. It is what determines the filename of
    29  	// this spec's results.
    30  	Name string
    31  
    32  	// Plan is the parameterized exprgen Plan, with each parameter prefixed with
    33  	// a $.
    34  	Plan string
    35  
    36  	// Inputs is the set of possible inputs, along with a set of potential values
    37  	// for each. This allows enumerating all combinations.
    38  	Inputs []Options
    39  
    40  	// GetParam maps the name of a parameter to its value, given
    41  	// the configuration.
    42  	GetParam func(string, Configuration) string
    43  }
    44  
    45  // paramRegex matches parameters in a Plan (words prefixed with a $).
    46  var paramRegex = regexp.MustCompile(`\$[a-zA-Z_]+`)
    47  
    48  // getParams extracts all the $dollarsign prefixed parameters from the spec's
    49  // Plan, sorting and deduplicating them.
    50  func (s *Spec) getParams() []string {
    51  	paramRefs := paramRegex.FindAllString(s.Plan, -1)
    52  	// Sort them for deduplication.
    53  	sort.Strings(paramRefs)
    54  	result := make([]string, 0, len(paramRefs))
    55  	last := ""
    56  	for i := 0; i < len(paramRefs); i++ {
    57  		if last != paramRefs[i] {
    58  			// Get rid of the leading $.
    59  			next := paramRefs[i][1:]
    60  			result = append(result, next)
    61  			last = paramRefs[i]
    62  		}
    63  	}
    64  	return result
    65  }
    66  
    67  // InputNames returns a slice of the names of the inputs to the spec.
    68  func (s *Spec) InputNames() []string {
    69  	var result []string
    70  	for _, i := range s.Inputs {
    71  		result = append(result, i.Field)
    72  	}
    73  	return result
    74  }
    75  
    76  // FillInParams returns the Spec's Plan with parameters filled
    77  // in with respect to the given configuration.
    78  func (s *Spec) FillInParams(c Configuration) string {
    79  	// Replace all the parameters in the Plan with their values.
    80  	text := s.Plan
    81  	params := s.getParams()
    82  	for _, k := range params {
    83  		text = strings.Replace(text, "$"+k, s.GetParam(k, c), -1)
    84  	}
    85  
    86  	return text
    87  }